Floyd-Steinberg抖動算法簡直量身爲價籤這種低顏色呈現設備準備的。因爲價籤的墨水屏可以呈現的色彩很是有限,根據型號不一樣,有的只能顯示黑白,有的只能顯示黑白紅,有的只能顯示黑白黃,因此對於一張普通圖片,須要將其轉換爲兩色或者三色才能比較好地在價簽上展現出來。java
核心代碼以下:算法
public class BMPConverter { public static RGBTriple[] getPalette(int deviceType) { final RGBTriple[] palette; if (deviceType == 0) { //黑白價籤 palette = new RGBTriple[]{ new RGBTriple(0, 0, 0), new RGBTriple(255, 255, 255) }; } else if (deviceType == 1) { //黑白紅價籤 palette = new RGBTriple[]{ new RGBTriple(0, 0, 0), new RGBTriple(255, 255, 255), new RGBTriple(255, 0, 0) }; } else { //黑白黃價籤 palette = new RGBTriple[]{ new RGBTriple(0, 0, 0), new RGBTriple(255, 255, 255), new RGBTriple(255, 255, 0) }; } return palette; } public static byte[][] floydSteinbergDither(RGBTriple[][] image, RGBTriple[] palette) { byte[][] result = new byte[image.length][image[0].length]; for (int y = 0; y < image.length; y++) { for (int x = 0; x < image[y].length; x++) { RGBTriple currentPixel = image[y][x]; byte index = findNearestColor(currentPixel, palette); result[y][x] = index; for (int i = 0; i < 3; i++) { int error = (currentPixel.channels[i] & 0xff) - (palette[index].channels[i] & 0xff); if (x + 1 < image[0].length) { image[y+0][x+1].channels[i] = plus_truncate_uchar(image[y+0][x+1].channels[i], (error*7) >> 4); } if (y + 1 < image.length) { if (x - 1 > 0) { image[y+1][x-1].channels[i] = plus_truncate_uchar(image[y+1][x-1].channels[i], (error*3) >> 4); } image[y+1][x+0].channels[i] = plus_truncate_uchar(image[y+1][x+0].channels[i], (error*5) >> 4); if (x + 1 < image[0].length) { image[y+1][x+1].channels[i] = plus_truncate_uchar(image[y+1][x+1].channels[i], (error*1) >> 4); } } } } } return result; } private static byte plus_truncate_uchar(byte a, int b) { if ((a & 0xff) + b < 0) { return 0; } else if ((a & 0xff) + b > 255) { return (byte) 255; } else { return (byte) (a + b); } } 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}; } }
原始圖片:rest
黑白紅價籤的顯示效果:code
黑白價籤的顯示效果:blog