package com.kreative.paint.material.dither; import java.awt.image.BufferedImage; public class DiffusionDitherAlgorithm extends MatrixDitherAlgorithm { public static final DiffusionDitherAlgorithm THRESHOLD = new DiffusionDitherAlgorithm(1, 1, 1, "Threshold"); public static final DiffusionDitherAlgorithm FLOYD_STEINBERG = new DiffusionDitherAlgorithm(2, 3, 16, "Floyd-Steinberg"); static { THRESHOLD.values[0][0] = 0; FLOYD_STEINBERG.values[0][0] = 0; FLOYD_STEINBERG.values[0][1] = 0; FLOYD_STEINBERG.values[0][2] = 7; FLOYD_STEINBERG.values[1][0] = 3; FLOYD_STEINBERG.values[1][1] = 5; FLOYD_STEINBERG.values[1][2] = 1; } public DiffusionDitherAlgorithm(int rows, int columns, int denominator, String name) { super(rows, columns, denominator, name); } public DiffusionDitherAlgorithm(int rows, int columns, int denominator, String text, String name) { super(rows, columns, denominator, text, name); } @Override public void dither(BufferedImage image, int[] colors) { int[] ca = new int[colors.length]; int[] cr = new int[colors.length]; int[] cg = new int[colors.length]; int[] cb = new int[colors.length]; for (int i = 0; i < colors.length; i++) { ca[i] = (colors[i] >> 24) & 0xFF; cr[i] = (colors[i] >> 16) & 0xFF; cg[i] = (colors[i] >> 8) & 0xFF; cb[i] = (colors[i] >> 0) & 0xFF; } int h = image.getHeight(); int w = image.getWidth(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { int o = image.getRGB(x, y); int oa = (o >> 24) & 0xFF; int or = (o >> 16) & 0xFF; int og = (o >> 8) & 0xFF; int ob = (o >> 0) & 0xFF; int m = 0; int mda = 256; int mdr = 256; int mdg = 256; int mdb = 256; int md = 262144; for (int i = 0; i < colors.length; i++) { int cda = oa - ca[i]; int cdr = or - cr[i]; int cdg = og - cg[i]; int cdb = ob - cb[i]; int cd = cda*cda + cdr*cdr + cdg*cdg + cdb*cdb; if (cd < md) { m = colors[i]; mda = cda; mdr = cdr; mdg = cdg; mdb = cdb; md = cd; } } image.setRGB(x, y, m); for (int k = 0; k < rows; k++) { if (y + k < h) { for (int i = 0, j = -columns/2; i < columns; i++, j++) { if (x + j >= 0 && x + j < w && values[k][i] != 0) { int p = image.getRGB(x + j, y + k); int pa = (p >> 24) & 0xFF; int pr = (p >> 16) & 0xFF; int pg = (p >> 8) & 0xFF; int pb = (p >> 0) & 0xFF; int aa = r255(pa + mda * values[k][i] / denominator); int ar = r255(pr + mdr * values[k][i] / denominator); int ag = r255(pg + mdg * values[k][i] / denominator); int ab = r255(pb + mdb * values[k][i] / denominator); int a = (aa << 24) | (ar << 16) | (ag << 8) | ab; image.setRGB(x + j, y + k, a); } } } } } } } private static int r255(int v) { if (v < 0) return 0; if (v > 255) return 255; return v; } }