1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.palette;
18
19 import java.awt.image.BufferedImage;
20
21 import org.apache.commons.imaging.ImagingException;
22
23
24
25
26 public final class Dithering {
27 private static int adjustPixel(final int argb, final int errA, final int errR, final int errG, final int errB, final int mul) {
28 int a = argb >> 24 & 0xff;
29 int r = argb >> 16 & 0xff;
30 int g = argb >> 8 & 0xff;
31 int b = argb & 0xff;
32
33 a += errA * mul / 16;
34 r += errR * mul / 16;
35 g += errG * mul / 16;
36 b += errB * mul / 16;
37
38 if (a < 0) {
39 a = 0;
40 } else if (a > 0xff) {
41 a = 0xff;
42 }
43 if (r < 0) {
44 r = 0;
45 } else if (r > 0xff) {
46 r = 0xff;
47 }
48 if (g < 0) {
49 g = 0;
50 } else if (g > 0xff) {
51 g = 0xff;
52 }
53 if (b < 0) {
54 b = 0;
55 } else if (b > 0xff) {
56 b = 0xff;
57 }
58
59 return a << 24 | r << 16 | g << 8 | b;
60 }
61
62
63
64
65
66
67
68
69
70 public static void applyFloydSteinbergDithering(final BufferedImage image, final Palette palette) throws ImagingException {
71 for (int y = 0; y < image.getHeight(); y++) {
72 for (int x = 0; x < image.getWidth(); x++) {
73 final int argb = image.getRGB(x, y);
74 final int index = palette.getPaletteIndex(argb);
75 final int nextArgb = palette.getEntry(index);
76 image.setRGB(x, y, nextArgb);
77
78 final int a = argb >> 24 & 0xff;
79 final int r = argb >> 16 & 0xff;
80 final int g = argb >> 8 & 0xff;
81 final int b = argb & 0xff;
82
83 final int na = nextArgb >> 24 & 0xff;
84 final int nr = nextArgb >> 16 & 0xff;
85 final int ng = nextArgb >> 8 & 0xff;
86 final int nb = nextArgb & 0xff;
87
88 final int errA = a - na;
89 final int errR = r - nr;
90 final int errG = g - ng;
91 final int errB = b - nb;
92
93 if (x + 1 < image.getWidth()) {
94 int update = adjustPixel(image.getRGB(x + 1, y), errA, errR, errG, errB, 7);
95 image.setRGB(x + 1, y, update);
96 if (y + 1 < image.getHeight()) {
97 update = adjustPixel(image.getRGB(x + 1, y + 1), errA, errR, errG, errB, 1);
98 image.setRGB(x + 1, y + 1, update);
99 }
100 }
101 if (y + 1 < image.getHeight()) {
102 int update = adjustPixel(image.getRGB(x, y + 1), errA, errR, errG, errB, 5);
103 image.setRGB(x, y + 1, update);
104 if (x - 1 >= 0) {
105 update = adjustPixel(image.getRGB(x - 1, y + 1), errA, errR, errG, errB, 3);
106 image.setRGB(x - 1, y + 1, update);
107 }
108
109 }
110 }
111 }
112 }
113
114 private Dithering() {
115
116 }
117 }