找了好久Atkinson的Java实现,始终没找到现成的,只有一个pde的参考:
https://github.com/danielepiccone/dithering_algorithms/blob/master/atkinson_color/atkinson_color.pde
用Java重新写了一下,核心代码如:
public class BMPConverter {
public static byte[][] atkinsonDither(RGBTriple[][] image, RGBTriple[] palette) {
int s = 1;
byte[][] result = new byte[image.length][image[0].length];
// Scan image
for (int x = s; x < image.length-2*s; x+=s) {
for (int y = 0; y < image[x].length-2*s; y+=s) {
// Calculate pixel
RGBTriple oldpixel = image[x][y];
byte index = findNearestColor(oldpixel, palette);
RGBTriple newpixel = palette[index];
RGBTriple quant_error = new RGBTriple(oldpixel.getRed() - newpixel.getRed(), oldpixel.getGreen() - newpixel.getGreen(), oldpixel.getBlue() - newpixel.getBlue());
result[x][y] = index;
// Atkinson algorithm http://verlagmartinkoch.at/software/dither/index.html
RGBTriple s1 = image[x+s][y];
image[x+s][y] = adjustRGB(s1, quant_error);
RGBTriple s2 = image[x-s][y+s];
image[x-s][y+s] = adjustRGB(s2, quant_error);
RGBTriple s3 = image[x][y+s];
image[x][y+s] = adjustRGB(s3, quant_error);
RGBTriple s4 = image[x+s][y+s];
image[x+s][y+s] = adjustRGB(s4, quant_error);
RGBTriple s5 = image[x+2*s][y];
image[x+2*s][y] = adjustRGB(s5, quant_error);
RGBTriple s6 = image[x][y+2*s];
image[x][y+2*s] = adjustRGB(s6, quant_error);
}
}
return result;
}
private static RGBTriple adjustRGB(RGBTriple originalRGB, RGBTriple error) {
return new RGBTriple((new Double(originalRGB.getRed() + 1.0/8 * error.getRed())).intValue(),
(new Double(originalRGB.getGreen() + 1.0/8 * error.getGreen())).intValue(),
(new Double(originalRGB.getBlue() + 1.0/8 * error.getBlue()).intValue()));
}
private static byte findNearestColor(RGBTriple color, RGBTriple[] palette) {
int minDistanceSquared = 255 * 255 + 255 * 255 + 255 * 255 + 1;
byte bestIndex = 0;
for (byte i = 0; i < palette.length; i++) {
int Rdiff = (color.channels[0] & 0xff) - (palette[i].channels[0] & 0xff);
int Gdiff = (color.channels[1] & 0xff) - (palette[i].channels[1] & 0xff);
int Bdiff = (color.channels[2] & 0xff) - (palette[i].channels[2] & 0xff);
int distanceSquared = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff;
if (distanceSquared < minDistanceSquared) {
minDistanceSquared = distanceSquared;
bestIndex = i;
}
}
return bestIndex;
}
}
public class RGBTriple {
public final byte[] channels;
public RGBTriple() {
channels = new byte[3];
}
public RGBTriple(int R, int G, int B) {
channels = new byte[]{(byte) R, (byte) G, (byte) B};
}
public byte getRed() {
return channels[0];
}
public byte getGreen() {
return channels[1];
}
public byte getBlue() {
return channels[2];
}
}
显示的效果如: