/* * Copyright 2015 Daniel Dittmar * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package dan.dit.whatsthat.util.mosaic.matching; import android.util.SparseArray; import dan.dit.whatsthat.util.image.ColorMetric; import dan.dit.whatsthat.util.mosaic.data.MosaicTile; /** * This class models an abstract TileMatcher which can with a certain * accuracy give the best matching mosaic tile to a given rgb color. * @author Daniel * */ public abstract class TileMatcher<S> { ColorMetric mColorMetric; private SparseArray<MosaicTile<S>> mBestMatches; public void setHashMatches(boolean hashMatches) { if (hashMatches && mBestMatches == null) { mBestMatches = new SparseArray<>(); } else if (!hashMatches) { mBestMatches = null; } } void resetHashMatches() { if (mBestMatches != null) { setHashMatches(false); setHashMatches(true); } } private MosaicTile<S> getBestMatchHashed(int color) { if (mBestMatches == null) { throw new IllegalStateException("Hash not used!"); } MosaicTile<S> match = mBestMatches.get(color); if (match != null) { return match; } match = calculateBestMatch(color); mBestMatches.put(color, match); return match; } /** * If the TileMatcher uses the alpha value of the rgb values for matching. */ boolean useAlpha; public void setUseAlpha(boolean useAlpha) { this.useAlpha = useAlpha; } /** * Creates a new tile matcher, the given flag simply signals * if the implementing tile matcher uses alpha for matching. * @param useAlpha If the matcher uses the alpha value for matching. * @param metric The color metric to use, if null defaults to Euclid2. */ TileMatcher(boolean useAlpha, ColorMetric metric) { this.useAlpha = useAlpha; mColorMetric = metric == null ? ColorMetric.Euclid2.INSTANCE : metric; } /** * Returns the best matching MosaicTile for the given rgb color. * The result and speed of this calculation highly depends on the tile matcher. * Higher accuracy usually returns better results at a cost of speed. * @param withRGB The rgb to match. If the alpha value is used can be requested by * usesAlpha(). * @return The best matching mosaic tile. If the tile matcher has tile data * this will never be <code>null</code>. */ protected abstract MosaicTile<S> calculateBestMatch(int withRGB); public MosaicTile<S> getBestMatch(int color) { if (mBestMatches == null) { return calculateBestMatch(color); } return getBestMatchHashed(color); } /** * Returns the accuracy of the best match. * @return A value from <code>0</code> (bad accuracy) to * <code>1</code> (best result). */ public abstract double getAccuracy(); public abstract boolean setAccuracy(double accuracy); /** * Removes one occurance of the given MosaicTile from the TileMatcher. This operation can * be performed during matching and is useful to eleminate tiles which reference * an invalid image file (which got deleted or is unaccesable) or MosaicTiles that should not be used * anymore for any other reason. * @param toRemove The MosaicTile to remove. * @return <code>true</code> only if the tile was contained in the set of MosaicTiles * of this matcher and then removed. */ public abstract boolean removeTile(MosaicTile<S> toRemove); /** * Returns the amount of MosaicTiles used by this TileMatcher. * @return The amount of MosaicTiles used by this TileMatcher. */ public abstract int getUsedTilesCount(); /** * Returns <code>true</code> if calculateBestMatch() takes the alpha * value of the rgb color codes into account. * @return If this matcher uses alpha. */ public boolean usesAlpha() { return this.useAlpha; } public abstract void setColorMetric(ColorMetric metric); }