找了很久Atkinson的Java實現,始終沒找到現成的,只有一個pde的參考:html
https://github.com/danielepiccone/dithering_algorithms/blob/master/atkinson_color/atkinson_color.pdejava
用Java從新寫了一下,核心代碼如:git
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]; } }
顯示的效果如:github