001/*
002Copyright 2006 Jerry Huxtable
003
004Licensed under the Apache License, Version 2.0 (the "License");
005you may not use this file except in compliance with the License.
006You may obtain a copy of the License at
007
008   http://www.apache.org/licenses/LICENSE-2.0
009
010Unless required by applicable law or agreed to in writing, software
011distributed under the License is distributed on an "AS IS" BASIS,
012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013See the License for the specific language governing permissions and
014limitations under the License.
015*/
016
017package com.jhlabs.image;
018
019import java.awt.*;
020import java.awt.image.*;
021
022/**
023 * A filter which performs ordered dithering on an image.
024 */
025public class DitherFilter extends PointFilter {
026        
027        /**
028     * 2x2 magic square.
029     */
030        protected final static int[] ditherMagic2x2Matrix = {
031                 0, 2,
032                 3, 1
033        };
034
035        /**
036     * 4x4 magic square.
037     */
038        protected final static int[] ditherMagic4x4Matrix = {
039                 0, 14,  3, 13,
040                11,  5,  8,  6,
041                12,  2, 15,  1,
042                 7,  9,  4, 10
043        };
044
045        /**
046     * 4x4 ordered dither.
047     */
048        public final static int[] ditherOrdered4x4Matrix = {
049                 0,  8,  2, 10,
050                12,  4, 14,  6,
051                 3, 11,  1,  9,
052                15,  7, 13,  5
053        };
054
055        /**
056     * 4x4 lines.
057     */
058        public final static int[] ditherLines4x4Matrix = {
059                 0,  1,  2,  3,
060                 4,  5,  6,  7,
061                 8,  9, 10, 11,
062                12, 13, 14, 15
063        };
064
065        /**
066     * 6x6 90 degree halftone.
067     */
068        public final static int[] dither90Halftone6x6Matrix = {
069                29, 18, 12, 19, 30, 34,
070                17,  7,  4,  8, 20, 28,
071                11,  3,  0,  1,  9, 27,
072                16,  6,  2,  5, 13, 26,
073                25, 15, 10, 14, 21, 31,
074                33, 25, 24, 23, 33, 36
075        };
076
077        /*
078         * The following dithering matrices are taken from "Digital Halftoning" 
079         * by Robert Ulichney, MIT Press, ISBN 0-262-21009-6.
080         */
081
082        /**
083     * Order-6 ordered dither.
084     */
085        public final static int[] ditherOrdered6x6Matrix = {
086                 1, 59, 15, 55,  2, 56, 12, 52,
087                33, 17, 47, 31, 34, 18, 44, 28,
088                 9, 49,  5, 63, 10, 50,  6, 60,
089                41, 25, 37, 21, 42, 26, 38, 22,
090                 3, 57, 13, 53,  0, 58, 14, 54,
091                35, 19, 45, 29, 32, 16, 46, 30,
092                11, 51,  7, 61,  8, 48,  4, 62,
093                43, 27, 39, 23, 40, 24, 36, 20 
094        };
095
096        /**
097     * Order-8 ordered dither.
098     */
099        public final static int[] ditherOrdered8x8Matrix = {
100                  1,235, 59,219, 15,231, 55,215,  2,232, 56,216, 12,228, 52,212,
101                129, 65,187,123,143, 79,183,119,130, 66,184,120,140, 76,180,116,
102                 33,193, 17,251, 47,207, 31,247, 34,194, 18,248, 44,204, 28,244,
103                161, 97,145, 81,175,111,159, 95,162, 98,146, 82,172,108,156, 92,
104                  9,225, 49,209,  5,239, 63,223, 10,226, 50,210,  6,236, 60,220,
105                137, 73,177,113,133, 69,191,127,138, 74,178,114,134, 70,188,124,
106                 41,201, 25,241, 37,197, 21,255, 42,202, 26,242, 38,198, 22,252,
107                169,105,153, 89,165,101,149, 85,170,106,154, 90,166,102,150, 86,
108                  3,233, 57,217, 13,229, 53,213,  0,234, 58,218, 14,230, 54,214,
109                131, 67,185,121,141, 77,181,117,128, 64,186,122,142, 78,182,118,
110                 35,195, 19,249, 45,205, 29,245, 32,192, 16,250, 46,206, 30,246,
111                163, 99,147, 83,173,109,157, 93,160, 96,144, 80,174,110,158, 94,
112                 11,227, 51,211,  7,237, 61,221,  8,224, 48,208,  4,238, 62,222,
113                139, 75,179,115,135, 71,189,125,136, 72,176,112,132, 68,190,126,
114                 43,203, 27,243, 39,199, 23,253, 40,200, 24,240, 36,196, 20,254,
115                171,107,155, 91,167,103,151, 87,168,104,152, 88,164,100,148, 84 };
116
117        /**
118     * Order-3 clustered dither.
119     */
120        public final static int[] ditherCluster3Matrix = {
121                 9,11,10, 8, 6, 7,
122                12,17,16, 5, 0, 1,
123                13,14,15, 4, 3, 2,
124                 8, 6, 7, 9,11,10,
125                 5, 0, 1,12,17,16,
126                 4, 3, 2,13,14,15 };
127
128        /**
129     * Order-4 clustered dither.
130     */
131        public final static int[] ditherCluster4Matrix = {
132                18,20,19,16,13,11,12,15,
133                27,28,29,22, 4, 3, 2, 9,
134                26,31,30,21, 5, 0, 1,10,
135                23,25,24,17, 8, 6, 7,14,
136                13,11,12,15,18,20,19,16,
137                 4, 3, 2, 9,27,28,29,22,
138                 5, 0, 1,10,26,31,30,21,
139                 8, 6, 7,14,23,25,24,17 };
140
141        /**
142     * Order-8 clustered dither.
143     */
144        public final static int[] ditherCluster8Matrix = {
145                 64, 69, 77, 87, 86, 76, 68, 67, 63, 58, 50, 40, 41, 51, 59, 60,
146                 70, 94,100,109,108, 99, 93, 75, 57, 33, 27, 18, 19, 28, 34, 52,
147                 78,101,114,116,115,112, 98, 83, 49, 26, 13, 11, 12, 15, 29, 44,
148                 88,110,123,124,125,118,107, 85, 39, 17,  4,  3,  2,  9, 20, 42,
149                 89,111,122,127,126,117,106, 84, 38, 16,  5,  0,  1, 10, 21, 43,
150                 79,102,119,121,120,113, 97, 82, 48, 25,  8,  6,  7, 14, 30, 45,
151                 71, 95,103,104,105, 96, 92, 74, 56, 32, 24, 23, 22, 31, 35, 53,
152                 65, 72, 80, 90, 91, 81, 73, 66, 62, 55, 47, 37, 36, 46, 54, 61,
153                 63, 58, 50, 40, 41, 51, 59, 60, 64, 69, 77, 87, 86, 76, 68, 67,
154                 57, 33, 27, 18, 19, 28, 34, 52, 70, 94,100,109,108, 99, 93, 75,
155                 49, 26, 13, 11, 12, 15, 29, 44, 78,101,114,116,115,112, 98, 83,
156                 39, 17,  4,  3,  2,  9, 20, 42, 88,110,123,124,125,118,107, 85,
157                 38, 16,  5,  0,  1, 10, 21, 43, 89,111,122,127,126,117,106, 84,
158                 48, 25,  8,  6,  7, 14, 30, 45, 79,102,119,121,120,113, 97, 82,
159                 56, 32, 24, 23, 22, 31, 35, 53, 71, 95,103,104,105, 96, 92, 74,
160                 62, 55, 47, 37, 36, 46, 54, 61, 65, 72, 80, 90, 91, 81, 73, 66 };
161
162        private int[] matrix;
163        private int rows, cols, levels;
164        private int[] mod;
165        private int[] div;
166        private int[] map;
167        private boolean colorDither;
168        private boolean initialized = false;
169
170        /**
171     * Constuct a DitherFilter.
172     */
173    public DitherFilter() {
174                rows = 2;
175                cols = 2;
176                matrix = ditherMagic4x4Matrix;
177                levels = 6;
178                colorDither = true;
179        }
180        
181        /**
182         * Set the dither matrix.
183         * @param matrix the dither matrix
184     * @see #getMatrix
185         */
186        public void setMatrix(int[] matrix) {
187                this.matrix = matrix;
188        }
189
190        /**
191         * Get the dither matrix.
192         * @return the dither matrix
193     * @see #setMatrix
194         */
195        public int[] getMatrix() {
196                return matrix;
197        }
198
199        /**
200         * Set the number of dither levels.
201         * @param levels the number of levels
202     * @see #getLevels
203         */
204        public void setLevels(int levels) {
205                this.levels = levels;
206        }
207
208        /**
209         * Get the number of dither levels.
210         * @return the number of levels
211     * @see #setLevels
212         */
213        public int getLevels() {
214                return levels;
215        }
216
217        /**
218         * Set whether to use a color dither.
219         * @param colorDither whether to use a color dither
220     * @see #getColorDither
221         */
222        public void setColorDither(boolean colorDither) {
223                this.colorDither = colorDither;
224        }
225
226        /**
227         * Get whether to use a color dither.
228         * @return whether to use a color dither
229     * @see #getColorDither
230         */
231        public boolean getColorDither() {
232                return colorDither;
233        }
234
235        /**
236     * Initialize the filter.
237     */
238    protected void initialize() {
239                rows = cols = (int)Math.sqrt(matrix.length);
240                map = new int[levels];
241                for (int i = 0; i < levels; i++) {
242                        int v = 255 * i / (levels-1);
243                        map[i] = v;
244                }
245                div = new int[256];
246                mod = new int[256];
247                int rc = (rows*cols+1);
248                for (int i = 0; i < 256; i++) {
249                        div[i] = (levels-1)*i / 256;
250                        mod[i] = i*rc/256;
251                }
252        }
253
254        public int filterRGB(int x, int y, int rgb) {
255                if (!initialized) {
256                        initialized = true;
257                        initialize();
258                }
259                int a = rgb & 0xff000000;
260                int r = (rgb >> 16) & 0xff;
261                int g = (rgb >> 8) & 0xff;
262                int b = rgb & 0xff;
263                int col = x % cols;
264                int row = y % rows;
265                int v = matrix[row*cols+col];
266                if (colorDither) {
267                        r = map[mod[r] > v ? div[r] + 1 : div[r]];
268                        g = map[mod[g] > v ? div[g] + 1 : div[g]];
269                        b = map[mod[b] > v ? div[b] + 1 : div[b]];
270                } else {
271                        int value = (r+g+b)/3;
272                        r = g = b = map[mod[value] > v ? div[value] + 1 : div[value]];
273                }
274                return a | (r << 16) | (g << 8) | b;
275        }
276
277        public String toString() {
278                return "Colors/Dither...";
279        }
280
281}
282