Advertisement
Guest User

Untitled

a guest
Mar 27th, 2015
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 30.59 KB | None | 0 0
  1. /*
  2.  * @(#)Quantize.java    0.90 9/19/00 Adam Doppelt
  3.  */
  4.  
  5.  package com.gurge.amd;
  6.  
  7. /**
  8.  * An efficient color quantization algorithm, adapted from the C++
  9.  * implementation quantize.c in <a
  10.  * href="http://www.imagemagick.org/">ImageMagick</a>. The pixels for
  11.  * an image are placed into an oct tree. The oct tree is reduced in
  12.  * size, and the pixels from the original image are reassigned to the
  13.  * nodes in the reduced tree.<p>
  14.  *
  15.  * Here is the copyright notice from ImageMagick:
  16.  *
  17.  * <pre>
  18. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  19. %  Permission is hereby granted, free of charge, to any person obtaining a    %
  20. %  copy of this software and associated documentation files ("ImageMagick"),  %
  21. %  to deal in ImageMagick without restriction, including without limitation   %
  22. %  the rights to use, copy, modify, merge, publish, distribute, sublicense,   %
  23. %  and/or sell copies of ImageMagick, and to permit persons to whom the       %
  24. %  ImageMagick is furnished to do so, subject to the following conditions:    %
  25. %                                                                             %
  26. %  The above copyright notice and this permission notice shall be included in %
  27. %  all copies or substantial portions of ImageMagick.                         %
  28. %                                                                             %
  29. %  The software is provided "as is", without warranty of any kind, express or %
  30. %  implied, including but not limited to the warranties of merchantability,   %
  31. %  fitness for a particular purpose and noninfringement.  In no event shall   %
  32. %  E. I. du Pont de Nemours and Company be liable for any claim, damages or   %
  33. %  other liability, whether in an action of contract, tort or otherwise,      %
  34. %  arising from, out of or in connection with ImageMagick or the use or other %
  35. %  dealings in ImageMagick.                                                   %
  36. %                                                                             %
  37. %  Except as contained in this notice, the name of the E. I. du Pont de       %
  38. %  Nemours and Company shall not be used in advertising or otherwise to       %
  39. %  promote the sale, use or other dealings in ImageMagick without prior       %
  40. %  written authorization from the E. I. du Pont de Nemours and Company.       %
  41. %                                                                             %
  42. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  43. </pre>
  44.  *
  45.  *
  46.  * @version 0.90 19 Sep 2000
  47.  * @author <a href="http://www.gurge.com/amd/">Adam Doppelt</a>
  48.  */
  49. public class Quantize {
  50.  
  51. /*
  52. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  53. %                                                                             %
  54. %                                                                             %
  55. %                                                                             %
  56. %           QQQ   U   U   AAA   N   N  TTTTT  IIIII   ZZZZZ  EEEEE            %
  57. %          Q   Q  U   U  A   A  NN  N    T      I        ZZ  E                %
  58. %          Q   Q  U   U  AAAAA  N N N    T      I      ZZZ   EEEEE            %
  59. %          Q  QQ  U   U  A   A  N  NN    T      I     ZZ     E                %
  60. %           QQQQ   UUU   A   A  N   N    T    IIIII   ZZZZZ  EEEEE            %
  61. %                                                                             %
  62. %                                                                             %
  63. %              Reduce the Number of Unique Colors in an Image                 %
  64. %                                                                             %
  65. %                                                                             %
  66. %                           Software Design                                   %
  67. %                             John Cristy                                     %
  68. %                              July 1992                                      %
  69. %                                                                             %
  70. %                                                                             %
  71. %  Copyright 1998 E. I. du Pont de Nemours and Company                        %
  72. %                                                                             %
  73. %  Permission is hereby granted, free of charge, to any person obtaining a    %
  74. %  copy of this software and associated documentation files ("ImageMagick"),  %
  75. %  to deal in ImageMagick without restriction, including without limitation   %
  76. %  the rights to use, copy, modify, merge, publish, distribute, sublicense,   %
  77. %  and/or sell copies of ImageMagick, and to permit persons to whom the       %
  78. %  ImageMagick is furnished to do so, subject to the following conditions:    %
  79. %                                                                             %
  80. %  The above copyright notice and this permission notice shall be included in %
  81. %  all copies or substantial portions of ImageMagick.                         %
  82. %                                                                             %
  83. %  The software is provided "as is", without warranty of any kind, express or %
  84. %  implied, including but not limited to the warranties of merchantability,   %
  85. %  fitness for a particular purpose and noninfringement.  In no event shall   %
  86. %  E. I. du Pont de Nemours and Company be liable for any claim, damages or   %
  87. %  other liability, whether in an action of contract, tort or otherwise,      %
  88. %  arising from, out of or in connection with ImageMagick or the use or other %
  89. %  dealings in ImageMagick.                                                   %
  90. %                                                                             %
  91. %  Except as contained in this notice, the name of the E. I. du Pont de       %
  92. %  Nemours and Company shall not be used in advertising or otherwise to       %
  93. %  promote the sale, use or other dealings in ImageMagick without prior       %
  94. %  written authorization from the E. I. du Pont de Nemours and Company.       %
  95. %                                                                             %
  96. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  97. %
  98. %  Realism in computer graphics typically requires using 24 bits/pixel to
  99. %  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.     /**
  266.      * Reduce the image to the given number of colors. The pixels are
  267.      * reduced in place.
  268.      * @return The new color palette.
  269.      */
  270.     public static int[] quantizeImage(int pixels[][], int max_colors) {
  271.         Cube cube = new Cube(pixels, max_colors);
  272.         cube.classification();
  273.         cube.reduction();
  274.         cube.assignment();
  275.         return cube.colormap;
  276.     }
  277.    
  278.     static class Cube {
  279.         int pixels[][];
  280.         int max_colors;
  281.         int colormap[];
  282.        
  283.         Node root;
  284.         int depth;
  285.  
  286.         // counter for the number of colors in the cube. this gets
  287.         // recalculated often.
  288.         int colors;
  289.  
  290.         // counter for the number of nodes in the tree
  291.         int nodes;
  292.  
  293.         Cube(int pixels[][], int max_colors) {
  294.             this.pixels = pixels;
  295.             this.max_colors = max_colors;
  296.  
  297.             int i = max_colors;
  298.             // tree_depth = log max_colors
  299.             //                 4
  300.             for (depth = 1; i != 0; depth++) {
  301.                 i /= 4;
  302.             }
  303.             if (depth > 1) {
  304.                 --depth;
  305.             }
  306.             if (depth > MAX_TREE_DEPTH) {
  307.                 depth = MAX_TREE_DEPTH;
  308.             } else if (depth < 2) {
  309.                 depth = 2;
  310.             }
  311.            
  312.             root = new Node(this);
  313.         }
  314.  
  315.         /*
  316.          * Procedure Classification begins by initializing a color
  317.          * description tree of sufficient depth to represent each
  318.          * possible input color in a leaf. However, it is impractical
  319.          * to generate a fully-formed color description tree in the
  320.          * classification phase for realistic values of cmax. If
  321.          * colors components in the input image are quantized to k-bit
  322.          * precision, so that cmax= 2k-1, the tree would need k levels
  323.          * below the root node to allow representing each possible
  324.          * input color in a leaf. This becomes prohibitive because the
  325.          * tree's total number of nodes is 1 + sum(i=1,k,8k).
  326.          *
  327.          * A complete tree would require 19,173,961 nodes for k = 8,
  328.          * cmax = 255. Therefore, to avoid building a fully populated
  329.          * tree, QUANTIZE: (1) Initializes data structures for nodes
  330.          * only as they are needed; (2) Chooses a maximum depth for
  331.          * the tree as a function of the desired number of colors in
  332.          * the output image (currently log2(colormap size)).
  333.          *
  334.          * For each pixel in the input image, classification scans
  335.          * downward from the root of the color description tree. At
  336.          * each level of the tree it identifies the single node which
  337.          * represents a cube in RGB space containing It updates the
  338.          * following data for each such node:
  339.          *
  340.          *   number_pixels : Number of pixels whose color is contained
  341.          *   in the RGB cube which this node represents;
  342.          *
  343.          *   unique : Number of pixels whose color is not represented
  344.          *   in a node at lower depth in the tree; initially, n2 = 0
  345.          *   for all nodes except leaves of the tree.
  346.          *
  347.          *   total_red/green/blue : Sums of the red, green, and blue
  348.          *   component values for all pixels not classified at a lower
  349.          *   depth. The combination of these sums and n2 will
  350.          *   ultimately characterize the mean color of a set of pixels
  351.          *   represented by this node.
  352.          */
  353.         void classification() {
  354.             int pixels[][] = this.pixels;
  355.  
  356.             int width = pixels.length;
  357.             int height = pixels[0].length;
  358.  
  359.             // convert to indexed color
  360.             for (int x = width; x-- > 0; ) {
  361.                 for (int y = height; y-- > 0; ) {
  362.                     int pixel = pixels[x][y];
  363.                     int red   = (pixel >> 16) & 0xFF;
  364.                     int green = (pixel >>  8) & 0xFF;
  365.                     int blue  = (pixel >>  0) & 0xFF;
  366.  
  367.                     // a hard limit on the number of nodes in the tree
  368.                     if (nodes > MAX_NODES) {
  369.                         System.out.println("pruning");
  370.                         root.pruneLevel();
  371.                         --depth;
  372.                     }
  373.  
  374.                     // walk the tree to depth, increasing the
  375.                     // number_pixels count for each node
  376.                     Node node = root;
  377.                     for (int level = 1; level <= depth; ++level) {
  378.                         int id = (((red   > node.mid_red   ? 1 : 0) << 0) |
  379.                                   ((green > node.mid_green ? 1 : 0) << 1) |
  380.                                   ((blue  > node.mid_blue  ? 1 : 0) << 2));
  381.                         if (node.child[id] == null) {
  382.                             new Node(node, id, level);
  383.                         }
  384.                         node = node.child[id];
  385.                         node.number_pixels += SHIFT[level];
  386.                     }
  387.  
  388.                     ++node.unique;
  389.                     node.total_red   += red;
  390.                     node.total_green += green;
  391.                     node.total_blue  += blue;
  392.                 }
  393.             }
  394.         }
  395.  
  396.         /*
  397.          * reduction repeatedly prunes the tree until the number of
  398.          * nodes with unique > 0 is less than or equal to the maximum
  399.          * number of colors allowed in the output image.
  400.          *
  401.          * When a node to be pruned has offspring, the pruning
  402.          * procedure invokes itself recursively in order to prune the
  403.          * tree from the leaves upward.  The statistics of the node
  404.          * being pruned are always added to the corresponding data in
  405.          * that node's parent.  This retains the pruned node's color
  406.          * characteristics for later averaging.
  407.          */
  408.         void reduction() {
  409.             int threshold = 1;
  410.             while (colors > max_colors) {
  411.                 colors = 0;
  412.                 threshold = root.reduce(threshold, Integer.MAX_VALUE);
  413.             }
  414.         }
  415.  
  416.         /**
  417.          * The result of a closest color search.
  418.          */
  419.         static class Search {
  420.             int distance;
  421.             int color_number;
  422.         }
  423.  
  424.         /*
  425.          * Procedure assignment generates the output image from the
  426.          * pruned tree. The output image consists of two parts: (1) A
  427.          * color map, which is an array of color descriptions (RGB
  428.          * triples) for each color present in the output image; (2) A
  429.          * pixel array, which represents each pixel as an index into
  430.          * the color map array.
  431.          *
  432.          * First, the assignment phase makes one pass over the pruned
  433.          * color description tree to establish the image's color map.
  434.          * For each node with n2 > 0, it divides Sr, Sg, and Sb by n2.
  435.          * This produces the mean color of all pixels that classify no
  436.          * lower than this node. Each of these colors becomes an entry
  437.          * in the color map.
  438.          *
  439.          * Finally, the assignment phase reclassifies each pixel in
  440.          * the pruned tree to identify the deepest node containing the
  441.          * pixel's color. The pixel's value in the pixel array becomes
  442.          * the index of this node's mean color in the color map.
  443.          */
  444.         void assignment() {
  445.             colormap = new int[colors];
  446.  
  447.             colors = 0;
  448.             root.colormap();
  449.  
  450.             int pixels[][] = this.pixels;
  451.  
  452.             int width = pixels.length;
  453.             int height = pixels[0].length;
  454.  
  455.             Search search = new Search();
  456.            
  457.             // convert to indexed color
  458.             for (int x = width; x-- > 0; ) {
  459.                 for (int y = height; y-- > 0; ) {
  460.                     int pixel = pixels[x][y];
  461.                     int red   = (pixel >> 16) & 0xFF;
  462.                     int green = (pixel >>  8) & 0xFF;
  463.                     int blue  = (pixel >>  0) & 0xFF;
  464.  
  465.                     // walk the tree to find the cube containing that color
  466.                     Node node = root;
  467.                     for ( ; ; ) {
  468.                         int id = (((red   > node.mid_red   ? 1 : 0) << 0) |
  469.                                   ((green > node.mid_green ? 1 : 0) << 1) |
  470.                                   ((blue  > node.mid_blue  ? 1 : 0) << 2)  );
  471.                         if (node.child[id] == null) {
  472.                             break;
  473.                         }
  474.                         node = node.child[id];
  475.                     }
  476.  
  477.                     if (QUICK) {
  478.                         // if QUICK is set, just use that
  479.                         // node. Strictly speaking, this isn't
  480.                         // necessarily best match.
  481.                         pixels[x][y] = node.color_number;
  482.                     } else {
  483.                         // Find the closest color.
  484.                         search.distance = Integer.MAX_VALUE;
  485.                         node.parent.closestColor(red, green, blue, 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 + ((id & 2) > 0 ? bi : -bi);
  562.                 mid_blue  = parent.mid_blue  + ((id & 4) > 0 ? bi : -bi);
  563.             }
  564.  
  565.             /**
  566.              * Remove this child node, and make sure our parent
  567.              * absorbs our pixel statistics.
  568.              */
  569.             void pruneChild() {
  570.                 --parent.nchild;
  571.                 parent.unique += unique;
  572.                 parent.total_red     += total_red;
  573.                 parent.total_green   += total_green;
  574.                 parent.total_blue    += total_blue;
  575.                 parent.child[id] = null;
  576.                 --cube.nodes;
  577.                 cube = null;
  578.                 parent = null;
  579.             }
  580.  
  581.             /**
  582.              * Prune the lowest layer of the tree.
  583.              */
  584.             void pruneLevel() {
  585.                 if (nchild != 0) {
  586.                     for (int id = 0; id < 8; id++) {
  587.                         if (child[id] != null) {
  588.                             child[id].pruneLevel();
  589.                         }
  590.                     }
  591.                 }
  592.                 if (level == cube.depth) {
  593.                     pruneChild();
  594.                 }
  595.             }
  596.  
  597.             /**
  598.              * Remove any nodes that have fewer than threshold
  599.              * pixels. Also, as long as we're walking the tree:
  600.              *
  601.              *  - figure out the color with the fewest pixels
  602.              *  - recalculate the total number of colors in the tree
  603.              */
  604.             int reduce(int threshold, int next_threshold) {
  605.                 if (nchild != 0) {
  606.                     for (int id = 0; id < 8; id++) {
  607.                         if (child[id] != null) {
  608.                             next_threshold = child[id].reduce(threshold, next_threshold);
  609.                         }
  610.                     }
  611.                 }
  612.                 if (number_pixels <= threshold) {
  613.                     pruneChild();
  614.                 } else {
  615.                     if (unique != 0) {
  616.                         cube.colors++;
  617.                     }
  618.                     if (number_pixels < next_threshold) {
  619.                         next_threshold = number_pixels;
  620.                     }
  621.                 }
  622.                 return next_threshold;
  623.             }
  624.  
  625.             /*
  626.              * colormap traverses the color cube tree and notes each
  627.              * colormap entry. A colormap entry is any node in the
  628.              * color cube tree where the number of unique colors is
  629.              * not zero.
  630.              */
  631.             void colormap() {
  632.                 if (nchild != 0) {
  633.                     for (int id = 0; id < 8; id++) {
  634.                         if (child[id] != null) {
  635.                             child[id].colormap();
  636.                         }
  637.                     }
  638.                 }
  639.                 if (unique != 0) {
  640.                     int r = ((total_red   + (unique >> 1)) / unique);
  641.                     int g = ((total_green + (unique >> 1)) / unique);
  642.                     int b = ((total_blue  + (unique >> 1)) / unique);
  643.                     cube.colormap[cube.colors] = (((    0xFF) << 24) |
  644.                                                   ((r & 0xFF) << 16) |
  645.                                                   ((g & 0xFF) <<  8) |
  646.                                                   ((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, Search search) {
  656.                 if (nchild != 0) {
  657.                     for (int id = 0; id < 8; id++) {
  658.                         if (child[id] != null) {
  659.                             child[id].closestColor(red, green, blue, search);
  660.                         }
  661.                     }
  662.                 }
  663.  
  664.                 if (unique != 0) {
  665.                     int color = cube.colormap[color_number];
  666.                     int distance = distance(color, red, green, blue);
  667.                     if (distance < search.distance) {
  668.                         search.distance = distance;
  669.                         search.color_number = color_number;
  670.                     }
  671.                 }
  672.             }
  673.  
  674.             /**
  675.              * Figure out the distance between this node and som color.
  676.              */
  677.             final static int distance(int color, int r, int g, int b) {
  678.                 return (SQUARES[((color >> 16) & 0xFF) - r + MAX_RGB] +
  679.                         SQUARES[((color >>  8) & 0xFF) - g + MAX_RGB] +
  680.                         SQUARES[((color >>  0) & 0xFF) - b + MAX_RGB]);
  681.             }
  682.  
  683.             public String toString() {
  684.                 StringBuffer buf = new StringBuffer();
  685.                 if (parent == this) {
  686.                     buf.append("root");
  687.                 } else {
  688.                     buf.append("node");
  689.                 }
  690.                 buf.append(' ');
  691.                 buf.append(level);
  692.                 buf.append(" [");
  693.                 buf.append(mid_red);
  694.                 buf.append(',');
  695.                 buf.append(mid_green);
  696.                 buf.append(',');
  697.                 buf.append(mid_blue);
  698.                 buf.append(']');
  699.                 return new String(buf);
  700.             }
  701.         }
  702.     }
  703. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement