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