/* JAI-Ext - OpenSource Java Advanced Image Extensions Library
* http://www.geo-solutions.it/
* Copyright 2014 GeoSolutions
* 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 it.geosolutions.jaiext.colorindexer;
import java.awt.image.IndexColorModel;
/**
* Maps every given color to the closest color in the palette, by exaustive search
*
* @author Andrea Aime - GeoSolutions
*/
public class SimpleColorIndexer implements ColorIndexer {
/** Input colors */
byte[][] colors;
public SimpleColorIndexer(byte[][] colors) {
this.colors = colors;
}
public SimpleColorIndexer(IndexColorModel icm) {
this.colors = new byte[4][icm.getMapSize()];
icm.getReds(colors[0]);
icm.getGreens(colors[1]);
icm.getBlues(colors[2]);
icm.getAlphas(colors[3]);
}
public IndexColorModel toIndexColorModel() {
int bits = (int) Math.ceil(Math.log(colors[0].length) / Math.log(2));
if (bits == 0) {
bits = 1;
}
return new IndexColorModel(bits, colors[0].length, colors[0], colors[1], colors[2],
colors[3]);
}
public int getClosestIndex(int r, int g, int b, int a) {
// find the closest color
int idx = 0;
int distance = Integer.MAX_VALUE;
for (int i = 0; i < colors[0].length; i++) {
int dr = r - (colors[0][i] & 0xFF);
int dg = g - (colors[1][i] & 0xFF);
int db = b - (colors[2][i] & 0xFF);
int da = a - (colors[3][i] & 0xFF);
/*
* This is a simple color distance formula, we might consider checking into the LAB color space, though the conversions would take some
* more time: http://en.wikipedia.org/wiki/L*a*b* http://www.easyrgb.com/index.php?X=MATH
*/
int d = 3 * dr * dr + 4 * dg * dg + 2 * db * db + 4 * da * da;
if (d < distance) {
distance = d;
idx = i;
if (distance == 0) {
break;
}
}
}
return idx;
}
}