/*
* 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.image;
import android.graphics.Color;
import java.util.ArrayList;
import java.util.List;
/**
* Created by daniel on 03.07.15.
*/
public abstract class ColorMetric {
public abstract double getDistance(int color1, int color2, boolean useAlpha);
public abstract double maxValue(boolean useAlpha);
public static List<ColorMetric> makeAll() {
List<ColorMetric> list = new ArrayList<>(5);
list.add(Euclid2.INSTANCE);
list.add(Absolute.INSTANCE);
list.add(Greyness.INSTANCE);
list.add(AbsoluteRed.INSTANCE);
list.add(AbsoluteGreen.INSTANCE);
list.add(AbsoluteBlue.INSTANCE);
list.add(Brightness.INSTANCE);
return list;
}
public static class Euclid2 extends ColorMetric { /**
* This value indicates the greatest possible value for two colors
* if alpha is not used. Equal to 3*255*255.
*/
private static final double GREATEST_VALUE_NO_ALPHA = 3 * 255 * 255;
/** This value indicates the greatest possible value for two colors
* if alpha is used. Equal to 4*255*255.
*/
private static final double GREATEST_VALUE_ALPHA = 4 * 255 * 255;
public static final Euclid2 INSTANCE = new Euclid2();
private Euclid2() {}
@Override
public double getDistance(int color1, int color2, boolean useAlpha) {
int result = 0;
int currColValue1;
int currColValue2;
currColValue1 = Color.red(color1);
currColValue2 = Color.red(color2);
result += (currColValue1 - currColValue2) * (currColValue1 - currColValue2);
currColValue1 = Color.green(color1);
currColValue2 = Color.green(color2);
result += (currColValue1 - currColValue2) * (currColValue1 - currColValue2);
currColValue1 = Color.blue(color1);
currColValue2 = Color.blue(color2);
result += (currColValue1 - currColValue2) * (currColValue1 - currColValue2);
if (useAlpha) {
currColValue1 = Color.alpha(color1);
currColValue2 = Color.alpha(color2);
result += (currColValue1 - currColValue2) * (currColValue1 - currColValue2);
}
return result;
}
@Override
public double maxValue(boolean useAlpha) {
return useAlpha ? GREATEST_VALUE_ALPHA : GREATEST_VALUE_NO_ALPHA;
}
@Override
public String toString() {
return "Euclid2";
}
}
public static class Absolute extends ColorMetric {
public static final Absolute INSTANCE = new Absolute();
private static final double GREATEST_VALUE_NO_ALPHA = 3 * 255;
private static final double GREATEST_VALUE_ALPHA = 4 * 255;
private Absolute() {}
@Override
public double getDistance(int color1, int color2, boolean useAlpha) {
return Math.abs(Color.red(color1) - Color.red(color2))
+ Math.abs(Color.green(color1) - Color.green(color2))
+ Math.abs(Color.blue(color1) - Color.blue(color2))
+ (useAlpha ? Math.abs(Color.alpha(color1) - Color.alpha(color2)) : 0);
}
@Override
public double maxValue(boolean useAlpha) {
return useAlpha ? GREATEST_VALUE_ALPHA : GREATEST_VALUE_NO_ALPHA;
}
@Override
public String toString() {
return "Absolute";
}
}
public static class Greyness extends ColorMetric {
public static final Greyness INSTANCE = new Greyness();
private Greyness() {}
@Override
public double getDistance(int color1, int color2, boolean useAlpha) {
return Math.abs(ColorAnalysisUtil.getGreyness(Color.red(color1), Color.green(color1), Color.blue(color1))
- ColorAnalysisUtil.getGreyness(Color.red(color2), Color.green(color2), Color.blue(color2)));
}
@Override
public double maxValue(boolean useAlpha) {
return 1.0;
}
@Override
public String toString() {
return "Greyness";
}
}
public static class AbsoluteRed extends ColorMetric {
public static final AbsoluteRed INSTANCE = new AbsoluteRed();
private AbsoluteRed() {}
@Override
public double getDistance(int color1, int color2, boolean useAlpha) {
return Math.abs(Color.red(color1) - Color.red(color2)) + (useAlpha ? Math.abs(Color.alpha(color1) - Color.alpha(color2)) : 0);
}
@Override
public double maxValue(boolean useAlpha) {
return useAlpha ? 255 * 2 : 255;
}
@Override
public String toString() {
return "AbsolutRed";
}
}
public static class AbsoluteGreen extends ColorMetric {
public static final AbsoluteGreen INSTANCE = new AbsoluteGreen();
private AbsoluteGreen() {}
@Override
public double getDistance(int color1, int color2, boolean useAlpha) {
return Math.abs(Color.green(color1) - Color.green(color2)) + (useAlpha ? Math.abs(Color.alpha(color1) - Color.alpha(color2)) : 0);
}
@Override
public double maxValue(boolean useAlpha) {
return useAlpha ? 255 * 2 : 255;
}
@Override
public String toString() {
return "AbsolutGreen";
}
}
public static class AbsoluteBlue extends ColorMetric {
public static final AbsoluteBlue INSTANCE = new AbsoluteBlue();
private AbsoluteBlue() {}
@Override
public double getDistance(int color1, int color2, boolean useAlpha) {
return Math.abs(Color.blue(color1) - Color.blue(color2)) + (useAlpha ? Math.abs(Color.alpha(color1) - Color.alpha(color2)) : 0);
}
@Override
public double maxValue(boolean useAlpha) {
return useAlpha ? 255 * 2 : 255;
}
@Override
public String toString() {
return "AbsolutBlue";
}
}
public static class Brightness extends ColorMetric {
public static final Brightness INSTANCE = new Brightness();
private Brightness() {}
@Override
public double getDistance(int color1, int color2, boolean useAlpha) {
if (useAlpha) {
return Math.abs(ColorAnalysisUtil.getBrightnessNoAlpha(color1) - ColorAnalysisUtil.getBrightnessNoAlpha(color2));
} else {
return Math.abs(ColorAnalysisUtil.getBrightnessWithAlpha(color1) - ColorAnalysisUtil.getBrightnessWithAlpha(color2));
}
}
@Override
public double maxValue(boolean useAlpha) {
return 1.0;
}
@Override
public String toString() {
return "Brightness";
}
}
}