Source Code Cross Referenced for Quantize.java in  » Installer » jsmooth » net » charabia » util » codec » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Installer » jsmooth » net.charabia.util.codec 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package net.charabia.util.codec;
002:
003:        /*
004:         * @(#)Quantize.java    0.90 9/19/00 Adam Doppelt
005:         */
006:
007:        /**
008:         * An efficient color quantization algorithm, adapted from the C++
009:         * implementation quantize.c in <a
010:         * href="http://www.imagemagick.org/">ImageMagick</a>. The pixels for
011:         * an image are placed into an oct tree. The oct tree is reduced in
012:         * size, and the pixels from the original image are reassigned to the
013:         * nodes in the reduced tree.<p>
014:         *
015:         * Here is the copyright notice from ImageMagick:
016:         * 
017:         * <pre>
018:         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
019:         %  Permission is hereby granted, free of charge, to any person obtaining a    %
020:         %  copy of this software and associated documentation files ("ImageMagick"),  %
021:         %  to deal in ImageMagick without restriction, including without limitation   %
022:         %  the rights to use, copy, modify, merge, publish, distribute, sublicense,   %
023:         %  and/or sell copies of ImageMagick, and to permit persons to whom the       %
024:         %  ImageMagick is furnished to do so, subject to the following conditions:    %
025:         %                                                                             %
026:         %  The above copyright notice and this permission notice shall be included in %
027:         %  all copies or substantial portions of ImageMagick.                         %
028:         %                                                                             %
029:         %  The software is provided "as is", without warranty of any kind, express or %
030:         %  implied, including but not limited to the warranties of merchantability,   %
031:         %  fitness for a particular purpose and noninfringement.  In no event shall   %
032:         %  E. I. du Pont de Nemours and Company be liable for any claim, damages or   %
033:         %  other liability, whether in an action of contract, tort or otherwise,      %
034:         %  arising from, out of or in connection with ImageMagick or the use or other %
035:         %  dealings in ImageMagick.                                                   %
036:         %                                                                             %
037:         %  Except as contained in this notice, the name of the E. I. du Pont de       %
038:         %  Nemours and Company shall not be used in advertising or otherwise to       %
039:         %  promote the sale, use or other dealings in ImageMagick without prior       %
040:         %  written authorization from the E. I. du Pont de Nemours and Company.       %
041:         %                                                                             %
042:         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
043:         </pre>
044:         *
045:         *
046:         * @version 0.90 19 Sep 2000
047:         * @author <a href="http://www.gurge.com/amd/">Adam Doppelt</a>
048:         */
049:        public class Quantize {
050:
051:            /*
052:             %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
053:             %                                                                             %
054:             %                                                                             %
055:             %                                                                             %
056:             %           QQQ   U   U   AAA   N   N  TTTTT  IIIII   ZZZZZ  EEEEE            %
057:             %          Q   Q  U   U  A   A  NN  N    T      I        ZZ  E                %
058:             %          Q   Q  U   U  AAAAA  N N N    T      I      ZZZ   EEEEE            %
059:             %          Q  QQ  U   U  A   A  N  NN    T      I     ZZ     E                %
060:             %           QQQQ   UUU   A   A  N   N    T    IIIII   ZZZZZ  EEEEE            %
061:             %                                                                             %
062:             %                                                                             %
063:             %              Reduce the Number of Unique Colors in an Image                 %
064:             %                                                                             %
065:             %                                                                             %
066:             %                           Software Design                                   %
067:             %                             John Cristy                                     %
068:             %                              July 1992                                      %
069:             %                                                                             %
070:             %                                                                             %
071:             %  Copyright 1998 E. I. du Pont de Nemours and Company                        %
072:             %                                                                             %
073:             %  Permission is hereby granted, free of charge, to any person obtaining a    %
074:             %  copy of this software and associated documentation files ("ImageMagick"),  %
075:             %  to deal in ImageMagick without restriction, including without limitation   %
076:             %  the rights to use, copy, modify, merge, publish, distribute, sublicense,   %
077:             %  and/or sell copies of ImageMagick, and to permit persons to whom the       %
078:             %  ImageMagick is furnished to do so, subject to the following conditions:    %
079:             %                                                                             %
080:             %  The above copyright notice and this permission notice shall be included in %
081:             %  all copies or substantial portions of ImageMagick.                         %
082:             %                                                                             %
083:             %  The software is provided "as is", without warranty of any kind, express or %
084:             %  implied, including but not limited to the warranties of merchantability,   %
085:             %  fitness for a particular purpose and noninfringement.  In no event shall   %
086:             %  E. I. du Pont de Nemours and Company be liable for any claim, damages or   %
087:             %  other liability, whether in an action of contract, tort or otherwise,      %
088:             %  arising from, out of or in connection with ImageMagick or the use or other %
089:             %  dealings in ImageMagick.                                                   %
090:             %                                                                             %
091:             %  Except as contained in this notice, the name of the E. I. du Pont de       %
092:             %  Nemours and Company shall not be used in advertising or otherwise to       %
093:             %  promote the sale, use or other dealings in ImageMagick without prior       %
094:             %  written authorization from the E. I. du Pont de Nemours and Company.       %
095:             %                                                                             %
096:             %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
097:             %
098:             %  Realism in computer graphics typically requires using 24 bits/pixel to
099:             %  generate an image. Yet many graphic display devices do not contain
100:             %  the amount of memory necessary to match the spatial and color
101:             %  resolution of the human eye. The QUANTIZE program takes a 24 bit
102:             %  image and reduces the number of colors so it can be displayed on
103:             %  raster device with less bits per pixel. In most instances, the
104:             %  quantized image closely resembles the original reference image.
105:             %
106:             %  A reduction of colors in an image is also desirable for image
107:             %  transmission and real-time animation.
108:             %
109:             %  Function Quantize takes a standard RGB or monochrome images and quantizes
110:             %  them down to some fixed number of colors.
111:             %
112:             %  For purposes of color allocation, an image is a set of n pixels, where
113:             %  each pixel is a point in RGB space. RGB space is a 3-dimensional
114:             %  vector space, and each pixel, pi, is defined by an ordered triple of
115:             %  red, green, and blue coordinates, (ri, gi, bi).
116:             %
117:             %  Each primary color component (red, green, or blue) represents an
118:             %  intensity which varies linearly from 0 to a maximum value, cmax, which
119:             %  corresponds to full saturation of that color. Color allocation is
120:             %  defined over a domain consisting of the cube in RGB space with
121:             %  opposite vertices at (0,0,0) and (cmax,cmax,cmax). QUANTIZE requires
122:             %  cmax = 255.
123:             %
124:             %  The algorithm maps this domain onto a tree in which each node
125:             %  represents a cube within that domain. In the following discussion
126:             %  these cubes are defined by the coordinate of two opposite vertices:
127:             %  The vertex nearest the origin in RGB space and the vertex farthest
128:             %  from the origin.
129:             %
130:             %  The tree's root node represents the the entire domain, (0,0,0) through
131:             %  (cmax,cmax,cmax). Each lower level in the tree is generated by
132:             %  subdividing one node's cube into eight smaller cubes of equal size.
133:             %  This corresponds to bisecting the parent cube with planes passing
134:             %  through the midpoints of each edge.
135:             %
136:             %  The basic algorithm operates in three phases: Classification,
137:             %  Reduction, and Assignment. Classification builds a color
138:             %  description tree for the image. Reduction collapses the tree until
139:             %  the number it represents, at most, the number of colors desired in the
140:             %  output image. Assignment defines the output image's color map and
141:             %  sets each pixel's color by reclassification in the reduced tree.
142:             %  Our goal is to minimize the numerical discrepancies between the original
143:             %  colors and quantized colors (quantization error).
144:             %
145:             %  Classification begins by initializing a color description tree of
146:             %  sufficient depth to represent each possible input color in a leaf.
147:             %  However, it is impractical to generate a fully-formed color
148:             %  description tree in the classification phase for realistic values of
149:             %  cmax. If colors components in the input image are quantized to k-bit
150:             %  precision, so that cmax= 2k-1, the tree would need k levels below the
151:             %  root node to allow representing each possible input color in a leaf.
152:             %  This becomes prohibitive because the tree's total number of nodes is
153:             %  1 + sum(i=1,k,8k).
154:             %
155:             %  A complete tree would require 19,173,961 nodes for k = 8, cmax = 255.
156:             %  Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
157:             %  Initializes data structures for nodes only as they are needed;  (2)
158:             %  Chooses a maximum depth for the tree as a function of the desired
159:             %  number of colors in the output image (currently log2(colormap size)).
160:             %
161:             %  For each pixel in the input image, classification scans downward from
162:             %  the root of the color description tree. At each level of the tree it
163:             %  identifies the single node which represents a cube in RGB space
164:             %  containing the pixel's color. It updates the following data for each
165:             %  such node:
166:             %
167:             %    n1: Number of pixels whose color is contained in the RGB cube
168:             %    which this node represents;
169:             %
170:             %    n2: Number of pixels whose color is not represented in a node at
171:             %    lower depth in the tree;  initially,  n2 = 0 for all nodes except
172:             %    leaves of the tree.
173:             %
174:             %    Sr, Sg, Sb: Sums of the red, green, and blue component values for
175:             %    all pixels not classified at a lower depth. The combination of
176:             %    these sums and n2  will ultimately characterize the mean color of a
177:             %    set of pixels represented by this node.
178:             %
179:             %    E: The distance squared in RGB space between each pixel contained
180:             %    within a node and the nodes' center. This represents the quantization
181:             %    error for a node.
182:             %
183:             %  Reduction repeatedly prunes the tree until the number of nodes with
184:             %  n2 > 0 is less than or equal to the maximum number of colors allowed
185:             %  in the output image. On any given iteration over the tree, it selects
186:             %  those nodes whose E count is minimal for pruning and merges their
187:             %  color statistics upward. It uses a pruning threshold, Ep, to govern
188:             %  node selection as follows:
189:             %
190:             %    Ep = 0
191:             %    while number of nodes with (n2 > 0) > required maximum number of colors
192:             %      prune all nodes such that E <= Ep
193:             %      Set Ep to minimum E in remaining nodes
194:             %
195:             %  This has the effect of minimizing any quantization error when merging
196:             %  two nodes together.
197:             %
198:             %  When a node to be pruned has offspring, the pruning procedure invokes
199:             %  itself recursively in order to prune the tree from the leaves upward.
200:             %  n2,  Sr, Sg,  and  Sb in a node being pruned are always added to the
201:             %  corresponding data in that node's parent. This retains the pruned
202:             %  node's color characteristics for later averaging.
203:             %
204:             %  For each node, n2 pixels exist for which that node represents the
205:             %  smallest volume in RGB space containing those pixel's colors. When n2
206:             %  > 0 the node will uniquely define a color in the output image. At the
207:             %  beginning of reduction,  n2 = 0  for all nodes except a the leaves of
208:             %  the tree which represent colors present in the input image.
209:             %
210:             %  The other pixel count, n1, indicates the total number of colors
211:             %  within the cubic volume which the node represents. This includes n1 -
212:             %  n2  pixels whose colors should be defined by nodes at a lower level in
213:             %  the tree.
214:             %
215:             %  Assignment generates the output image from the pruned tree. The
216:             %  output image consists of two parts: (1)  A color map, which is an
217:             %  array of color descriptions (RGB triples) for each color present in
218:             %  the output image;  (2)  A pixel array, which represents each pixel as
219:             %  an index into the color map array.
220:             %
221:             %  First, the assignment phase makes one pass over the pruned color
222:             %  description tree to establish the image's color map. For each node
223:             %  with n2  > 0, it divides Sr, Sg, and Sb by n2 . This produces the
224:             %  mean color of all pixels that classify no lower than this node. Each
225:             %  of these colors becomes an entry in the color map.
226:             %
227:             %  Finally,  the assignment phase reclassifies each pixel in the pruned
228:             %  tree to identify the deepest node containing the pixel's color. The
229:             %  pixel's value in the pixel array becomes the index of this node's mean
230:             %  color in the color map.
231:             %
232:             %  With the permission of USC Information Sciences Institute, 4676 Admiralty
233:             %  Way, Marina del Rey, California  90292, this code was adapted from module
234:             %  ALCOLS written by Paul Raveling.
235:             %
236:             %  The names of ISI and USC are not used in advertising or publicity
237:             %  pertaining to distribution of the software without prior specific
238:             %  written permission from ISI.
239:             %
240:             */
241:
242:            final static boolean QUICK = true;
243:
244:            final static int MAX_RGB = 255;
245:            final static int MAX_NODES = 266817;
246:            final static int MAX_TREE_DEPTH = 8;
247:
248:            // these are precomputed in advance
249:            static int SQUARES[];
250:            static int SHIFT[];
251:
252:            static {
253:                SQUARES = new int[MAX_RGB + MAX_RGB + 1];
254:                for (int i = -MAX_RGB; i <= MAX_RGB; i++) {
255:                    SQUARES[i + MAX_RGB] = i * i;
256:                }
257:
258:                SHIFT = new int[MAX_TREE_DEPTH + 1];
259:                for (int i = 0; i < MAX_TREE_DEPTH + 1; ++i) {
260:                    SHIFT[i] = 1 << (15 - i);
261:                }
262:            }
263:
264:            /**
265:             * Reduce the image to the given number of colors. The pixels are
266:             * reduced in place.
267:             * @return The new color palette.
268:             */
269:            public static int[] quantizeImage(int pixels[][], int max_colors) {
270:                Cube cube = new Cube(pixels, max_colors);
271:                cube.classification();
272:                cube.reduction();
273:                cube.assignment();
274:                return cube.colormap;
275:            }
276:
277:            static class Cube {
278:                int pixels[][];
279:                int max_colors;
280:                int colormap[];
281:
282:                Node root;
283:                int depth;
284:
285:                // counter for the number of colors in the cube. this gets
286:                // recalculated often.
287:                int colors;
288:
289:                // counter for the number of nodes in the tree
290:                int nodes;
291:
292:                Cube(int pixels[][], int max_colors) {
293:                    this .pixels = pixels;
294:                    this .max_colors = max_colors;
295:
296:                    int i = max_colors;
297:                    // tree_depth = log max_colors
298:                    //                 4
299:                    for (depth = 1; i != 0; depth++) {
300:                        i /= 4;
301:                    }
302:                    if (depth > 1) {
303:                        --depth;
304:                    }
305:                    if (depth > MAX_TREE_DEPTH) {
306:                        depth = MAX_TREE_DEPTH;
307:                    } else if (depth < 2) {
308:                        depth = 2;
309:                    }
310:
311:                    root = new Node(this );
312:                }
313:
314:                /*
315:                 * Procedure Classification begins by initializing a color
316:                 * description tree of sufficient depth to represent each
317:                 * possible input color in a leaf. However, it is impractical
318:                 * to generate a fully-formed color description tree in the
319:                 * classification phase for realistic values of cmax. If
320:                 * colors components in the input image are quantized to k-bit
321:                 * precision, so that cmax= 2k-1, the tree would need k levels
322:                 * below the root node to allow representing each possible
323:                 * input color in a leaf. This becomes prohibitive because the
324:                 * tree's total number of nodes is 1 + sum(i=1,k,8k).
325:                 *
326:                 * A complete tree would require 19,173,961 nodes for k = 8,
327:                 * cmax = 255. Therefore, to avoid building a fully populated
328:                 * tree, QUANTIZE: (1) Initializes data structures for nodes
329:                 * only as they are needed; (2) Chooses a maximum depth for
330:                 * the tree as a function of the desired number of colors in
331:                 * the output image (currently log2(colormap size)).
332:                 *
333:                 * For each pixel in the input image, classification scans
334:                 * downward from the root of the color description tree. At
335:                 * each level of the tree it identifies the single node which
336:                 * represents a cube in RGB space containing It updates the
337:                 * following data for each such node:
338:                 *
339:                 *   number_pixels : Number of pixels whose color is contained
340:                 *   in the RGB cube which this node represents;
341:                 *
342:                 *   unique : Number of pixels whose color is not represented
343:                 *   in a node at lower depth in the tree; initially, n2 = 0
344:                 *   for all nodes except leaves of the tree.
345:                 *
346:                 *   total_red/green/blue : Sums of the red, green, and blue
347:                 *   component values for all pixels not classified at a lower
348:                 *   depth. The combination of these sums and n2 will
349:                 *   ultimately characterize the mean color of a set of pixels
350:                 *   represented by this node.
351:                 */
352:                void classification() {
353:                    int pixels[][] = this .pixels;
354:
355:                    int width = pixels.length;
356:                    int height = pixels[0].length;
357:
358:                    // convert to indexed color
359:                    for (int x = width; x-- > 0;) {
360:                        for (int y = height; y-- > 0;) {
361:                            int pixel = pixels[x][y];
362:                            int red = (pixel >> 16) & 0xFF;
363:                            int green = (pixel >> 8) & 0xFF;
364:                            int blue = (pixel >> 0) & 0xFF;
365:
366:                            // a hard limit on the number of nodes in the tree
367:                            if (nodes > MAX_NODES) {
368:                                System.out.println("pruning");
369:                                root.pruneLevel();
370:                                --depth;
371:                            }
372:
373:                            // walk the tree to depth, increasing the
374:                            // number_pixels count for each node
375:                            Node node = root;
376:                            for (int level = 1; level <= depth; ++level) {
377:                                int id = (((red > node.mid_red ? 1 : 0) << 0)
378:                                        | ((green > node.mid_green ? 1 : 0) << 1) | ((blue > node.mid_blue ? 1
379:                                        : 0) << 2));
380:                                if (node.child[id] == null) {
381:                                    new Node(node, id, level);
382:                                }
383:                                node = node.child[id];
384:                                node.number_pixels += SHIFT[level];
385:                            }
386:
387:                            ++node.unique;
388:                            node.total_red += red;
389:                            node.total_green += green;
390:                            node.total_blue += blue;
391:                        }
392:                    }
393:                }
394:
395:                /*
396:                 * reduction repeatedly prunes the tree until the number of
397:                 * nodes with unique > 0 is less than or equal to the maximum
398:                 * number of colors allowed in the output image.
399:                 *
400:                 * When a node to be pruned has offspring, the pruning
401:                 * procedure invokes itself recursively in order to prune the
402:                 * tree from the leaves upward.  The statistics of the node
403:                 * being pruned are always added to the corresponding data in
404:                 * that node's parent.  This retains the pruned node's color
405:                 * characteristics for later averaging.
406:                 */
407:                void reduction() {
408:                    int threshold = 1;
409:                    while (colors > max_colors) {
410:                        colors = 0;
411:                        threshold = root.reduce(threshold, Integer.MAX_VALUE);
412:                    }
413:                }
414:
415:                /**
416:                 * The result of a closest color search.
417:                 */
418:                static class Search {
419:                    int distance;
420:                    int color_number;
421:                }
422:
423:                /*
424:                 * Procedure assignment generates the output image from the
425:                 * pruned tree. The output image consists of two parts: (1) A
426:                 * color map, which is an array of color descriptions (RGB
427:                 * triples) for each color present in the output image; (2) A
428:                 * pixel array, which represents each pixel as an index into
429:                 * the color map array.
430:                 *
431:                 * First, the assignment phase makes one pass over the pruned
432:                 * color description tree to establish the image's color map.
433:                 * For each node with n2 > 0, it divides Sr, Sg, and Sb by n2.
434:                 * This produces the mean color of all pixels that classify no
435:                 * lower than this node. Each of these colors becomes an entry
436:                 * in the color map.
437:                 *
438:                 * Finally, the assignment phase reclassifies each pixel in
439:                 * the pruned tree to identify the deepest node containing the
440:                 * pixel's color. The pixel's value in the pixel array becomes
441:                 * the index of this node's mean color in the color map.
442:                 */
443:                void assignment() {
444:                    colormap = new int[colors];
445:
446:                    colors = 0;
447:                    root.colormap();
448:
449:                    int pixels[][] = this .pixels;
450:
451:                    int width = pixels.length;
452:                    int height = pixels[0].length;
453:
454:                    Search search = new Search();
455:
456:                    // convert to indexed color
457:                    for (int x = width; x-- > 0;) {
458:                        for (int y = height; y-- > 0;) {
459:                            int pixel = pixels[x][y];
460:                            int red = (pixel >> 16) & 0xFF;
461:                            int green = (pixel >> 8) & 0xFF;
462:                            int blue = (pixel >> 0) & 0xFF;
463:
464:                            // walk the tree to find the cube containing that color
465:                            Node node = root;
466:                            for (;;) {
467:                                int id = (((red > node.mid_red ? 1 : 0) << 0)
468:                                        | ((green > node.mid_green ? 1 : 0) << 1) | ((blue > node.mid_blue ? 1
469:                                        : 0) << 2));
470:                                if (node.child[id] == null) {
471:                                    break;
472:                                }
473:                                node = node.child[id];
474:                            }
475:
476:                            if (QUICK) {
477:                                // if QUICK is set, just use that
478:                                // node. Strictly speaking, this isn't
479:                                // necessarily best match.
480:                                pixels[x][y] = node.color_number;
481:                            } else {
482:                                // Find the closest color.
483:                                search.distance = Integer.MAX_VALUE;
484:                                node.parent.closestColor(red, green, blue,
485:                                        search);
486:                                pixels[x][y] = search.color_number;
487:                            }
488:                        }
489:                    }
490:                }
491:
492:                /**
493:                 * A single Node in the tree.
494:                 */
495:                static class Node {
496:                    Cube cube;
497:
498:                    // parent node
499:                    Node parent;
500:
501:                    // child nodes
502:                    Node child[];
503:                    int nchild;
504:
505:                    // our index within our parent
506:                    int id;
507:                    // our level within the tree
508:                    int level;
509:                    // our color midpoint
510:                    int mid_red;
511:                    int mid_green;
512:                    int mid_blue;
513:
514:                    // the pixel count for this node and all children
515:                    int number_pixels;
516:
517:                    // the pixel count for this node
518:                    int unique;
519:                    // the sum of all pixels contained in this node
520:                    int total_red;
521:                    int total_green;
522:                    int total_blue;
523:
524:                    // used to build the colormap
525:                    int color_number;
526:
527:                    Node(Cube cube) {
528:                        this .cube = cube;
529:                        this .parent = this ;
530:                        this .child = new Node[8];
531:                        this .id = 0;
532:                        this .level = 0;
533:
534:                        this .number_pixels = Integer.MAX_VALUE;
535:
536:                        this .mid_red = (MAX_RGB + 1) >> 1;
537:                        this .mid_green = (MAX_RGB + 1) >> 1;
538:                        this .mid_blue = (MAX_RGB + 1) >> 1;
539:                    }
540:
541:                    Node(Node parent, int id, int level) {
542:                        this .cube = parent.cube;
543:                        this .parent = parent;
544:                        this .child = new Node[8];
545:                        this .id = id;
546:                        this .level = level;
547:
548:                        // add to the cube
549:                        ++cube.nodes;
550:                        if (level == cube.depth) {
551:                            ++cube.colors;
552:                        }
553:
554:                        // add to the parent
555:                        ++parent.nchild;
556:                        parent.child[id] = this ;
557:
558:                        // figure out our midpoint
559:                        int bi = (1 << (MAX_TREE_DEPTH - level)) >> 1;
560:                        mid_red = parent.mid_red + ((id & 1) > 0 ? bi : -bi);
561:                        mid_green = parent.mid_green
562:                                + ((id & 2) > 0 ? bi : -bi);
563:                        mid_blue = parent.mid_blue + ((id & 4) > 0 ? bi : -bi);
564:                    }
565:
566:                    /**
567:                     * Remove this child node, and make sure our parent
568:                     * absorbs our pixel statistics.
569:                     */
570:                    void pruneChild() {
571:                        --parent.nchild;
572:                        parent.unique += unique;
573:                        parent.total_red += total_red;
574:                        parent.total_green += total_green;
575:                        parent.total_blue += total_blue;
576:                        parent.child[id] = null;
577:                        --cube.nodes;
578:                        cube = null;
579:                        parent = null;
580:                    }
581:
582:                    /**
583:                     * Prune the lowest layer of the tree.
584:                     */
585:                    void pruneLevel() {
586:                        if (nchild != 0) {
587:                            for (int id = 0; id < 8; id++) {
588:                                if (child[id] != null) {
589:                                    child[id].pruneLevel();
590:                                }
591:                            }
592:                        }
593:                        if (level == cube.depth) {
594:                            pruneChild();
595:                        }
596:                    }
597:
598:                    /**
599:                     * Remove any nodes that have fewer than threshold
600:                     * pixels. Also, as long as we're walking the tree:
601:                     *
602:                     *  - figure out the color with the fewest pixels
603:                     *  - recalculate the total number of colors in the tree
604:                     */
605:                    int reduce(int threshold, int next_threshold) {
606:                        if (nchild != 0) {
607:                            for (int id = 0; id < 8; id++) {
608:                                if (child[id] != null) {
609:                                    next_threshold = child[id].reduce(
610:                                            threshold, next_threshold);
611:                                }
612:                            }
613:                        }
614:                        if (number_pixels <= threshold) {
615:                            pruneChild();
616:                        } else {
617:                            if (unique != 0) {
618:                                cube.colors++;
619:                            }
620:                            if (number_pixels < next_threshold) {
621:                                next_threshold = number_pixels;
622:                            }
623:                        }
624:                        return next_threshold;
625:                    }
626:
627:                    /*
628:                     * colormap traverses the color cube tree and notes each
629:                     * colormap entry. A colormap entry is any node in the
630:                     * color cube tree where the number of unique colors is
631:                     * not zero.
632:                     */
633:                    void colormap() {
634:                        if (nchild != 0) {
635:                            for (int id = 0; id < 8; id++) {
636:                                if (child[id] != null) {
637:                                    child[id].colormap();
638:                                }
639:                            }
640:                        }
641:                        if (unique != 0) {
642:                            int r = ((total_red + (unique >> 1)) / unique);
643:                            int g = ((total_green + (unique >> 1)) / unique);
644:                            int b = ((total_blue + (unique >> 1)) / unique);
645:                            cube.colormap[cube.colors] = (((0xFF) << 24)
646:                                    | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | ((b & 0xFF) << 0));
647:                            color_number = cube.colors++;
648:                        }
649:                    }
650:
651:                    /* ClosestColor traverses the color cube tree at a
652:                     * particular node and determines which colormap entry
653:                     * best represents the input color.
654:                     */
655:                    void closestColor(int red, int green, int blue,
656:                            Search search) {
657:                        if (nchild != 0) {
658:                            for (int id = 0; id < 8; id++) {
659:                                if (child[id] != null) {
660:                                    child[id].closestColor(red, green, blue,
661:                                            search);
662:                                }
663:                            }
664:                        }
665:
666:                        if (unique != 0) {
667:                            int color = cube.colormap[color_number];
668:                            int distance = distance(color, red, green, blue);
669:                            if (distance < search.distance) {
670:                                search.distance = distance;
671:                                search.color_number = color_number;
672:                            }
673:                        }
674:                    }
675:
676:                    /**
677:                     * Figure out the distance between this node and som color.
678:                     */
679:                    final static int distance(int color, int r, int g, int b) {
680:                        return (SQUARES[((color >> 16) & 0xFF) - r + MAX_RGB]
681:                                + SQUARES[((color >> 8) & 0xFF) - g + MAX_RGB] + SQUARES[((color >> 0) & 0xFF)
682:                                - b + MAX_RGB]);
683:                    }
684:
685:                    public String toString() {
686:                        StringBuffer buf = new StringBuffer();
687:                        if (parent == this ) {
688:                            buf.append("root");
689:                        } else {
690:                            buf.append("node");
691:                        }
692:                        buf.append(' ');
693:                        buf.append(level);
694:                        buf.append(" [");
695:                        buf.append(mid_red);
696:                        buf.append(',');
697:                        buf.append(mid_green);
698:                        buf.append(',');
699:                        buf.append(mid_blue);
700:                        buf.append(']');
701:                        return new String(buf);
702:                    }
703:                }
704:            }
705:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.