Leptonica 1.68
C Image Processing Library

colorquant1.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 /*
00017  *  colorquant1.c
00018  *                     
00019  *  Octcube color quantization
00020  *
00021  *  There are several different octcube/octree based quantizations.
00022  *  These can be classified, in the order in which they appear in this
00023  *  file, as follows:
00024  *
00025  *  -----------------------------------------------------------------
00026  *  (1) General adaptive octree
00027  *  (2) Adaptive octree by population at fixed level
00028  *  (3) Adaptive octree using population and with specified number
00029  *      of output colors
00030  *  (4) Octcube with colormap representation of mixed color/gray
00031  *  (5) 256 fixed octcubes covering color space
00032  *  (6) Octcubes at fixed level for ncolors <= 256
00033  *  (7) Octcubes at fixed level with RGB output
00034  *  (8) Quantizing an rgb image using a specified colormap
00035  *  -----------------------------------------------------------------
00036  *
00037  *  (1) Two-pass adaptive octree color quantization
00038  *          PIX              *pixOctreeColorQuant()
00039  *          PIX              *pixOctreeColorQuantGeneral()
00040  *
00041  *        which calls
00042  *          static CQCELL  ***octreeGenerateAndPrune()
00043  *          static PIX       *pixOctreeQuantizePixels()
00044  *
00045  *        which calls
00046  *          static l_int32    octreeFindColorCell()
00047  *          
00048  *      Helper cqcell functions
00049  *          static CQCELL  ***cqcellTreeCreate()
00050  *          static void       cqcellTreeDestroy()
00051  *
00052  *      Helper index functions
00053  *          l_int32           makeRGBToIndexTables()
00054  *          void              getOctcubeIndexFromRGB()
00055  *          static void       getRGBFromOctcube()
00056  *          static l_int32    getOctcubeIndices()
00057  *          static l_int32    octcubeGetCount()
00058  *
00059  *  (2) Adaptive octree quantization based on population at a fixed level
00060  *          PIX              *pixOctreeQuantByPopulation()
00061  *          static l_int32    pixDitherOctindexWithCmap()
00062  *
00063  *  (3) Adaptive octree quantization to 4 and 8 bpp with specified
00064  *      number of output colors in colormap
00065  *          PIX              *pixOctreeQuantNumColors()
00066  *
00067  *  (4) Mixed color/gray quantization with specified number of colors
00068  *          PIX              *pixOctcubeQuantMixedWithGray()
00069  *
00070  *  (5) Fixed partition octcube quantization with 256 cells
00071  *          PIX              *pixFixedOctcubeQuant256()
00072  *
00073  *  (6) Fixed partition quantization for images with few colors
00074  *          PIX              *pixFewColorsOctcubeQuant1()
00075  *          PIX              *pixFewColorsOctcubeQuant2()
00076  *          PIX              *pixFewColorsOctcubeQuantMixed()
00077  *
00078  *  (7) Fixed partition octcube quantization at specified level
00079  *      with quantized output to RGB
00080  *          PIX              *pixFixedOctcubeQuantGenRGB()
00081  *
00082  *  (8) Color quantize RGB image using existing colormap
00083  *          PIX              *pixQuantFromCmap()  [high-level wrapper]
00084  *          PIX              *pixOctcubeQuantFromCmap()
00085  *          PIX              *pixOctcubeQuantFromCmapLUT()
00086  *
00087  *      Generation of octcube histogram
00088  *          NUMA             *pixOctcubeHistogram()
00089  *          
00090  *      Get filled octcube table from colormap
00091  *          l_int32          *pixcmapToOctcubeLUT()
00092  *
00093  *      Strip out unused elements in colormap
00094  *          l_int32           pixRemoveUnusedColors()
00095  *
00096  *      Find number of occupied octcubes at the specified level
00097  *          l_int32           pixNumberOccupiedOctcubes()
00098  *
00099  *  Note: leptonica also provides color quantization using a modified
00100  *        form of median cut.  See colorquant2.c for details.
00101  */
00102 
00103 #include <stdio.h>
00104 #include <stdlib.h>
00105 #include <string.h>
00106 #include "allheaders.h"
00107 
00108 
00109 /*  This data structure is used for pixOctreeColorQuant(),
00110  *  a color octree that adjusts to the color distribution
00111  *  in the image that is being quantized.  The best settings
00112  *  are with CQ_NLEVELS = 6 and DITHERING set on.
00113  *
00114  *  Notes:  (1) the CTE (color table entry) index is sequentially
00115  *              assigned as the tree is pruned back
00116  *          (2) if 'bleaf' == 1, all pixels in that cube have been
00117  *              assigned to one or more CTEs.  But note that if
00118  *              all 8 subcubes have 'bleaf' == 1, it will have no
00119  *              pixels left for assignment and will not be a CTE.
00120  *          (3) 'nleaves', the number of leaves contained at the next
00121  *              lower level is some number between 0 and 8, inclusive.
00122  *              If it is zero, it means that all colors within this cube
00123  *              are part of a single growing cluster that has not yet
00124  *              been set aside as a leaf.  If 'nleaves' > 0, 'bleaf'
00125  *              will be set to 1 and all pixels not assigned to leaves
00126  *              at lower levels will be assigned to a CTE here.
00127  *              (However, as described above, if all pixels are already
00128  *              assigned, we set 'bleaf' = 1 but do not create a CTE
00129  *              at this level.)
00130  *          (4) To keep the maximum color error to a minimum, we
00131  *              prune the tree back to level 2, and require that
00132  *              all 64 level 2 cells are CTEs.
00133  *          (5) We reserve an extra set of colors to prevent running out
00134  *              of colors during the assignment of the final 64 level 2 cells.
00135  *              This is more likely to happen with small images.
00136  *          (6) When we run out of colors, the dithered image can be very
00137  *              poor, so we additionally prevent dithering if the image
00138  *              is small.
00139  *          (7) The color content of the image is measured, and if there
00140  *              is very little color, it is quantized in grayscale.
00141  */
00142 struct ColorQuantCell
00143 {
00144     l_int32     rc, gc, bc;   /* center values                              */
00145     l_int32     n;            /* number of samples in this cell             */
00146     l_int32     index;        /* CTE (color table entry) index              */
00147     l_int32     nleaves;      /* # of leaves contained at next lower level  */
00148     l_int32     bleaf;        /* boolean: 0 if not a leaf, 1 if so          */
00149 };
00150 typedef struct ColorQuantCell    CQCELL;
00151 
00152     /* Constants for pixOctreeColorQuant() */
00153 static const l_int32  CQ_NLEVELS = 5;   /* only 4, 5 and 6 are allowed */
00154 static const l_int32  CQ_RESERVED_COLORS = 64;  /* to allow for level 2 */
00155                                                 /* remainder CTEs */
00156 static const l_int32  EXTRA_RESERVED_COLORS = 25;  /* to avoid running out */
00157 static const l_int32  TREE_GEN_WIDTH = 350;  /* big enough for good stats */
00158 static const l_int32  MIN_DITHER_SIZE = 250;  /* don't dither if smaller */
00159 
00160 
00161 /*  This data structure is used for pixOctreeQuantNumColors(),
00162  *  a color octree that adjusts in a simple way to the to the color
00163  *  distribution in the image that is being quantized.  It outputs
00164  *  colormapped images, either 4 bpp or 8 bpp, depending on the
00165  *  max number of colors and the compression desired. 
00166  *
00167  *  The number of samples is saved as a float in the first location,
00168  *  because this is required to use it as the key that orders the
00169  *  cells in the priority queue.  */
00170 struct OctcubeQuantCell
00171 {
00172     l_float32  n;                  /* number of samples in this cell       */
00173     l_int32    octindex;           /* octcube index                        */
00174     l_int32    rcum, gcum, bcum;   /* cumulative values                    */
00175     l_int32    rval, gval, bval;   /* average values                       */
00176 };
00177 typedef struct OctcubeQuantCell    OQCELL;
00178 
00179 
00180     /* This data structure is using for heap sorting octcubes
00181      * by population.  Sort order is decreasing.  */
00182 struct L_OctcubePop
00183 {
00184     l_float32        npix;    /* parameter on which to sort  */
00185     l_int32          index;   /* octcube index at assigned level */
00186     l_int32          rval;    /* mean red value of pixels in octcube */
00187     l_int32          gval;    /* mean green value of pixels in octcube */
00188     l_int32          bval;    /* mean blue value of pixels in octcube */
00189 };
00190 typedef struct L_OctcubePop  L_OCTCUBE_POP;
00191 
00192     /* In pixDitherOctindexWithCmap(), we use these default values.
00193      * To get the max value of 'dif' in the dithering color transfer,
00194      * divide these "DIF_CAP" values by 8.  However, a value of
00195      * 0 means that there is no cap (infinite cap).  A very small
00196      * value is used for POP_DIF_CAP because dithering on the population
00197      * generated colormap can be unstable without a tight cap.   */
00198 static const l_int32  FIXED_DIF_CAP = 0;
00199 static const l_int32  POP_DIF_CAP = 40;
00200 
00201 
00202     /* Static octree helper function */
00203 static l_int32 octreeFindColorCell(l_int32 octindex, CQCELL ***cqcaa,
00204                                    l_int32 *pindex, l_int32 *prval,
00205                                    l_int32 *pgval, l_int32 *pbval);
00206 
00207     /* Static cqcell functions */
00208 static CQCELL ***octreeGenerateAndPrune(PIX *pixs, l_int32 colors,
00209                                         l_int32 reservedcolors,
00210                                         PIXCMAP **pcmap);
00211 static PIX *pixOctreeQuantizePixels(PIX *pixs, CQCELL ***cqcaa,
00212                                     l_int32 ditherflag);
00213 static CQCELL ***cqcellTreeCreate(void);
00214 static void cqcellTreeDestroy(CQCELL ****pcqcaa);
00215 
00216     /* Static helper octcube index functions */
00217 static void getRGBFromOctcube(l_int32 cubeindex, l_int32 level,
00218                               l_int32 *prval, l_int32 *pgval, l_int32 *pbval);
00219 static l_int32 getOctcubeIndices(l_int32 rgbindex, l_int32 level,
00220                                  l_int32 *pbindex, l_int32 *psindex);
00221 static l_int32 octcubeGetCount(l_int32 level, l_int32 *psize);
00222 
00223     /* Static function to perform octcube-indexed dithering */
00224 static l_int32 pixDitherOctindexWithCmap(PIX *pixs, PIX *pixd, l_uint32 *rtab,
00225                                          l_uint32 *gtab, l_uint32 *btab,
00226                                          l_int32 *carray, l_int32 difcap);
00227 
00228 
00229 #ifndef   NO_CONSOLE_IO
00230 #define   DEBUG_OCTINDEX        0
00231 #define   DEBUG_OCTCUBE_CMAP    0
00232 #define   DEBUG_POP             0
00233 #define   DEBUG_FEW_COLORS      0
00234 #define   PRINT_OCTCUBE_STATS   0
00235 #endif   /* ~NO_CONSOLE_IO */
00236 
00237 
00238 /*-------------------------------------------------------------------------*
00239  *                Two-pass adaptive octree color quantization              *
00240  *-------------------------------------------------------------------------*/
00241 /*!
00242  *  pixOctreeColorQuant()
00243  *
00244  *      Input:  pixs  (32 bpp; 24-bit color)
00245  *              colors  (in colormap; some number in range [128 ... 256];
00246  *                      the actual number of colors used will be smaller)
00247  *              ditherflag  (1 to dither, 0 otherwise)
00248  *      Return: pixd (8 bpp with colormap), or null on error
00249  *
00250  *  I found one description in the literature of octree color
00251  *  quantization, using progressive truncation of the octree,
00252  *  by M. Gervautz and W. Purgathofer in Graphics Gems, pp.
00253  *  287-293, ed. A. Glassner, Academic Press, 1990.
00254  *  Rather than setting up a fixed partitioning of the color
00255  *  space ab initio, as we do here, they allow the octree to be
00256  *  progressively truncated as new pixels are added.  They
00257  *  need to set up some data structures that are traversed
00258  *  with the addition of each 24 bit pixel, in order to decide
00259  *  either (1) in which cluster (sub-branch of the octree) to put
00260  *  the pixel, or (2) whether to truncate the octree further
00261  *  to place the pixel in an existing cluster, or (3) which
00262  *  two existing clusters should be merged so that the pixel
00263  *  can be left to start a truncated leaf of the octree.  Such dynamic
00264  *  truncation is considerably more complicated, and Gervautz et
00265  *  al. did not explain how they did it in anywhere near the
00266  *  detail required to check their implementation.
00267  *
00268  *  The simple method in pixFixedOctcubeQuant256() is very
00269  *  fast, and with dithering the results are good, but you
00270  *  can do better if the color clusters are selected adaptively
00271  *  from the image.  We want a method that makes much better
00272  *  use of color samples in regions of color space with high
00273  *  pixel density, while also fairly representing small numbers
00274  *  of color pixels in low density regions.  Such adaptation
00275  *  requires two passes through the image: the first for generating
00276  *  the pruned tree of color cubes and the second for computing the index
00277  *  into the color table for each pixel.
00278  *
00279  *  A relatively simple adaptive method is pixOctreeQuantByPopulation().
00280  *  That function first determines if the image has very few colors,
00281  *  and, if so, quantizes to those colors.  If there are more than
00282  *  256 colors, it generates a histogram of octcube leaf occupancy
00283  *  at level 4, chooses the 192 most populated such leaves as
00284  *  the first 192 colors, and sets the remaining 64 colors to the
00285  *  residual average pixel values in each of the 64 level 2 octcubes.
00286  *  This is a bit faster than pixOctreeColorQuant(), and does very
00287  *  well without dithering, but for most images with dithering it
00288  *  is clearly inferior.
00289  *
00290  *  We now describe pixOctreeColorQuant().  The first pass is done
00291  *  on a subsampled image, because we do not need to use all the
00292  *  pixels in the image to generate the tree.  Subsampling
00293  *  down to 0.25 (1/16 of the pixels) makes the program run
00294  *  about 1.3 times faster.
00295  *
00296  *  Instead of dividing the color space into 256 equal-sized
00297  *  regions, we initially divide it into 2^12 or 2^15 or 2^18
00298  *  equal-sized octcubes.  Suppose we choose to use 2^18 octcubes.  
00299  *  This gives us 6 octree levels.  We then prune back,
00300  *  starting from level 6.  For every cube at level 6, there
00301  *  are 8 cubes at level 5.  Call the operation of putting a
00302  *  cube aside as a color table entry (CTE) a "saving." 
00303  *  We use a (in general) level-dependent threshold, and save
00304  *  those level 6 cubes that are above threshold.
00305  *  The rest are combined into the containing level 5 cube.
00306  *  If between 1 and 7 level 6 cubes within a level 5
00307  *  cube have been saved by thresholding, then the remaining
00308  *  level 6 cubes in that level 5 cube are automatically
00309  *  saved as well, without applying a threshold.  This greatly
00310  *  simplifies both the description of the CTEs and the later
00311  *  classification of each pixel as belonging to a CTE.
00312  *  This procedure is iterated through every cube, starting at
00313  *  level 5, and then 4, 3, and 2, successively.  The result is that
00314  *  each CTE contains the entirety of a set of from 1 to 7 cubes
00315  *  from a given level that all belong to a single cube at the
00316  *  level above.   We classify the CTEs in terms of the
00317  *  condition in which they are made as either being "threshold"
00318  *  or "residual."  They are "threshold" CTEs if no subcubes
00319  *  are CTEs (that is, they contain every pixel within the cube)
00320  *  and the number of pixels exceeds the threshold for making 
00321  *  a CTE.  They are "residual" CTEs if at least one but not more
00322  *  than 7 of the subcubes have already been determined to be CTEs;
00323  *  this happens automatically -- no threshold is applied.
00324  *  If all 8 subcubes are determined to be CTEs, the cube is
00325  *  marked as having all pixels accounted for ('bleaf' = 1) but
00326  *  is not saved as a CTE.
00327  *
00328  *  We stop the pruning at level 2, at which there are 64
00329  *  sub-cubes.  Any pixels not already claimed in a CTE are
00330  *  put in these cubes.  
00331  *
00332  *  As the cubes are saved as color samples in the color table,
00333  *  the number of remaining pixels P and the number of
00334  *  remaining colors in the color table N are recomputed,
00335  *  along with the average number of pixels P/N (ppc) to go in
00336  *  each of the remaining colors.  This running average number is
00337  *  used to set the threshold at the current level.
00338  *
00339  *  Because we are going to very small cubes at levels 6 or 5,
00340  *  and will dither the colors for errors, it is not necessary 
00341  *  to compute the color center of each cluster; we can simply
00342  *  use the center of the cube.  This gives us a minimax error
00343  *  condition: the maximum error is half the width of the 
00344  *  level 2 cubes -- 32 color values out of 256 -- for each color
00345  *  sample.  In practice, most of the pixels will be very much
00346  *  closer to the center of their cells.  And with dithering,
00347  *  the average pixel color in a small region will be closer still.
00348  *  Thus with the octree quantizer, we are able to capture
00349  *  regions of high color pdf (probability density function) in small
00350  *  but accurate CTEs, and to have only a small number of pixels
00351  *  that end up a significant distance (with a guaranteed maximum)
00352  *  from their true color.
00353  *
00354  *  How should the threshold factor vary?  Threshold factors
00355  *  are required for levels 2, 3, 4 and 5 in the pruning stage.
00356  *  The threshold for level 5 is actually applied to cubes at
00357  *  level 6, etc.  From various experiments, it appears that
00358  *  the results do not vary appreciably for threshold values near 1.0.
00359  *  If you want more colors in smaller cubes, the threshold
00360  *  factors can be set lower than 1.0 for cubes at levels 4 and 5. 
00361  *  However, if the factor is set much lower than 1.0 for
00362  *  levels 2 and 3, we can easily run out of colors.
00363  *  We put aside 64 colors in the calculation of the threshold
00364  *  values, because we must have 64 color centers at level 2,
00365  *  that will have very few pixels in most of them.
00366  *  If we reduce the factor for level 5 to 0.4, this will
00367  *  generate many level 6 CTEs, and consequently
00368  *  many residual cells will be formed up from those leaves,
00369  *  resulting in the possibility of running out of colors.
00370  *  Remember, the residual CTEs are mandatory, and are formed
00371  *  without using the threshold, regardless of the number of
00372  *  pixels that are absorbed.
00373  *      
00374  *  The implementation logically has four parts:
00375  *
00376  *       (1) accumulation into small, fixed cells
00377  *       (2) pruning back into selected CTE cubes
00378  *       (3) organizing the CTEs for fast search to find
00379  *           the CTE to which any image pixel belongs
00380  *       (4) doing a second scan to code the image pixels by CTE
00381  *
00382  *  Step (1) is straightforward; we use 2^15 cells.
00383  *
00384  *  We've already discussed how the pruning step (2) will be performed.
00385  *
00386  *  Steps (3) and (4) are related, in that the organization
00387  *  used by step (3) determines how the search actually
00388  *  takes place for each pixel in step (4).
00389  *
00390  *  There are many ways to do step (3).  Let's explore a few.
00391  *
00392  *  (a) The simplest is to order the cubes from highest occupancy
00393  *      to lowest, and traverse the list looking for the deepest
00394  *      match.  To make this more efficient, so that we know when
00395  *      to stop looking, any cube that has separate CTE subcubes
00396  *      would be marked as such, so that we know when we hit a 
00397  *      true leaf.
00398  *
00399  *  (b) Alternatively, we can order the cubes by highest
00400  *      occupancy separately each level, and work upward,
00401  *      starting at level 5, so that when we find a match we
00402  *      know that it will be correct. 
00403  *
00404  *  (c) Another approach would be to order the cubes by
00405  *      "address" and use a hash table to find the cube
00406  *      corresponding to a pixel color.  I don't know how to
00407  *      do this with a variable length address, as each CTE
00408  *      will have 3*n bits, where n is the level.
00409  *
00410  *  (d) Another approach entirely is to put the CTE cubes into
00411  *      a tree, in such a way that starting from the root, and
00412  *      using 3 bits of address at a time, the correct branch of
00413  *      each octree can be taken until a leaf is found.  Because
00414  *      a given cube can be both a leaf and also have branches
00415  *      going to sub-cubes, the search stops only when no
00416  *      marked subcubes have addresses that match the given pixel.
00417  *
00418  *      In the tree method, we can start with a dense infrastructure,
00419  *      and place the leaves corresponding to the N colors
00420  *      in the tree, or we can grow from the root only those
00421  *      branches that end directly on leaves.
00422  *
00423  *  What we do here is to take approach (d), and implement the tree
00424  *  "virtually", as a set of arrays, one array for each level
00425  *  of the tree.   Initially we start at level 5, an array with
00426  *  2^15 cubes, each with 8 subcubes.  We then build nodes at
00427  *  levels closer to the root; at level 4 there are 2^12 nodes
00428  *  each with 8 subcubes; etc.  Using these arrays has
00429  *  several advantages:
00430  *
00431  *     -  We don't need to keep track of links between cubes
00432  *        and subcubes, because we can use the canonical
00433  *        addressing on the cell arrays directly to determine
00434  *        which nodes are parent cubes and which are sub-cubes.
00435  *
00436  *     -  We can prune directly on this tree
00437  *
00438  *     -  We can navigate the pruned tree quickly to classify
00439  *        each pixel in the image.
00440  *      
00441  *  Canonical addressing guarantees that the i-th node at level k
00442  *  has 8 subnodes given by the 8*i ... 8*i+7 nodes at level k+1.
00443  *
00444  *  The pruning step works as follows.  We go from the lowest
00445  *  level up.  At each level, the threshold is found from the
00446  *  product of a factor near 1.0 and the ratio of unmarked pixels
00447  *  to remaining colors (minus the 64).  We march through
00448  *  the space, sequentially considering a cube and its 8 subcubes.
00449  *  We first check those subcubes that are not already
00450  *  marked as CTE to see if any are above threshold, and if so,
00451  *  generate a CTE and mark them as such.
00452  *  We then determine if any of the subcubes have been marked.
00453  *  If so, and there are subcubes that are not marked,
00454  *  we generate a CTE for the cube from the remaining unmarked
00455  *  subcubes; this is mandatory and does not depend on how many
00456  *  pixels are in the set of subcubes.  If none of the subcubes
00457  *  are marked, we aggregate their pixels into the cube
00458  *  containing them, but do not mark it as a CTE; that
00459  *  will be determined when iterating through the next level up.
00460  *
00461  *  When all the pixels in a cube are accounted for in one or more
00462  *  colors, we set the boolean 'bleaf' to true.  This is the
00463  *  flag used to mark the cubes in the pruning step.  If a cube
00464  *  is marked, and all 8 subcubes are marked, then it is not
00465  *  itself given a CTE because all pixels have already been
00466  *  accounted for.
00467  *
00468  *  Note that the pruning of the tree and labelling of the CTEs
00469  *  (step 2) accomplishes step 3 implicitly, because the marked
00470  *  and pruned tree is ready for use in labelling each pixel
00471  *  in step 4.  We now, for every pixel in the image, traverse
00472  *  the tree from the root, looking for the lowest cube that is a leaf.
00473  *  At each level we have a cube and subcube.  If we reach a subcube
00474  *  leaf that is marked 0, we know that the color is stored in the
00475  *  cube above, and we've found the CTE.  Otherwise, the subcube
00476  *  leaf is marked 1.  If we're at the last level, we've reached
00477  *  the final leaf and must use it.  Otherwise, continue the
00478  *  process at the next level down.
00479  *
00480  *  For robustness, efficiency and high quality output, we do the following:
00481  *
00482  *  (1) Measure the color content of the image.  If there is very little
00483  *      color, quantize in grayscale.
00484  *  (2) For efficiency, build the octree with a subsampled image if the
00485  *      image is larger than some threshold size.
00486  *  (3) Reserve an extra set of colors to prevent running out of colors
00487  *      when pruning the octree; specifically, during the assignment
00488  *      of those level 2 cells (out of the 64) that have unassigned
00489  *      pixels.  The problem of running out is more likely to happen
00490  *      with small images, because the estimation we use for the
00491  *      number of pixels available is not accurate.
00492  *  (4) In the unlikely event that we run out of colors, the dithered
00493  *      image can be very poor.  As this would only happen with very 
00494  *      small images, and dithering is not particularly noticeable with
00495  *      such images, turn it off.
00496  */
00497 PIX *
00498 pixOctreeColorQuant(PIX     *pixs,
00499                     l_int32  colors,
00500                     l_int32  ditherflag)
00501 {
00502     PROCNAME("pixOctreeColorQuant");
00503 
00504     if (!pixs)
00505         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
00506     if (pixGetDepth(pixs) != 32)
00507         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
00508     if (colors < 128 || colors > 240)  /* further restricted */
00509         return (PIX *)ERROR_PTR("colors must be in [128, 240]", procName, NULL);
00510 
00511     return pixOctreeColorQuantGeneral(pixs, colors, ditherflag, 0.01, 0.01);
00512 }
00513 
00514 
00515 /*!
00516  *  pixOctreeColorQuantGeneral()
00517  *
00518  *      Input:  pixs  (32 bpp; 24-bit color)
00519  *              colors  (in colormap; some number in range [128 ... 240];
00520  *                      the actual number of colors used will be smaller)
00521  *              ditherflag  (1 to dither, 0 otherwise)
00522  *              validthresh (minimum fraction of pixels neither near white
00523  *                           nor black, required for color quantization;
00524  *                           typically ~0.01, but smaller for images that have
00525  *                           color but are nearly all white)
00526  *              colorthresh (minimum fraction of pixels with color that are
00527  *                           not near white or black, that are required
00528  *                           for color quantization; typ. ~0.01, but smaller
00529  *                           for images that have color along with a
00530  *                           significant fraction of gray)
00531  *      Return: pixd (8 bit with colormap), or null on error
00532  *
00533  *  Notes:
00534  *      (1) The parameters @validthresh and @colorthresh are used to
00535  *          determine if color quantization should be used on an image,
00536  *          or whether, instead, it should be quantized in grayscale.
00537  *          If the image has very few non-white and non-black pixels, or
00538  *          if those pixels that are non-white and non-black are all
00539  *          very close to either white or black, it is usually better
00540  *          to treat the color as accidental and to quantize the image
00541  *          to gray only.  These parameters are useful if you know
00542  *          something a priori about the image.  Perhaps you know that
00543  *          there is only a very small fraction of color pixels, but they're
00544  *          important to preserve; then you want to use a smaller value for
00545  *          these parameters.  To disable conversion to gray and force
00546  *          color quantization, use @validthresh = 0.0 and @colorthresh = 0.0.
00547  *      (2) See pixOctreeColorQuant() for algorithmic and implementation
00548  *          details.  This function has a more general interface.
00549  *      (3) See pixColorFraction() for computing the fraction of pixels
00550  *          that are neither white nor black, and the fraction of those
00551  *          pixels that have little color.  From the documentation there:
00552  *             If pixfract is very small, there are few pixels that are
00553  *             neither black nor white.  If colorfract is very small,
00554  *             the pixels that are neither black nor white have very
00555  *             little color content.  The product 'pixfract * colorfract'
00556  *             gives the fraction of pixels with significant color content.
00557  *          We test against the product @validthresh * @colorthresh
00558  *          to find color in images that have either very few
00559  *          intermediate gray pixels or that have many such gray pixels.
00560  */
00561 PIX *
00562 pixOctreeColorQuantGeneral(PIX       *pixs,
00563                            l_int32    colors,
00564                            l_int32    ditherflag,
00565                            l_float32  validthresh,
00566                            l_float32  colorthresh)
00567 {
00568 l_int32    w, h, minside, factor, index, rval, gval, bval;
00569 l_float32  scalefactor;
00570 l_float32  pixfract;  /* fraction neither near white nor black */
00571 l_float32  colorfract;  /* fraction with color of the pixfract population */
00572 CQCELL  ***cqcaa;
00573 PIX       *pixd, *pixsub;
00574 PIXCMAP   *cmap;
00575 
00576     PROCNAME("pixOctreeColorQuantGeneral");
00577 
00578     if (!pixs)
00579         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
00580     if (pixGetDepth(pixs) != 32)
00581         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
00582     if (colors < 128 || colors > 240)
00583         return (PIX *)ERROR_PTR("colors must be in [128, 240]", procName, NULL);
00584 
00585         /* Determine if the image has sufficient color content for
00586          *   octree quantization, based on the input thresholds.
00587          * If pixfract << 1, most pixels are close to black or white.
00588          * If colorfract << 1, the pixels that are not near
00589          *   black or white have very little color.
00590          * If with insufficient color, quantize with a grayscale colormap. */
00591     pixGetDimensions(pixs, &w, &h, NULL);
00592     if (validthresh > 0.0 && colorthresh > 0.0) {
00593         minside = L_MIN(w, h);
00594         factor = L_MAX(1, minside / 400);
00595         pixColorFraction(pixs, 20, 244, 20, factor, &pixfract, &colorfract);
00596         if (pixfract * colorfract < validthresh * colorthresh) {
00597             L_INFO_FLOAT2("\n  Pixel fraction neither white nor black = %6.3f"
00598                           "\n  Color fraction of those pixels = %6.3f"
00599                           "\n  Quantizing to 8 bpp gray",
00600                           procName, pixfract, colorfract);
00601             return pixConvertTo8(pixs, 1);
00602         }
00603     }
00604     else
00605         L_INFO("\n  Process in color by default", procName);
00606 
00607         /* Conditionally subsample to speed up the first pass */
00608     if (w > TREE_GEN_WIDTH) {
00609         scalefactor = (l_float32)TREE_GEN_WIDTH / (l_float32)w;
00610         pixsub = pixScaleBySampling(pixs, scalefactor, scalefactor);
00611     }
00612     else
00613         pixsub = pixClone(pixs);
00614 
00615         /* Drop the number of requested colors if image is very small */
00616     if (w < MIN_DITHER_SIZE && h < MIN_DITHER_SIZE)
00617         colors = L_MIN(colors, 220);
00618 
00619         /* Make the pruned octree */
00620     cqcaa = octreeGenerateAndPrune(pixsub, colors, CQ_RESERVED_COLORS, &cmap);
00621     if (!cqcaa)
00622         return (PIX *)ERROR_PTR("tree not made", procName, NULL);
00623 #if 0
00624     L_INFO_INT(" Colors requested = %d", procName, colors);
00625     L_INFO_INT(" Actual colors = %d", procName, cmap->n);
00626 #endif
00627 
00628         /* Do not dither if image is very small */
00629     if (w < MIN_DITHER_SIZE && h < MIN_DITHER_SIZE && ditherflag == 1) {
00630         L_INFO("Small image: dithering turned off", procName);
00631         ditherflag = 0;
00632     }
00633 
00634         /* Traverse tree from root, looking for lowest cube
00635          * that is a leaf, and set dest pix value to its 
00636          * colortable index */
00637     if ((pixd = pixOctreeQuantizePixels(pixs, cqcaa, ditherflag)) == NULL)
00638         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
00639 
00640         /* Attach colormap and copy res */
00641     pixSetColormap(pixd, cmap);
00642     pixCopyResolution(pixd, pixs);
00643     pixCopyInputFormat(pixd, pixs);
00644 
00645         /* Force darkest color to black if each component <= 4 */
00646     pixcmapGetRankIntensity(cmap, 0.0, &index);
00647     pixcmapGetColor(cmap, index, &rval, &gval, &bval);
00648     if (rval < 5 && gval < 5 && bval < 5)
00649         pixcmapResetColor(cmap, index, 0, 0, 0);
00650 
00651         /* Force lightest color to white if each component >= 252 */
00652     pixcmapGetRankIntensity(cmap, 1.0, &index);
00653     pixcmapGetColor(cmap, index, &rval, &gval, &bval);
00654     if (rval > 251 && gval > 251 && bval > 251)
00655         pixcmapResetColor(cmap, index, 255, 255, 255);
00656 
00657     cqcellTreeDestroy(&cqcaa);
00658     pixDestroy(&pixsub);
00659     return pixd;
00660 }
00661 
00662 
00663 /*!
00664  *  octreeGenerateAndPrune()
00665  *
00666  *      Input:  pixs
00667  *              number of colors to use (between 128 and 256)
00668  *              number of reserved colors
00669  *              &cmap  (made and returned)
00670  *      Return: octree, colormap and number of colors used, or null
00671  *              on error
00672  *
00673  *  Notes:
00674  *      (1) The number of colors in the cmap may differ from the number
00675  *          of colors requested, but it will not be larger than 256
00676  */
00677 static CQCELL ***
00678 octreeGenerateAndPrune(PIX       *pixs,
00679                        l_int32    colors,
00680                        l_int32    reservedcolors,
00681                        PIXCMAP  **pcmap)
00682 {
00683 l_int32    rval, gval, bval, cindex;
00684 l_int32    level, ncells, octindex;
00685 l_int32    w, h, wpls;
00686 l_int32    i, j, isub;
00687 l_int32    npix;  /* number of remaining pixels to be assigned */
00688 l_int32    ncolor; /* number of remaining color cells to be used */
00689 l_int32    ppc;  /* ave number of pixels left for each color cell */
00690 l_int32    rv, gv, bv;
00691 l_float32  thresholdFactor[] = {0.01, 0.01, 1.0, 1.0, 1.0, 1.0};
00692 l_float32  thresh;  /* factor of ppc for this level */
00693 l_uint32  *datas, *lines;
00694 l_uint32  *rtab, *gtab, *btab;
00695 CQCELL  ***cqcaa;   /* one array for each octree level */
00696 CQCELL   **cqca, **cqcasub;
00697 CQCELL    *cqc, *cqcsub;
00698 PIXCMAP   *cmap;
00699 NUMA      *nat;  /* accumulates levels for threshold cells */
00700 NUMA      *nar;  /* accumulates levels for residual cells */
00701 
00702     PROCNAME("octreeGenerateAndPrune");
00703 
00704     if (!pixs)
00705         return (CQCELL ***)ERROR_PTR("pixs not defined", procName, NULL);
00706     if (pixGetDepth(pixs) != 32)
00707         return (CQCELL ***)ERROR_PTR("pixs must be 32 bpp", procName, NULL);
00708     if (colors < 128 || colors > 256)
00709         return (CQCELL ***)ERROR_PTR("colors not in [128,256]", procName, NULL);
00710     if (!pcmap)
00711         return (CQCELL ***)ERROR_PTR("&cmap not defined", procName, NULL);
00712 
00713         /* Make the canonical index tables */
00714     if (makeRGBToIndexTables(&rtab, &gtab, &btab, CQ_NLEVELS))
00715         return (CQCELL ***)ERROR_PTR("tables not made", procName, NULL);
00716 
00717     if ((cqcaa = cqcellTreeCreate()) == NULL)
00718         return (CQCELL ***)ERROR_PTR("cqcaa not made", procName, NULL);
00719 
00720         /* Generate an 8 bpp cmap (max size 256) */
00721     cmap = pixcmapCreate(8);
00722     *pcmap = cmap;
00723 
00724     pixGetDimensions(pixs, &w, &h, NULL);
00725     npix = w * h;  /* initialize to all pixels */
00726     ncolor = colors - reservedcolors - EXTRA_RESERVED_COLORS;
00727     ppc = npix / ncolor;
00728     datas = pixGetData(pixs);
00729     wpls = pixGetWpl(pixs);
00730 
00731         /* Accumulate the centers of each cluster at level CQ_NLEVELS */
00732     ncells = 1 << (3 * CQ_NLEVELS);
00733     cqca = cqcaa[CQ_NLEVELS];
00734     for (i = 0; i < h; i++) {
00735         lines = datas + i * wpls;
00736         for (j = 0; j < w; j++) {
00737             extractRGBValues(lines[j], &rval, &gval, &bval);
00738             octindex = rtab[rval] | gtab[gval] | btab[bval];
00739             cqc = cqca[octindex];
00740             cqc->n++;
00741         }
00742     }
00743 
00744         /* Arrays for storing statistics */
00745     if ((nat = numaCreate(0)) == NULL)
00746         return (CQCELL ***)ERROR_PTR("nat not made", procName, NULL);
00747     if ((nar = numaCreate(0)) == NULL)
00748         return (CQCELL ***)ERROR_PTR("nar not made", procName, NULL);
00749 
00750         /* Prune back from the lowest level and generate the colormap */
00751     for (level = CQ_NLEVELS - 1; level >= 2; level--) {
00752         thresh = thresholdFactor[level];
00753         cqca = cqcaa[level];
00754         cqcasub = cqcaa[level + 1];
00755         ncells = 1 << (3 * level);
00756         for (i = 0; i < ncells; i++) {  /* i is octindex at level */
00757             cqc = cqca[i];
00758             for (j = 0; j < 8; j++) {  /* check all subnodes */
00759                 isub = 8 * i + j;   /* isub is octindex at level+1 */
00760                 cqcsub = cqcasub[isub];
00761                 if (cqcsub->bleaf == 1) {  /* already a leaf? */
00762                     cqc->nleaves++;   /* count the subcube leaves */
00763                     continue;
00764                 }
00765                 if (cqcsub->n >= thresh * ppc) {  /* make it a true leaf? */
00766                     cqcsub->bleaf = 1;
00767                     if (cmap->n < 256) {
00768                         cqcsub->index = cmap->n;  /* assign the color index */
00769                         getRGBFromOctcube(isub, level + 1, &rv, &gv, &bv); 
00770                         pixcmapAddColor(cmap, rv, gv, bv);
00771 #if 1   /* save values */
00772                         cqcsub->rc = rv;
00773                         cqcsub->gc = gv;
00774                         cqcsub->bc = bv;
00775 #endif
00776                     }
00777                     else {
00778                             /* This doesn't seem to happen. */
00779                         L_WARNING("possibly assigned pixels to wrong color",
00780                                 procName);
00781                         pixcmapGetNearestIndex(cmap, rv, gv, bv, &cindex);
00782                         cqcsub->index = cindex;  /* assign to the nearest */
00783                         pixcmapGetColor(cmap, cindex, &rval, &gval, &bval);
00784                         cqcsub->rc = rval;
00785                         cqcsub->gc = gval;
00786                         cqcsub->bc = bval;
00787                     }
00788                     cqc->nleaves++;
00789                     npix -= cqcsub->n;
00790                     ncolor--;
00791                     if (ncolor > 0)
00792                         ppc = npix / ncolor;
00793                     else if (ncolor + reservedcolors > 0)
00794                         ppc = npix / (ncolor + reservedcolors);
00795                     else
00796                         ppc = 1000000;  /* make it big */
00797                     numaAddNumber(nat, level + 1);
00798 
00799 #if  DEBUG_OCTCUBE_CMAP
00800     fprintf(stderr, "Exceeds threshold: colors used = %d, colors remaining = %d\n",
00801                      cmap->n, ncolor + reservedcolors);
00802     fprintf(stderr, "  cell with %d pixels, npix = %d, ppc = %d\n",
00803                      cqcsub->n, npix, ppc);
00804     fprintf(stderr, "  index = %d, level = %d, subindex = %d\n",
00805                      i, level, j);
00806     fprintf(stderr, "  rv = %d, gv = %d, bv = %d\n", rv, gv, bv);
00807 #endif  /* DEBUG_OCTCUBE_CMAP */
00808 
00809                 }
00810             }
00811             if (cqc->nleaves > 0 || level == 2) { /* make the cube a leaf now */
00812                 cqc->bleaf = 1;
00813                 if (cqc->nleaves < 8) {  /* residual CTE cube: acquire the
00814                                           * remaining pixels */
00815                     for (j = 0; j < 8; j++) {  /* check all subnodes */
00816                         isub = 8 * i + j;
00817                         cqcsub = cqcasub[isub];
00818                         if (cqcsub->bleaf == 0)  /* absorb */
00819                             cqc->n += cqcsub->n;
00820                     }
00821                     if (cmap->n < 256) {
00822                         cqc->index = cmap->n;  /* assign the color index */
00823                         getRGBFromOctcube(i, level, &rv, &gv, &bv); 
00824                         pixcmapAddColor(cmap, rv, gv, bv);
00825 #if 1   /* save values */
00826                         cqc->rc = rv;
00827                         cqc->gc = gv;
00828                         cqc->bc = bv;
00829 #endif
00830                     }
00831                     else {
00832                         L_WARNING("possibly assigned pixels to wrong color",
00833                                 procName);
00834                             /* This is very bad.  It will only cause trouble
00835                              * with dithering, and we try to avoid it with
00836                              * EXTRA_RESERVED_PIXELS. */
00837                         pixcmapGetNearestIndex(cmap, rv, gv, bv, &cindex);
00838                         cqc->index = cindex;  /* assign to the nearest */
00839                         pixcmapGetColor(cmap, cindex, &rval, &gval, &bval);
00840                         cqc->rc = rval;
00841                         cqc->gc = gval;
00842                         cqc->bc = bval;
00843                     }
00844                     npix -= cqc->n;
00845                     ncolor--;
00846                     if (ncolor > 0)
00847                         ppc = npix / ncolor;
00848                     else if (ncolor + reservedcolors > 0)
00849                         ppc = npix / (ncolor + reservedcolors);
00850                     else
00851                         ppc = 1000000;  /* make it big */
00852                     numaAddNumber(nar, level);
00853 
00854 #if  DEBUG_OCTCUBE_CMAP
00855     fprintf(stderr, "By remainder: colors used = %d, colors remaining = %d\n",
00856                      cmap->n, ncolor + reservedcolors);
00857     fprintf(stderr, "  cell with %d pixels, npix = %d, ppc = %d\n",
00858                      cqc->n, npix, ppc);
00859     fprintf(stderr, "  index = %d, level = %d\n", i, level);
00860     fprintf(stderr, "  rv = %d, gv = %d, bv = %d\n", rv, gv, bv);
00861 #endif  /* DEBUG_OCTCUBE_CMAP */
00862 
00863                 }
00864             }
00865             else {  /* absorb all the subpixels but don't make it a leaf */
00866                 for (j = 0; j < 8; j++) {  /* absorb from all subnodes */
00867                     isub = 8 * i + j;
00868                     cqcsub = cqcasub[isub];
00869                     cqc->n += cqcsub->n;
00870                 }
00871             }
00872         }
00873     }
00874 
00875 #if  PRINT_OCTCUBE_STATS
00876 {
00877 l_int32    tc[] = {0, 0, 0, 0, 0, 0, 0};
00878 l_int32    rc[] = {0, 0, 0, 0, 0, 0, 0};
00879 l_int32    nt, nr, ival;
00880 
00881     nt = numaGetCount(nat);
00882     nr = numaGetCount(nar);
00883     for (i = 0; i < nt; i++) {
00884         numaGetIValue(nat, i, &ival);
00885         tc[ival]++;
00886     }
00887     for (i = 0; i < nr; i++) {
00888         numaGetIValue(nar, i, &ival);
00889         rc[ival]++;
00890     }
00891     fprintf(stderr, " Threshold cells formed: %d\n", nt);
00892     for (i = 1; i < CQ_NLEVELS + 1; i++)
00893         fprintf(stderr, "   level %d:  %d\n", i, tc[i]);
00894     fprintf(stderr, "\n Residual cells formed: %d\n", nr);
00895     for (i = 0; i < CQ_NLEVELS ; i++)
00896         fprintf(stderr, "   level %d:  %d\n", i, rc[i]);
00897 }
00898 #endif  /* PRINT_OCTCUBE_STATS */
00899 
00900     numaDestroy(&nat);
00901     numaDestroy(&nar);
00902     FREE(rtab);
00903     FREE(gtab);
00904     FREE(btab);
00905 
00906     return cqcaa;
00907 }
00908 
00909 
00910 /*!
00911  *  pixOctreeQuantizePixels()
00912  *
00913  *      Input:  pixs (32 bpp)
00914  *              octree in array format
00915  *              ditherflag (1 for dithering, 0 for no dithering)
00916  *      Return: pixd or null on error
00917  *
00918  *  Notes:
00919  *      (1) This routine doesn't need to use the CTEs (colormap
00920  *          table entries) because the color indices are embedded
00921  *          in the octree.  Thus, the calling program must make
00922  *          and attach the colormap to pixd after it is returned.
00923  *      (2) Dithering is performed in integers, effectively rounding
00924  *          to 1/8 sample increment.  The data in the integer buffers is
00925  *          64 times the sample values.  The 'dif' is 8 times the
00926  *          sample values, and this spread, multiplied by 8, to the
00927  *          integer buffers.  Because the dif is truncated to an
00928  *          integer, the dither is accurate to 1/8 of a sample increment,
00929  *          or 1/2048 of the color range.
00930  */
00931 static PIX *
00932 pixOctreeQuantizePixels(PIX       *pixs,
00933                         CQCELL  ***cqcaa,
00934                         l_int32    ditherflag)
00935 {
00936 l_uint8   *bufu8r, *bufu8g, *bufu8b;
00937 l_int32    rval, gval, bval;
00938 l_int32    octindex, index;
00939 l_int32    val1, val2, val3, dif;
00940 l_int32    w, h, wpls, wpld, i, j;
00941 l_int32    rc, gc, bc;
00942 l_int32   *buf1r, *buf1g, *buf1b, *buf2r, *buf2g, *buf2b;
00943 l_uint32  *rtab, *gtab, *btab;
00944 l_uint32  *datas, *datad, *lines, *lined;
00945 PIX       *pixd;
00946 
00947     PROCNAME("pixOctreeQuantizePixels");
00948 
00949     if (!pixs)
00950         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
00951     if (pixGetDepth(pixs) != 32)
00952         return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);
00953     if (!cqcaa)
00954         return (PIX *)ERROR_PTR("cqcaa not defined", procName, NULL);
00955 
00956         /* Make the canonical index tables */
00957     if (makeRGBToIndexTables(&rtab, &gtab, &btab, CQ_NLEVELS))
00958         return (PIX *)ERROR_PTR("tables not made", procName, NULL);
00959 
00960         /* Make output 8 bpp palette image */
00961     pixGetDimensions(pixs, &w, &h, NULL);
00962     datas = pixGetData(pixs);
00963     wpls = pixGetWpl(pixs);
00964     if ((pixd = pixCreate(w, h, 8)) == NULL)
00965         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
00966     pixCopyResolution(pixd, pixs);
00967     pixCopyInputFormat(pixd, pixs);
00968     datad = pixGetData(pixd);
00969     wpld = pixGetWpl(pixd);
00970 
00971         /* Traverse tree from root, looking for lowest cube
00972          * that is a leaf, and set dest pix to its 
00973          * colortable index value.  The results are far
00974          * better when dithering to get a more accurate
00975          * average color.  */
00976     if (ditherflag == 0) {    /* no dithering */
00977         for (i = 0; i < h; i++) {
00978             lines = datas + i * wpls;
00979             lined = datad + i * wpld;
00980             for (j = 0; j < w; j++) {
00981                 extractRGBValues(lines[j], &rval, &gval, &bval);
00982                 octindex = rtab[rval] | gtab[gval] | btab[bval];
00983                 octreeFindColorCell(octindex, cqcaa, &index, &rc, &gc, &bc);
00984                 SET_DATA_BYTE(lined, j, index);
00985             }
00986         }
00987     }
00988     else {  /* Dither */
00989         bufu8r = (l_uint8 *)CALLOC(w, sizeof(l_uint8));
00990         bufu8g = (l_uint8 *)CALLOC(w, sizeof(l_uint8));
00991         bufu8b = (l_uint8 *)CALLOC(w, sizeof(l_uint8));
00992         buf1r = (l_int32 *)CALLOC(w, sizeof(l_int32));
00993         buf1g = (l_int32 *)CALLOC(w, sizeof(l_int32));
00994         buf1b = (l_int32 *)CALLOC(w, sizeof(l_int32));
00995         buf2r = (l_int32 *)CALLOC(w, sizeof(l_int32));
00996         buf2g = (l_int32 *)CALLOC(w, sizeof(l_int32));
00997         buf2b = (l_int32 *)CALLOC(w, sizeof(l_int32));
00998         if (!bufu8r || !bufu8g || !bufu8b)
00999             return (PIX *)ERROR_PTR("uint8 mono line buf not made",
01000                 procName, NULL);
01001         if (!buf1r || !buf1g || !buf1b || !buf2r || !buf2g || !buf2b)
01002             return (PIX *)ERROR_PTR("mono line buf not made", procName, NULL);
01003 
01004             /* Start by priming buf2; line 1 is above line 2 */
01005         pixGetRGBLine(pixs, 0, bufu8r, bufu8g, bufu8b);
01006         for (j = 0; j < w; j++) {
01007             buf2r[j] = 64 * bufu8r[j];
01008             buf2g[j] = 64 * bufu8g[j];
01009             buf2b[j] = 64 * bufu8b[j];
01010         }
01011 
01012         for (i = 0; i < h - 1; i++) {
01013                 /* Swap data 2 --> 1, and read in new line 2 */
01014             memcpy(buf1r, buf2r, 4 * w);
01015             memcpy(buf1g, buf2g, 4 * w);
01016             memcpy(buf1b, buf2b, 4 * w);
01017             pixGetRGBLine(pixs, i + 1, bufu8r, bufu8g, bufu8b);
01018             for (j = 0; j < w; j++) {
01019                 buf2r[j] = 64 * bufu8r[j];
01020                 buf2g[j] = 64 * bufu8g[j];
01021                 buf2b[j] = 64 * bufu8b[j];
01022             }
01023 
01024                 /* Dither */
01025             lined = datad + i * wpld;
01026             for (j = 0; j < w - 1; j++) {
01027                 rval = buf1r[j] / 64;
01028                 gval = buf1g[j] / 64;
01029                 bval = buf1b[j] / 64;
01030                 octindex = rtab[rval] | gtab[gval] | btab[bval];
01031                 octreeFindColorCell(octindex, cqcaa, &index, &rc, &gc, &bc);
01032                 SET_DATA_BYTE(lined, j, index);
01033 
01034                 dif = buf1r[j] / 8 - 8 * rc;
01035                 if (dif != 0) {
01036                     val1 = buf1r[j + 1] + 3 * dif;
01037                     val2 = buf2r[j] + 3 * dif;
01038                     val3 = buf2r[j + 1] + 2 * dif;
01039                     if (dif > 0) {
01040                         buf1r[j + 1] = L_MIN(16383, val1);
01041                         buf2r[j] = L_MIN(16383, val2);
01042                         buf2r[j + 1] = L_MIN(16383, val3);
01043                     }
01044                     else if (dif < 0) {
01045                         buf1r[j + 1] = L_MAX(0, val1);
01046                         buf2r[j] = L_MAX(0, val2);
01047                         buf2r[j + 1] = L_MAX(0, val3);
01048                     }
01049                 }
01050 
01051                 dif = buf1g[j] / 8 - 8 * gc;
01052                 if (dif != 0) {
01053                     val1 = buf1g[j + 1] + 3 * dif;
01054                     val2 = buf2g[j] + 3 * dif;
01055                     val3 = buf2g[j + 1] + 2 * dif;
01056                     if (dif > 0) {
01057                         buf1g[j + 1] = L_MIN(16383, val1);
01058                         buf2g[j] = L_MIN(16383, val2);
01059                         buf2g[j + 1] = L_MIN(16383, val3);
01060                     }
01061                     else if (dif < 0) {
01062                         buf1g[j + 1] = L_MAX(0, val1);
01063                         buf2g[j] = L_MAX(0, val2);
01064                         buf2g[j + 1] = L_MAX(0, val3);
01065                     }
01066                 }
01067 
01068                 dif = buf1b[j] / 8 - 8 * bc;
01069                 if (dif != 0) {
01070                     val1 = buf1b[j + 1] + 3 * dif;
01071                     val2 = buf2b[j] + 3 * dif;
01072                     val3 = buf2b[j + 1] + 2 * dif;
01073                     if (dif > 0) {
01074                         buf1b[j + 1] = L_MIN(16383, val1);
01075                         buf2b[j] = L_MIN(16383, val2);
01076                         buf2b[j + 1] = L_MIN(16383, val3);
01077                     }
01078                     else if (dif < 0) {
01079                         buf1b[j + 1] = L_MAX(0, val1);
01080                         buf2b[j] = L_MAX(0, val2);
01081                         buf2b[j + 1] = L_MAX(0, val3);
01082                     }
01083                 }
01084             }
01085 
01086                 /* Get last pixel in row; no downward propagation */
01087             rval = buf1r[w - 1] / 64;
01088             gval = buf1g[w - 1] / 64;
01089             bval = buf1b[w - 1] / 64;
01090             octindex = rtab[rval] | gtab[gval] | btab[bval];
01091             octreeFindColorCell(octindex, cqcaa, &index, &rc, &gc, &bc);
01092             SET_DATA_BYTE(lined, w - 1, index);
01093         }
01094 
01095             /* Get last row of pixels; no leftward propagation */
01096         lined = datad + (h - 1) * wpld;
01097         for (j = 0; j < w; j++) {
01098             rval = buf2r[j] / 64;
01099             gval = buf2g[j] / 64;
01100             bval = buf2b[j] / 64;
01101             octindex = rtab[rval] | gtab[gval] | btab[bval];
01102             octreeFindColorCell(octindex, cqcaa, &index, &rc, &gc, &bc);
01103             SET_DATA_BYTE(lined, j, index);
01104         }
01105 
01106         FREE(bufu8r);
01107         FREE(bufu8g);
01108         FREE(bufu8b);
01109         FREE(buf1r);
01110         FREE(buf1g);
01111         FREE(buf1b);
01112         FREE(buf2r);
01113         FREE(buf2g);
01114         FREE(buf2b);
01115     }
01116 
01117     FREE(rtab);
01118     FREE(gtab);
01119     FREE(btab);
01120     return pixd;
01121 }
01122 
01123 
01124 /*!
01125  *  octreeFindColorCell()
01126  *
01127  *      Input:  octindex 
01128  *              cqcaa
01129  *              &index   (<return> index of CTE; returned to set pixel value)
01130  *              &rval    (<return> of CTE)
01131  *              &gval    (<return> of CTE)
01132  *              &bval    (<return> of CTE)
01133  *      Return: 0 if OK; 1 on error
01134  *
01135  *  Notes:
01136  *      (1) As this is in inner loop, we don't check input pointers!
01137  *      (2) This traverses from the root (well, actually from level 2,
01138  *          because the level 2 cubes are the largest CTE cubes),
01139  *          and finds the index number of the cell and the color values,
01140  *          which can be used either directly or in a (Floyd-Steinberg)
01141  *          error-diffusion dithering algorithm.
01142  */
01143 static l_int32
01144 octreeFindColorCell(l_int32    octindex,
01145                     CQCELL  ***cqcaa,
01146                     l_int32   *pindex,
01147                     l_int32   *prval,
01148                     l_int32   *pgval,
01149                     l_int32   *pbval)
01150 {
01151 l_int32  level;
01152 l_int32  baseindex, subindex;
01153 CQCELL  *cqc, *cqcsub;
01154 
01155         /* Use rgb values stored in the cubes; a little faster */
01156     for (level = 2; level < CQ_NLEVELS; level++) {
01157         getOctcubeIndices(octindex, level, &baseindex, &subindex);
01158         cqc = cqcaa[level][baseindex];
01159         cqcsub = cqcaa[level + 1][subindex];
01160         if (cqcsub->bleaf == 0) {  /* use cell at level above */
01161             *pindex = cqc->index;
01162             *prval = cqc->rc;
01163             *pgval = cqc->gc;
01164             *pbval = cqc->bc;
01165             break;
01166         }
01167         else if (level == CQ_NLEVELS - 1) {  /* reached the bottom */
01168            *pindex = cqcsub->index;
01169            *prval = cqcsub->rc;
01170            *pgval = cqcsub->gc;
01171            *pbval = cqcsub->bc;
01172             break;
01173         }
01174     }
01175 
01176 #if 0
01177         /* Generate rgb values for each cube on the fly; slower */
01178     for (level = 2; level < CQ_NLEVELS; level++) {
01179         l_int32  rv, gv, bv;
01180         getOctcubeIndices(octindex, level, &baseindex, &subindex);
01181         cqc = cqcaa[level][baseindex];
01182         cqcsub = cqcaa[level + 1][subindex];
01183         if (cqcsub->bleaf == 0) {  /* use cell at level above */
01184             getRGBFromOctcube(baseindex, level, &rv, &gv, &bv);
01185             *pindex = cqc->index;
01186             *prval = rv;
01187             *pgval = gv;
01188             *pbval = bv;
01189             break;
01190         }
01191         else if (level == CQ_NLEVELS - 1) {  /* reached the bottom */
01192             getRGBFromOctcube(subindex, level + 1, &rv, &gv, &bv);
01193            *pindex = cqcsub->index;
01194             *prval = rv;
01195             *pgval = gv;
01196             *pbval = bv;
01197             break;
01198         }
01199     }
01200 #endif
01201 
01202     return 0;
01203 }
01204 
01205 
01206 
01207 /*------------------------------------------------------------------*
01208  *                      Helper cqcell functions                     *
01209  *------------------------------------------------------------------*/
01210 /*!
01211  *  cqcellTreeCreate()
01212  *
01213  *      Input:  none
01214  *      Return: cqcell array tree
01215  */
01216 static CQCELL ***
01217 cqcellTreeCreate(void)
01218 {
01219 l_int32    level, ncells, i;
01220 CQCELL  ***cqcaa;  
01221 CQCELL   **cqca;   /* one array for each octree level */
01222 
01223     PROCNAME("cqcellTreeCreate");
01224 
01225         /* Make array of accumulation cell arrays from levels 1 to 5 */
01226     if ((cqcaa = (CQCELL ***)CALLOC(CQ_NLEVELS + 1, sizeof(CQCELL **))) == NULL)
01227         return (CQCELL ***)ERROR_PTR("cqcaa not made", procName, NULL);
01228     for (level = 0; level <= CQ_NLEVELS; level++) {
01229         ncells = 1 << (3 * level);
01230         if ((cqca = (CQCELL **)CALLOC(ncells, sizeof(CQCELL *))) == NULL)
01231             return (CQCELL ***)ERROR_PTR("cqca not made", procName, NULL);
01232         cqcaa[level] = cqca;
01233         for (i = 0; i < ncells; i++) {
01234             if ((cqca[i] = (CQCELL *)CALLOC(1, sizeof(CQCELL))) == NULL)
01235                 return (CQCELL ***)ERROR_PTR("cqc not made", procName, NULL);
01236         }
01237     }
01238 
01239     return cqcaa;
01240 }
01241 
01242 
01243 /*!
01244  *  cqcellTreeDestroy()
01245  *
01246  *      Input:  &cqcaa (<to be nulled>
01247  *      Return: void
01248  */
01249 static void
01250 cqcellTreeDestroy(CQCELL  ****pcqcaa)
01251 {
01252 l_int32    level, ncells, i;
01253 CQCELL  ***cqcaa;
01254 CQCELL   **cqca;
01255 
01256     PROCNAME("cqcellTreeDestroy");
01257 
01258     if (pcqcaa == NULL) {
01259         L_WARNING("ptr address is NULL", procName);
01260         return;
01261     }
01262 
01263     if ((cqcaa = *pcqcaa) == NULL)
01264         return;
01265 
01266     for (level = 0; level <= CQ_NLEVELS; level++) {
01267         cqca = cqcaa[level];
01268         ncells = 1 << (3 * level);
01269         for (i = 0; i < ncells; i++)
01270             FREE(cqca[i]);
01271         FREE(cqca);
01272     }
01273     FREE(cqcaa);
01274     *pcqcaa = NULL;
01275 
01276     return;
01277 }
01278 
01279 
01280 
01281 /*------------------------------------------------------------------*
01282  *                       Helper index functions                     *
01283  *------------------------------------------------------------------*/
01284 /*!
01285  *  makeRGBToIndexTables()
01286  *
01287  *      Input:  &rtab, &gtab, &btab  (<return> tables)
01288  *              cqlevels (can be 1, 2, 3, 4, 5 or 6)
01289  *      Return: 0 if OK; 1 on error
01290  *
01291  *  Set up tables.  e.g., for cqlevels = 5, we need an integer 0 < i < 2^15:
01292  *      rtab = (0  i7  0   0  i6  0   0  i5  0   0   i4  0   0   i3  0   0)
01293  *      gtab = (0  0   i7  0   0  i6  0   0  i5  0   0   i4  0   0   i3  0)
01294  *      btab = (0  0   0   i7  0  0   i6  0  0   i5  0   0   i4  0   0   i3)
01295  *
01296  *  The tables are then used to map from rbg --> index as follows:
01297  *      index = (0  r7  g7  b7  r6  g6  b6  r5  g5  b5  r4  g4  b4  r3  g3  b3)
01298  *
01299  *    e.g., for cqlevels = 4, we map to
01300  *      index = (0  0   0   0   r7  g7  b7  r6  g6  b6  r5  g5  b5  r4  g4  b4)
01301  *
01302  *  This may look a bit strange.  The notation 'r7' means the MSBit of
01303  *  the r value (which has 8 bits, going down from r7 to r0).  
01304  *  Keep in mind that r7 is actually the r component bit for level 1 of
01305  *  the octtree.  Level 1 is composed of 8 octcubes, represented by
01306  *  the bits (r7 g7 b7), which divide the entire color space into
01307  *  8 cubes.  At level 2, each of these 8 octcubes is further divided into
01308  *  8 cubes, each labeled by the second most significant bits (r6 g6 b6)
01309  *  of the rgb color.
01310  */
01311 l_int32
01312 makeRGBToIndexTables(l_uint32  **prtab,
01313                      l_uint32  **pgtab,
01314                      l_uint32  **pbtab,
01315                      l_int32     cqlevels)
01316 {
01317 l_int32    i;
01318 l_uint32  *rtab, *gtab, *btab;
01319 
01320     PROCNAME("makeRGBToIndexTables");
01321 
01322     if (cqlevels < 1 || cqlevels > 6)
01323         return ERROR_INT("cqlevels must be in {1,...6}", procName, 1);
01324 
01325     if (!prtab || !pgtab || !pbtab)
01326         return ERROR_INT("&*tab not defined", procName, 1);
01327     if ((rtab = (l_uint32 *)CALLOC(256, sizeof(l_uint32))) == NULL)
01328         return ERROR_INT("rtab not made", procName, 1);
01329     if ((gtab = (l_uint32 *)CALLOC(256, sizeof(l_uint32))) == NULL)
01330         return ERROR_INT("gtab not made", procName, 1);
01331     if ((btab = (l_uint32 *)CALLOC(256, sizeof(l_uint32))) == NULL)
01332         return ERROR_INT("btab not made", procName, 1);
01333     *prtab = rtab;
01334     *pgtab = gtab;
01335     *pbtab = btab;
01336         
01337     switch (cqlevels)
01338     {
01339     case 1:
01340         for (i = 0; i < 256; i++) {
01341             rtab[i] = (i >> 5) & 0x0004;
01342             gtab[i] = (i >> 6) & 0x0002;
01343             btab[i] = (i >> 7);
01344         }
01345         break;
01346     case 2:
01347         for (i = 0; i < 256; i++) {
01348             rtab[i] = ((i >> 2) & 0x0020) | ((i >> 4) & 0x0004);
01349             gtab[i] = ((i >> 3) & 0x0010) | ((i >> 5) & 0x0002);
01350             btab[i] = ((i >> 4) & 0x0008) | ((i >> 6) & 0x0001);
01351         }
01352         break;
01353     case 3:
01354         for (i = 0; i < 256; i++) {
01355             rtab[i] = ((i << 1) & 0x0100) | ((i >> 1) & 0x0020) |
01356                       ((i >> 3) & 0x0004);
01357             gtab[i] = (i & 0x0080) | ((i >> 2) & 0x0010) |
01358                       ((i >> 4) & 0x0002);
01359             btab[i] = ((i >> 1) & 0x0040) | ((i >> 3) & 0x0008) |
01360                       ((i >> 5) & 0x0001);
01361         }
01362         break;
01363     case 4:
01364         for (i = 0; i < 256; i++) {
01365             rtab[i] = ((i << 4) & 0x0800) | ((i << 2) & 0x0100) |
01366                       (i & 0x0020) | ((i >> 2) & 0x0004);
01367             gtab[i] = ((i << 3) & 0x0400) | ((i << 1) & 0x0080) |
01368                       ((i >> 1) & 0x0010) | ((i >> 3) & 0x0002);
01369             btab[i] = ((i << 2) & 0x0200) | (i & 0x0040) |
01370                       ((i >> 2) & 0x0008) | ((i >> 4) & 0x0001);
01371         }
01372         break;
01373     case 5:
01374         for (i = 0; i < 256; i++) {
01375             rtab[i] = ((i << 7) & 0x4000) | ((i << 5) & 0x0800) |
01376                       ((i << 3) & 0x0100) | ((i << 1) & 0x0020) |
01377                       ((i >> 1) & 0x0004);
01378             gtab[i] = ((i << 6) & 0x2000) | ((i << 4) & 0x0400) |
01379                       ((i << 2) & 0x0080) | (i & 0x0010) |
01380                       ((i >> 2) & 0x0002);
01381             btab[i] = ((i << 5) & 0x1000) | ((i << 3) & 0x0200) |
01382                       ((i << 1) & 0x0040) | ((i >> 1) & 0x0008) |
01383                       ((i >> 3) & 0x0001);
01384         }
01385         break;
01386     case 6:
01387         for (i = 0; i < 256; i++) {
01388             rtab[i] = ((i << 10) & 0x20000) | ((i << 8) & 0x4000) |
01389                       ((i << 6) & 0x0800) | ((i << 4) & 0x0100) |
01390                       ((i << 2) & 0x0020) | (i & 0x0004);
01391             gtab[i] = ((i << 9) & 0x10000) | ((i << 7) & 0x2000) |
01392                       ((i << 5) & 0x0400) | ((i << 3) & 0x0080) |
01393                       ((i << 1) & 0x0010) | ((i >> 1) & 0x0002);
01394             btab[i] = ((i << 8) & 0x8000) | ((i << 6) & 0x1000) |
01395                       ((i << 4) & 0x0200) | ((i << 2) & 0x0040) |
01396                       (i & 0x0008) | ((i >> 2) & 0x0001);
01397         }
01398         break;
01399     default:
01400         ERROR_INT("cqlevels not in [1...6]", procName, 1);
01401         break;
01402     }
01403 
01404     return 0;
01405 }
01406 
01407 
01408 /*!
01409  *  getOctcubeIndexFromRGB()
01410  *
01411  *      Input:  rval, gval, bval
01412  *              rtab, gtab, btab  (generated with makeRGBToIndexTables())
01413  *              &index (<return>)
01414  *      Return: void
01415  *
01416  *  Note: no error checking!
01417  */
01418 void
01419 getOctcubeIndexFromRGB(l_int32    rval,
01420                        l_int32    gval,
01421                        l_int32    bval,
01422                        l_uint32  *rtab,
01423                        l_uint32  *gtab,
01424                        l_uint32  *btab,
01425                        l_uint32  *pindex)
01426 {
01427     *pindex = rtab[rval] | gtab[gval] | btab[bval];
01428     return;
01429 }
01430 
01431 
01432 /*!
01433  *  getRGBFromOctcube()
01434  *
01435  *      Input:  octcube index
01436  *              level (at which index is expressed)
01437  *              &rval  (<return> r val of this cube)
01438  *              &gval  (<return> g val of this cube)
01439  *              &bval  (<return> b val of this cube)
01440  *      Return: void
01441  *
01442  *  Notes:
01443  *      (1) We can consider all octcube indices to represent a
01444  *          specific point in color space: namely, the location
01445  *          of the 'upper-left' corner of the cube, where indices
01446  *          increase down and to the right.  The upper left corner
01447  *          of the color space is then 00000.... 
01448  *      (2) The 'rgbindex' is a 24-bit representation of the location,
01449  *          in octcube notation, at the center of the octcube.
01450  *          To get to the center of an octcube, you choose the 111
01451  *          octcube at the next lower level.
01452  *      (3) For example, if the octcube index = 110101 (binary),
01453  *          which is a level 2 expression, then the rgbindex
01454  *          is the 24-bit representation of 110101111 (at level 3);
01455  *          namely, 000110101111000000000000.  The number is padded
01456  *          with 3 leading 0s (because the representation uses
01457  *          only 21 bits) and 12 trailing 0s (the default for
01458  *          levels 4-7, which are contained within each of the level3
01459  *          octcubes.  Then the rgb values for the center of the
01460  *          octcube are: rval = 11100000, gval = 10100000, bval = 01100000
01461  */
01462 static void
01463 getRGBFromOctcube(l_int32   cubeindex,
01464                   l_int32   level,
01465                   l_int32  *prval,
01466                   l_int32  *pgval,
01467                   l_int32  *pbval)
01468 {
01469 l_int32  rgbindex;
01470 
01471         /* Bring to format in 21 bits: (r7 g7 b7 r6 g6 b6 ...) */
01472         /* This is valid for levels from 0 to 6 */
01473     rgbindex = cubeindex << (3 * (7 - level));  /* upper corner of cube */
01474     rgbindex |= (0x7 << (3 * (6 - level)));   /* index to center of cube */
01475 
01476         /* Extract separate pieces */
01477     *prval = ((rgbindex >> 13) & 0x80) |
01478              ((rgbindex >> 11) & 0x40) |
01479              ((rgbindex >> 9) & 0x20) |
01480              ((rgbindex >> 7) & 0x10) |
01481              ((rgbindex >> 5) & 0x08) |
01482              ((rgbindex >> 3) & 0x04) |
01483              ((rgbindex >> 1) & 0x02);
01484     *pgval = ((rgbindex >> 12) & 0x80) |
01485              ((rgbindex >> 10) & 0x40) |
01486              ((rgbindex >> 8) & 0x20) |
01487              ((rgbindex >> 6) & 0x10) |
01488              ((rgbindex >> 4) & 0x08) |
01489              ((rgbindex >> 2) & 0x04) |
01490              (rgbindex & 0x02);
01491     *pbval = ((rgbindex >> 11) & 0x80) |
01492              ((rgbindex >> 9) & 0x40) |
01493              ((rgbindex >> 7) & 0x20) |
01494              ((rgbindex >> 5) & 0x10) |
01495              ((rgbindex >> 3) & 0x08) |
01496              ((rgbindex >> 1) & 0x04) |
01497              ((rgbindex << 1) & 0x02);
01498 
01499     return;
01500 }
01501 
01502     
01503 /*!
01504  *  getOctcubeIndices()
01505  *
01506  *     Input:  rgbindex
01507  *             octree level (0, 1, 2, 3, 4, 5)
01508  *             &octcube base index (<return> index at the octree level)
01509  *             &octcube sub index (<return> index at the next lower level)
01510  *     Return: 0 if OK, 1 on error
01511  *
01512  *  for CQ_NLEVELS = 6, the full RGB index is in the form:
01513  *     index = (0[13] 0 r7 g7 b7 r6 g6 b6 r5 g5 b5 r4 g4 b4 r3 g3 b3 r2 g2 b2)
01514  *  for CQ_NLEVELS = 5, the full RGB index is in the form:
01515  *     index = (0[16] 0 r7 g7 b7 r6 g6 b6 r5 g5 b5 r4 g4 b4 r3 g3 b3)
01516  *  for CQ_NLEVELS = 4, the full RGB index is in the form:
01517  *     index = (0[19] 0 r7 g7 b7 r6 g6 b6 r5 g5 b5 r4 g4 b4)
01518  *
01519  *  The base index is the index of the octcube at the level given,
01520  *  whereas the sub index is the index at the next level down.
01521  *
01522  *  For level 0: base index = 0
01523  *               sub index is the 3 bit number (r7 g7 b7)
01524  *  For level 1: base index = (r7 g7 b7)
01525  *               sub index = (r7 g7 b7 r6 g6 b6)
01526  *  For level 2: base index = (r7 g7 b7 r6 g6 b6)
01527  *               sub index = (r7 g7 b7 r6 g6 b6 r5 g5 b5)
01528  *  For level 3: base index = (r7 g7 b7 r6 g6 b6 r5 g5 b5)
01529  *               sub index = (r7 g7 b7 r6 g6 b6 r5 g5 b5 r4 g4 b4)
01530  *  For level 4: base index = (r7 g7 b7 r6 g6 b6 r5 g5 b5 r4 g4 b4)
01531  *               sub index = (r7 g7 b7 r6 g6 b6 r5 g5 b5 r4 g4 b4 r3 g3 b3)
01532  *  For level 5: base index = (r7 g7 b7 r6 g6 b6 r5 g5 b5 r4 g4 b4 r3 g3 b3)
01533  *               sub index = (r7 g7 b7 r6 g6 b6 r5 g5 b5 r4 g4 b4 r3 g3 b3
01534  *                            r2 g2 b2)
01535  */
01536 static l_int32
01537 getOctcubeIndices(l_int32   rgbindex,
01538                   l_int32   level,
01539                   l_int32  *pbindex,
01540                   l_int32  *psindex)
01541 {
01542     PROCNAME("getOctcubeIndex");
01543 
01544     if (level < 0 || level > CQ_NLEVELS - 1)
01545         return ERROR_INT("level must be in e.g., [0 ... 5]", procName, 1);
01546     if (!pbindex)
01547         return ERROR_INT("&bindex not defined", procName, 1);
01548     if (!psindex)
01549         return ERROR_INT("&sindex not defined", procName, 1);
01550 
01551     *pbindex = rgbindex >> (3 * (CQ_NLEVELS - level));
01552     *psindex = rgbindex >> (3 * (CQ_NLEVELS - 1 - level));
01553     return 0;
01554 }
01555 
01556 
01557 /*!
01558  *  octcubeGetCount()
01559  *
01560  *      Input:  level (valid values are in [1,...6]; there are 2^level
01561  *                     cubes along each side of the rgb cube)
01562  *              &size (<return> 2^(3 * level) cubes in the entire rgb cube)
01563  *      Return:  0 if OK, 1 on error.  Caller must check!
01564  *
01565  *         level:   1        2        3        4        5        6
01566  *         size:    8       64       512     4098     32784   262272
01567  */
01568 static l_int32
01569 octcubeGetCount(l_int32   level,
01570                 l_int32  *psize)
01571 {
01572     PROCNAME("octcubeGetCount");
01573 
01574     if (!psize)
01575         return ERROR_INT("&size not defined", procName, 1);
01576     if (level < 1 || level > 6)
01577         return ERROR_INT("invalid level", procName, 1);
01578 
01579     *psize = 1 << (3 * level);
01580     return 0;
01581 }
01582 
01583 
01584 /*---------------------------------------------------------------------------*
01585  *      Adaptive octree quantization based on population at a fixed level    *
01586  *---------------------------------------------------------------------------*/
01587 /*!
01588  *  pixOctreeQuantByPopulation()
01589  *
01590  *      Input:  pixs (32 bpp rgb)
01591  *              level (significant bits for each of RGB; valid for {3,4},
01592  *                     Use 0 for default (level 4; recommended)
01593  *              ditherflag  (1 to dither, 0 otherwise)
01594  *      Return: pixd (quantized to octcubes) or null on error
01595  *
01596  *  Notes:
01597  *      (1) This color quantization method works very well without
01598  *          dithering, using octcubes at two different levels:
01599  *            (a) the input @level, which is either 3 or 4
01600  *            (b) level 2 (64 octcubes to cover the entire color space)
01601  *      (2) For best results, using @level = 4 is recommended.
01602  *          Why do we provide an option for using level 3?  Because
01603  *          there are 512 octcubes at level 3, and for many images
01604  *          not more than 256 are filled.  As a result, on some images
01605  *          a very accurate quantized representation is possible using
01606  *          @level = 3.
01607  *      (3) This first breaks up the color space into octcubes at the
01608  *          input @level, and computes, for each octcube, the average
01609  *          value of the pixels that are in it.
01610  *      (4) Then there are two possible situations:
01611  *            (a) If there are not more than 256 populated octcubes,
01612  *                it returns a cmapped pix with those values assigned.
01613  *            (b) Otherwise, it selects 192 octcubes containing the largest
01614  *                number of pixels and quantizes pixels within those octcubes
01615  *                to their average.  Then, to handle the residual pixels
01616  *                that are not in those 192 octcubes, it generates a
01617  *                level 2 octree consisting of 64 octcubes, and within
01618  *                each octcube it quantizes the residual pixels to their
01619  *                average within each of those level 2 octcubes.
01620  *      (5) Unpopulated level 2 octcubes are represented in the colormap
01621  *          by their centers.  This, of course, has no effect unless
01622  *          dithering is used for the output image.
01623  *      (6) The depth of pixd is the minumum required to suppport the
01624  *          number of colors found at @level; namely, 2, 4 or 8.
01625  *      (7) This function works particularly well on images such as maps,
01626  *          where there are a relatively small number of well-populated
01627  *          colors, but due to antialiasing and compression artifacts
01628  *          there may be a large number of different colors.  This will
01629  *          pull out and represent accurately the highly populated colors,
01630  *          while still making a reasonable approximation for the others.
01631  *      (8) The highest level of octcubes allowed is 4.  Use of higher
01632  *          levels typically results in having a small fraction of
01633  *          pixels in the most populated 192 octcubes.  As a result,
01634  *          most of the pixels are represented at level 2, which is
01635  *          not sufficiently accurate.
01636  *      (9) Dithering shows artifacts on some images.  If you plan to
01637  *          dither, pixOctreeColorQuant() and pixFixedOctcubeQuant256()
01638  *          usually give better results.
01639  */     
01640 PIX *
01641 pixOctreeQuantByPopulation(PIX     *pixs,
01642                            l_int32  level,
01643                            l_int32  ditherflag)
01644 {
01645 l_int32         w, h, wpls, wpld, i, j, depth, size, ncolors, index;
01646 l_int32         rval, gval, bval;
01647 l_int32        *rarray, *garray, *barray, *narray, *iarray;
01648 l_uint32        octindex, octindex2;
01649 l_uint32       *rtab, *gtab, *btab, *rtab2, *gtab2, *btab2;
01650 l_uint32       *lines, *lined, *datas, *datad;
01651 L_OCTCUBE_POP  *opop;
01652 L_HEAP         *lh;
01653 PIX            *pixd;
01654 PIXCMAP        *cmap;
01655 
01656     PROCNAME("pixOctreeQuantByPopulation");
01657 
01658     if (!pixs)
01659         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
01660     if (pixGetDepth(pixs) != 32)
01661         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
01662     if (level == 0) level = 4;
01663     if (level < 3 || level > 4)
01664         return (PIX *)ERROR_PTR("level not in {3,4}", procName, NULL);
01665 
01666         /* Do not dither if image is very small */
01667     pixGetDimensions(pixs, &w, &h, NULL);
01668     if (w < MIN_DITHER_SIZE && h < MIN_DITHER_SIZE && ditherflag == 1) {
01669         L_INFO("Small image: dithering turned off", procName);
01670         ditherflag = 0;
01671     }
01672 
01673     if (octcubeGetCount(level, &size))  /* array size = 2 ** (3 * level) */
01674         return (PIX *)ERROR_PTR("size not returned", procName, NULL);
01675     if (makeRGBToIndexTables(&rtab, &gtab, &btab, level))
01676         return (PIX *)ERROR_PTR("tables not made", procName, NULL);
01677 
01678     if ((narray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
01679         return (PIX *)ERROR_PTR("narray not made", procName, NULL);
01680     if ((rarray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
01681         return (PIX *)ERROR_PTR("rarray not made", procName, NULL);
01682     if ((garray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
01683         return (PIX *)ERROR_PTR("garray not made", procName, NULL);
01684     if ((barray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
01685         return (PIX *)ERROR_PTR("barray not made", procName, NULL);
01686 
01687         /* Place the pixels in octcube leaves. */
01688     datas = pixGetData(pixs);
01689     wpls = pixGetWpl(pixs);
01690     pixd = NULL;
01691     for (i = 0; i < h; i++) {
01692         lines = datas + i * wpls;
01693         for (j = 0; j < w; j++) {
01694             extractRGBValues(lines[j], &rval, &gval, &bval);
01695             octindex = rtab[rval] | gtab[gval] | btab[bval];
01696             narray[octindex]++;
01697             rarray[octindex] += rval;
01698             garray[octindex] += gval;
01699             barray[octindex] += bval;
01700         }
01701     }
01702 
01703         /* Find the number of different colors */
01704     for (i = 0, ncolors = 0; i < size; i++) {
01705         if (narray[i] > 0)
01706             ncolors++;
01707     }
01708     if (ncolors <= 4)
01709         depth = 2;
01710     else if (ncolors <= 16)
01711         depth = 4;
01712     else
01713         depth = 8;
01714     pixd = pixCreate(w, h, depth);
01715     datad = pixGetData(pixd);
01716     wpld = pixGetWpl(pixd);
01717     pixCopyResolution(pixd, pixs);
01718     pixCopyInputFormat(pixd, pixs);
01719     cmap = pixcmapCreate(depth);
01720     pixSetColormap(pixd, cmap);
01721 
01722         /* Average the colors in each octcube leaf. */
01723     for (i = 0; i < size; i++) {
01724         if (narray[i] > 0) {
01725             rarray[i] /= narray[i];
01726             garray[i] /= narray[i];
01727             barray[i] /= narray[i];
01728         }
01729     }
01730 
01731         /* If ncolors <= 256, finish immediately.  Do not dither.
01732          * Re-use narray to hold the colormap index + 1  */
01733     if (ncolors <= 256) {
01734         for (i = 0, index = 0; i < size; i++) {
01735             if (narray[i] > 0) {
01736                 pixcmapAddColor(cmap, rarray[i], garray[i], barray[i]);
01737                 narray[i] = index + 1;  /* to avoid storing 0 */
01738                 index++;
01739             }
01740         }
01741 
01742             /* Set the cmap indices for each pixel */
01743         for (i = 0; i < h; i++) {
01744             lines = datas + i * wpls;
01745             lined = datad + i * wpld;
01746             for (j = 0; j < w; j++) {
01747                 extractRGBValues(lines[j], &rval, &gval, &bval);
01748                 octindex = rtab[rval] | gtab[gval] | btab[bval];
01749                 switch (depth) 
01750                 {
01751                 case 8:
01752                     SET_DATA_BYTE(lined, j, narray[octindex] - 1);
01753                     break;
01754                 case 4:
01755                     SET_DATA_QBIT(lined, j, narray[octindex] - 1);
01756                     break;
01757                 case 2:
01758                     SET_DATA_DIBIT(lined, j, narray[octindex] - 1);
01759                     break;
01760                 default:
01761                     L_WARNING("shouldn't get here", procName);
01762                 }
01763             }
01764         }
01765         goto array_cleanup;
01766     }
01767 
01768         /* More complicated.  Sort by decreasing population */
01769     lh = lheapCreate(500, L_SORT_DECREASING);
01770     for (i = 0; i < size; i++) {
01771         if (narray[i] > 0) {
01772             opop = (L_OCTCUBE_POP *)CALLOC(1, sizeof(L_OCTCUBE_POP));
01773             opop->npix = (l_float32)narray[i];
01774             opop->index = i;
01775             opop->rval = rarray[i];
01776             opop->gval = garray[i];
01777             opop->bval = barray[i];
01778             lheapAdd(lh, opop);
01779         }
01780     }
01781 
01782         /* Take the top 192.  These will form the first 192 colors
01783          * in the cmap.  iarray[i] holds the index into the cmap. */
01784     if ((iarray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
01785         return (PIX *)ERROR_PTR("iarray not made", procName, NULL);
01786     for (i = 0; i < 192; i++) {
01787         opop = (L_OCTCUBE_POP*)lheapRemove(lh);
01788         if (!opop) break;
01789         pixcmapAddColor(cmap, opop->rval, opop->gval, opop->bval);
01790         iarray[opop->index] = i + 1;  /* +1 to avoid storing 0 */
01791 
01792 #if DEBUG_POP
01793         fprintf(stderr, "i = %d, n = %6.0f, (r,g,b) = (%d %d %d)\n",
01794                 i, opop->npix, opop->rval, opop->gval, opop->bval);
01795 #endif  /* DEBUG_POP */
01796 
01797         FREE(opop);
01798     }
01799 
01800         /* Make the octindex tables for level 2, and reuse rarray, etc. */
01801     if (makeRGBToIndexTables(&rtab2, &gtab2, &btab2, 2))
01802         return (PIX *)ERROR_PTR("level 2 tables not made", procName, NULL);
01803     for (i = 0; i < 64; i++) {
01804         narray[i] = 0;
01805         rarray[i] = 0;
01806         garray[i] = 0;
01807         barray[i] = 0;
01808     }
01809 
01810         /* Take the rest of the occupied octcubes, assigning the pixels
01811          * to these new colormap indices.  iarray[] is addressed
01812          * by @level octcube indices, and it now holds the
01813          * colormap indices for all pixels in pixs.  */
01814     for (i = 192; i < size; i++) {
01815         opop = (L_OCTCUBE_POP*)lheapRemove(lh);
01816         if (!opop) break;
01817         rval = opop->rval;
01818         gval = opop->gval;
01819         bval = opop->bval;
01820         octindex2 = rtab2[rval] | gtab2[gval] | btab2[bval];
01821         narray[octindex2] += (l_int32)opop->npix;
01822         rarray[octindex2] += (l_int32)opop->npix * rval;
01823         garray[octindex2] += (l_int32)opop->npix * gval;
01824         barray[octindex2] += (l_int32)opop->npix * bval;
01825         iarray[opop->index] = 192 + octindex2 + 1;  /* +1 to avoid storing 0 */
01826         FREE(opop);
01827     }
01828     lheapDestroy(&lh, TRUE);
01829 
01830         /* To span the full color space, which is necessary for dithering,
01831          * set each iarray element whose value is still 0 at the input
01832          * level octcube leaves (because there were no pixels in those
01833          * octcubes) to the colormap index corresponding to its level 2
01834          * octcube. */
01835     if (ditherflag) {
01836         for (i = 0; i < size; i++) {
01837             if (iarray[i] == 0) {
01838                 getRGBFromOctcube(i, level, &rval, &gval, &bval);
01839                 octindex2 = rtab2[rval] | gtab2[gval] | btab2[bval];
01840                 iarray[i] = 192 + octindex2 + 1;
01841             }
01842         }
01843     }
01844     FREE(rtab2);
01845     FREE(gtab2);
01846     FREE(btab2);
01847 
01848         /* Average the colors from the residuals in each level 2 octcube,
01849          * and add these 64 values to the colormap. */
01850     for (i = 0; i < 64; i++) {
01851         if (narray[i] > 0) {
01852             rarray[i] /= narray[i];
01853             garray[i] /= narray[i];
01854             barray[i] /= narray[i];
01855         }
01856         else   /* no pixels in this octcube; use center value */
01857             getRGBFromOctcube(i, 2, &rarray[i], &garray[i], &barray[i]);
01858         pixcmapAddColor(cmap, rarray[i], garray[i], barray[i]);
01859     }
01860 
01861         /* Set the cmap indices for each pixel.  Subtract 1 from
01862          * the value in iarray[] because we added 1 earlier.  */
01863     if (ditherflag == 0) {
01864         for (i = 0; i < h; i++) {
01865             lines = datas + i * wpls;
01866             lined = datad + i * wpld;
01867             for (j = 0; j < w; j++) {
01868                 extractRGBValues(lines[j], &rval, &gval, &bval);
01869                 octindex = rtab[rval] | gtab[gval] | btab[bval];
01870                 SET_DATA_BYTE(lined, j, iarray[octindex] - 1);
01871             }
01872         }
01873     }
01874     else   /* dither */
01875         pixDitherOctindexWithCmap(pixs, pixd, rtab, gtab, btab,
01876                                   iarray, POP_DIF_CAP);
01877 
01878 #if DEBUG_POP
01879     for (i = 0; i < size / 16; i++) {
01880         l_int32 j;
01881         for (j = 0; j < 16; j++)
01882             fprintf(stderr, "%d ", iarray[16 * i + j]);
01883         fprintf(stderr, "\n");
01884     }
01885 #endif  /* DEBUG_POP */
01886 
01887     FREE(iarray);
01888 
01889 array_cleanup:
01890     FREE(narray);
01891     FREE(rarray);
01892     FREE(garray);
01893     FREE(barray);
01894     FREE(rtab);
01895     FREE(gtab);
01896     FREE(btab);
01897 
01898     return pixd;
01899 }
01900 
01901 
01902 /*!
01903  *  pixDitherOctindexWithCmap()
01904  *
01905  *      Input:  pixs (32 bpp rgb)
01906  *              pixd (8 bpp cmapped)
01907  *              rtab, gtab, btab (tables from rval to octindex)
01908  *              indexmap (array mapping octindex to cmap index)
01909  *              difcap (max allowed dither transfer; use 0 for infinite cap)
01910  *      Return: 0 if OK, 1 on error
01911  *
01912  *  Notes:
01913  *      (1) This performs dithering to generate the colormap indices
01914  *          in pixd.  The colormap has been calculated, along with
01915  *          four input LUTs that together give the inverse colormapping
01916  *          from RGB to colormap index.
01917  *      (2) For pixOctreeQuantByPopulation(), @indexmap maps from the
01918  *          standard octindex to colormap index (after subtracting 1).
01919  *          The basic pixel-level function, without dithering, is:
01920  *             extractRGBValues(lines[j], &rval, &gval, &bval);
01921  *             octindex = rtab[rval] | gtab[gval] | btab[bval];
01922  *             SET_DATA_BYTE(lined, j, indexmap[octindex] - 1);
01923  *      (3) This can be used in any situation where the general
01924  *          prescription for finding the colormap index from the rgb
01925  *          value is precisely this:
01926  *             cmapindex = indexmap[rtab[rval] | gtab[gval] | btab[bval]] - 1
01927  *          For example, in pixFixedOctcubeQuant256(), we don't use
01928  *          standard octcube indexing, the rtab (etc) LUTs map directly
01929  *          to the colormap index, and @indexmap just compensates for
01930  *          the 1-off indexing assumed to be in that table.
01931  */
01932 static l_int32
01933 pixDitherOctindexWithCmap(PIX       *pixs,
01934                           PIX       *pixd,
01935                           l_uint32  *rtab,
01936                           l_uint32  *gtab,
01937                           l_uint32  *btab,
01938                           l_int32   *indexmap,
01939                           l_int32    difcap)
01940 {
01941 l_uint8   *bufu8r, *bufu8g, *bufu8b;
01942 l_int32    i, j, w, h, wpld, octindex, cmapindex;
01943 l_int32    rval, gval, bval, rc, gc, bc;
01944 l_int32    dif, val1, val2, val3;
01945 l_int32   *buf1r, *buf1g, *buf1b, *buf2r, *buf2g, *buf2b;
01946 l_uint32  *datad, *lined;
01947 PIXCMAP   *cmap;
01948 
01949     PROCNAME("pixDitherOctindexWithCmap");
01950 
01951     if (!pixs || pixGetDepth(pixs) != 32)
01952         return ERROR_INT("pixs undefined or not 32 bpp", procName, 1);
01953     if (!pixd || pixGetDepth(pixd) != 8)
01954         return ERROR_INT("pixd undefined or not 8 bpp", procName, 1);
01955     if ((cmap = pixGetColormap(pixd)) == NULL)
01956         return ERROR_INT("pixd not cmapped", procName, 1);
01957     if (!rtab || !gtab || !btab || !indexmap)
01958         return ERROR_INT("not all 4 tables defined", procName, 1);
01959     pixGetDimensions(pixs, &w, &h, NULL);
01960     if (pixGetWidth(pixd) != w || pixGetHeight(pixd) != h)
01961         return ERROR_INT("pixs and pixd not same size", procName, 1);
01962 
01963     bufu8r = (l_uint8 *)CALLOC(w, sizeof(l_uint8));
01964     bufu8g = (l_uint8 *)CALLOC(w, sizeof(l_uint8));
01965     bufu8b = (l_uint8 *)CALLOC(w, sizeof(l_uint8));
01966     buf1r = (l_int32 *)CALLOC(w, sizeof(l_int32));
01967     buf1g = (l_int32 *)CALLOC(w, sizeof(l_int32));
01968     buf1b = (l_int32 *)CALLOC(w, sizeof(l_int32));
01969     buf2r = (l_int32 *)CALLOC(w, sizeof(l_int32));
01970     buf2g = (l_int32 *)CALLOC(w, sizeof(l_int32));
01971     buf2b = (l_int32 *)CALLOC(w, sizeof(l_int32));
01972     if (!bufu8r || !bufu8g || !bufu8b)
01973         return ERROR_INT("uint8 line buf not made", procName, 1);
01974     if (!buf1r || !buf1g || !buf1b || !buf2r || !buf2g || !buf2b)
01975         return ERROR_INT("mono line buf not made", procName, 1);
01976 
01977         /* Start by priming buf2; line 1 is above line 2 */
01978     pixGetRGBLine(pixs, 0, bufu8r, bufu8g, bufu8b);
01979     for (j = 0; j < w; j++) {
01980         buf2r[j] = 64 * bufu8r[j];
01981         buf2g[j] = 64 * bufu8g[j];
01982         buf2b[j] = 64 * bufu8b[j];
01983     }
01984 
01985     datad = pixGetData(pixd);
01986     wpld = pixGetWpl(pixd);
01987     for (i = 0; i < h - 1; i++) {
01988             /* Swap data 2 --> 1, and read in new line 2 */
01989         memcpy(buf1r, buf2r, 4 * w);
01990         memcpy(buf1g, buf2g, 4 * w);
01991         memcpy(buf1b, buf2b, 4 * w);
01992         pixGetRGBLine(pixs, i + 1, bufu8r, bufu8g, bufu8b);
01993         for (j = 0; j < w; j++) {
01994             buf2r[j] = 64 * bufu8r[j];
01995             buf2g[j] = 64 * bufu8g[j];
01996             buf2b[j] = 64 * bufu8b[j];
01997         }
01998 
01999             /* Dither */
02000         lined = datad + i * wpld;
02001         for (j = 0; j < w - 1; j++) {
02002             rval = buf1r[j] / 64;
02003             gval = buf1g[j] / 64;
02004             bval = buf1b[j] / 64;
02005             octindex = rtab[rval] | gtab[gval] | btab[bval];
02006             cmapindex = indexmap[octindex] - 1;
02007             SET_DATA_BYTE(lined, j, cmapindex);
02008             pixcmapGetColor(cmap, cmapindex, &rc, &gc, &bc);
02009 
02010             dif = buf1r[j] / 8 - 8 * rc;
02011             if (difcap > 0) {
02012                 if (dif > difcap) dif = difcap;
02013                 if (dif < -difcap) dif = -difcap;
02014             }
02015             if (dif != 0) {
02016                 val1 = buf1r[j + 1] + 3 * dif;
02017                 val2 = buf2r[j] + 3 * dif;
02018                 val3 = buf2r[j + 1] + 2 * dif;
02019                 if (dif > 0) {
02020                     buf1r[j + 1] = L_MIN(16383, val1);
02021                     buf2r[j] = L_MIN(16383, val2);
02022                     buf2r[j + 1] = L_MIN(16383, val3);
02023                 }
02024                 else if (dif < 0) {
02025                     buf1r[j + 1] = L_MAX(0, val1);
02026                     buf2r[j] = L_MAX(0, val2);
02027                     buf2r[j + 1] = L_MAX(0, val3);
02028                 }
02029             }
02030 
02031             dif = buf1g[j] / 8 - 8 * gc;
02032             if (difcap > 0) {
02033                 if (dif > difcap) dif = difcap;
02034                 if (dif < -difcap) dif = -difcap;
02035             }
02036             if (dif != 0) {
02037                 val1 = buf1g[j + 1] + 3 * dif;
02038                 val2 = buf2g[j] + 3 * dif;
02039                 val3 = buf2g[j + 1] + 2 * dif;
02040                 if (dif > 0) {
02041                     buf1g[j + 1] = L_MIN(16383, val1);
02042                     buf2g[j] = L_MIN(16383, val2);
02043                     buf2g[j + 1] = L_MIN(16383, val3);
02044                 }
02045                 else if (dif < 0) {
02046                     buf1g[j + 1] = L_MAX(0, val1);
02047                     buf2g[j] = L_MAX(0, val2);
02048                     buf2g[j + 1] = L_MAX(0, val3);
02049                 }
02050             }
02051 
02052             dif = buf1b[j] / 8 - 8 * bc;
02053             if (difcap > 0) {
02054                 if (dif > difcap) dif = difcap;
02055                 if (dif < -difcap) dif = -difcap;
02056             }
02057             if (dif != 0) {
02058                 val1 = buf1b[j + 1] + 3 * dif;
02059                 val2 = buf2b[j] + 3 * dif;
02060                 val3 = buf2b[j + 1] + 2 * dif;
02061                 if (dif > 0) {
02062                     buf1b[j + 1] = L_MIN(16383, val1);
02063                     buf2b[j] = L_MIN(16383, val2);
02064                     buf2b[j + 1] = L_MIN(16383, val3);
02065                 }
02066                 else if (dif < 0) {
02067                     buf1b[j + 1] = L_MAX(0, val1);
02068                     buf2b[j] = L_MAX(0, val2);
02069                     buf2b[j + 1] = L_MAX(0, val3);
02070                 }
02071             }
02072         }
02073 
02074             /* Get last pixel in row; no downward propagation */
02075         rval = buf1r[w - 1] / 64;
02076         gval = buf1g[w - 1] / 64;
02077         bval = buf1b[w - 1] / 64;
02078         octindex = rtab[rval] | gtab[gval] | btab[bval];
02079         cmapindex = indexmap[octindex] - 1;
02080         SET_DATA_BYTE(lined, w - 1, cmapindex);
02081     }
02082 
02083         /* Get last row of pixels; no leftward propagation */
02084     lined = datad + (h - 1) * wpld;
02085     for (j = 0; j < w; j++) {
02086         rval = buf2r[j] / 64;
02087         gval = buf2g[j] / 64;
02088         bval = buf2b[j] / 64;
02089         octindex = rtab[rval] | gtab[gval] | btab[bval];
02090         cmapindex = indexmap[octindex] - 1;
02091         SET_DATA_BYTE(lined, j, cmapindex);
02092     }
02093 
02094     FREE(bufu8r);
02095     FREE(bufu8g);
02096     FREE(bufu8b);
02097     FREE(buf1r);
02098     FREE(buf1g);
02099     FREE(buf1b);
02100     FREE(buf2r);
02101     FREE(buf2g);
02102     FREE(buf2b);
02103 
02104     return 0;
02105 }
02106 
02107 
02108 /*---------------------------------------------------------------------------*
02109  *         Adaptive octree quantization to 4 and 8 bpp with max colors       *
02110  *---------------------------------------------------------------------------*/
02111 /*!
02112  *  pixOctreeQuantNumColors()
02113  *
02114  *      Input:  pixs (32 bpp rgb)
02115  *              maxcolors (8 to 256; the actual number of colors used
02116  *                         may be less than this)
02117  *              subsample (factor for computing color distribution;
02118  *                         use 0 for default)
02119  *      Return: pixd (4 or 8 bpp, colormapped), or null on error
02120  *
02121  *  pixOctreeColorQuant() is very flexible in terms of the relative
02122  *  depth of different cubes of the octree.   By contrast, this function,
02123  *  pixOctreeQuantNumColors() is also adaptive, but it supports octcube
02124  *  leaves at only two depths: a smaller depth that guarantees
02125  *  full coverage of the color space and octcubes at one level
02126  *  deeper for more accurate colors.  Its main virutes are simplicity
02127  *  and speed, which are both derived from the natural indexing of
02128  *  the octcubes from the RGB values.
02129  *
02130  *  Before describing pixOctreeQuantNumColors(), consider an even simpler
02131  *  approach for 4 bpp with either 8 or 16 colors.  With 8 colors,
02132  *  you simply go to level 1 octcubes and use the average color
02133  *  found in each cube.  For 16 colors, you find which of the three
02134  *  colors has the largest variance at the second level, and use two
02135  *  indices for that color.  The result is quite poor, because (1) some
02136  *  of the cubes are nearly empty and (2) you don't get much color
02137  *  differentiation for the extra 8 colors.  Trust me, this method may
02138  *  be simple, but it isn't worth anything.
02139  *
02140  *  In pixOctreeQuantNumColors(), we generate colormapped images at
02141  *  either 4 bpp or 8 bpp.  For 4 bpp, we have a minimum of 8 colors
02142  *  for the level 1 octcubes, plus up to 8 additional colors that
02143  *  are determined from the level 2 popularity.  If the number of colors
02144  *  is between 8 and 16, the output is a 4 bpp image.  If the number of
02145  *  colors is greater than 16, the output is a 8 bpp image.
02146  *
02147  *  We use a priority queue, implemented with a heap, to select the
02148  *  requisite number of most populated octcubes at the deepest level
02149  *  (level 2 for 64 or fewer colors; level 3 for more than 64 colors).
02150  *  These are combined with one color for each octcube one level above,
02151  *  which is used to span the color space of octcubes that were not
02152  *  included at the deeper level.
02153  *
02154  *  If the deepest level is 2, we combine the popular level 2 octcubes
02155  *  (out of a total of 64) with the 8 level 1 octcubes.  If the deepest
02156  *  level is 3, we combine the popular level 3 octcubes (out of a
02157  *  total 512) with the 64 level 2 octcubes that span the color space.
02158  *  In the latter case, we require a minimum of 64 colors for the level 2
02159  *  octcubes, plus up to 192 additional colors determined from level 3
02160  *  popularity.
02161  *
02162  *  The parameter 'maxlevel' is the deepest octcube level that is used.
02163  *  The implementation also uses two LUTs, which are employed in
02164  *  two successive traversals of the dest image.  The first maps
02165  *  from the src octindex at 'maxlevel' to the color table index,
02166  *  which is the value that is stored in the 4 or 8 bpp dest pixel.
02167  *  The second LUT maps from that colormap value in the dest to a
02168  *  new colormap value for a minimum sized colormap, stored back in
02169  *  the dest.  It is used to remove any color map entries that
02170  *  correspond to color space regions that have no pixels in the
02171  *  source image.  These regions can be either from the higher level
02172  *  (e.g., level 1 for 4 bpp), or from octcubes at 'maxlevel' that
02173  *  are unoccupied.  This remapping results in the minimum number
02174  *  of colors used according to the constraints induced by the
02175  *  input 'maxcolors'.  We also compute the average R, G and B color
02176  *  values in each region of the color space represented by a
02177  *  colormap entry, and store them in the colormap.
02178  *
02179  *  The maximum number of colors is input, which determines the
02180  *  following properties of the dest image and octcube regions used:
02181  *
02182  *     Number of colors      dest image depth      maxlevel
02183  *     ----------------      ----------------      --------
02184  *       8 to 16                  4 bpp               2
02185  *       17 to 64                 8 bpp               2
02186  *       65 to 256                8 bpp               3
02187  *
02188  *  It may turn out that the number of extra colors, beyond the
02189  *  minimum (8 and 64 for maxlevel 2 and 3, respectively), is larger
02190  *  than the actual number of occupied cubes at these levels
02191  *  In that case, all the pixels are contained in this
02192  *  subset of cubes at maxlevel, and no colormap colors are needed
02193  *  to represent the remainder pixels one level above.  Thus, for
02194  *  example, in use one often finds that the pixels in an image
02195  *  occupy less than 192 octcubes at level 3, so they can be represented
02196  *  by a colormap for octcubes at level 3 only.
02197  */     
02198 PIX *
02199 pixOctreeQuantNumColors(PIX     *pixs,
02200                         l_int32  maxcolors,
02201                         l_int32  subsample)
02202 {
02203 l_int32    w, h, minside, bpp, wpls, wpld, i, j, actualcolors;
02204 l_int32    rval, gval, bval, nbase, nextra, maxlevel, ncubes, val;
02205 l_int32   *lut1, *lut2;
02206 l_uint32   index;
02207 l_uint32  *lines, *lined, *datas, *datad, *pspixel;
02208 l_uint32  *rtab, *gtab, *btab;
02209 OQCELL    *oqc;
02210 OQCELL   **oqca;
02211 L_HEAP    *lh;
02212 PIX       *pixd;
02213 PIXCMAP   *cmap;
02214 
02215     PROCNAME("pixOctreeQuantNumColors");
02216 
02217     if (!pixs)
02218         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
02219     if (pixGetDepth(pixs) != 32)
02220         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
02221 
02222     pixGetDimensions(pixs, &w, &h, NULL);
02223     datas = pixGetData(pixs);
02224     wpls = pixGetWpl(pixs);
02225     minside = L_MIN(w, h);
02226     if (subsample <= 0) {
02227        subsample = L_MAX(1, minside / 200);
02228     }
02229 
02230     if (maxcolors >= 8 && maxcolors <= 16) {
02231         bpp = 4;
02232         pixd = pixCreate(w, h, bpp);
02233         maxlevel = 2;
02234         ncubes = 64;   /* 2^6 */
02235         nbase = 8;
02236         nextra = maxcolors - nbase;
02237     }
02238     else if (maxcolors < 64) {
02239         bpp = 8;
02240         pixd = pixCreate(w, h, bpp);
02241         maxlevel = 2;
02242         ncubes = 64;  /* 2^6 */
02243         nbase = 8;
02244         nextra = maxcolors - nbase;
02245     }
02246     else if (maxcolors >= 64 && maxcolors <= 256) {
02247         bpp = 8;
02248         pixd = pixCreate(w, h, bpp);
02249         maxlevel = 3;
02250         ncubes = 512;  /* 2^9 */
02251         nbase = 64;
02252         nextra = maxcolors - nbase;
02253     }
02254     else
02255         return (PIX *)ERROR_PTR("maxcolors not in {8...256}", procName, NULL);
02256 
02257     pixCopyResolution(pixd, pixs);
02258     pixCopyInputFormat(pixd, pixs);
02259 
02260         /*----------------------------------------------------------*
02261          * If we're using the minimum number of colors, it is       *
02262          * much simpler.  We just use 'nbase' octcubes.             *
02263          * For this case, we don't eliminate any extra colors.      *
02264          *----------------------------------------------------------*/
02265     if (nextra == 0) {
02266             /* prepare the OctcubeQuantCell array */
02267         if ((oqca = (OQCELL **)CALLOC(nbase, sizeof(OQCELL *))) == NULL)
02268             return (PIX *)ERROR_PTR("oqca not made", procName, NULL);
02269         for (i = 0; i < nbase; i++) {
02270             oqca[i] = (OQCELL *)CALLOC(1, sizeof(OQCELL));
02271             oqca[i]->n = 0.0;
02272         }
02273 
02274         makeRGBToIndexTables(&rtab, &gtab, &btab, maxlevel - 1);
02275 
02276             /* Go through the entire image, gathering statistics and
02277              * assigning pixels to their quantized value */
02278         datad = pixGetData(pixd);
02279         wpld = pixGetWpl(pixd);
02280         for (i = 0; i < h; i++) {
02281             lines = datas + i * wpls;
02282             lined = datad + i * wpld;
02283             for (j = 0; j < w; j++) {
02284                 pspixel = lines + j;
02285                 extractRGBValues(*pspixel, &rval, &gval, &bval);
02286                 getOctcubeIndexFromRGB(rval, gval, bval,
02287                                        rtab, gtab, btab, &index);
02288 /*                fprintf(stderr, "rval = %d, gval = %d, bval = %d, index = %d\n",
02289                         rval, gval, bval, index); */
02290                 switch (bpp) {
02291                 case 4:
02292                     SET_DATA_QBIT(lined, j, index);
02293                     break;
02294                 case 8:
02295                     SET_DATA_BYTE(lined, j, index);
02296                     break;
02297                 default:
02298                     return (PIX *)ERROR_PTR("bpp not 4 or 8!", procName, NULL);
02299                     break;
02300                 }
02301                 oqca[index]->n += 1.0;
02302                 oqca[index]->rcum += rval;
02303                 oqca[index]->gcum += gval;
02304                 oqca[index]->bcum += bval;
02305             }
02306         }
02307 
02308             /* Compute average color values in each octcube, and
02309              * generate colormap */
02310         cmap = pixcmapCreate(bpp);
02311         pixSetColormap(pixd, cmap);
02312         for (i = 0; i < nbase; i++) {
02313             oqc = oqca[i];
02314             if (oqc->n != 0) {
02315                 oqc->rval = (l_int32)(oqc->rcum / oqc->n);
02316                 oqc->gval = (l_int32)(oqc->gcum / oqc->n);
02317                 oqc->bval = (l_int32)(oqc->bcum / oqc->n);
02318             }
02319             else 
02320                 getRGBFromOctcube(i, maxlevel - 1, &oqc->rval,
02321                                   &oqc->gval, &oqc->bval);
02322             pixcmapAddColor(cmap, oqc->rval, oqc->gval, oqc->bval);
02323         }
02324 /*        pixcmapWriteStream(stderr, cmap); */
02325 
02326         for (i = 0; i < nbase; i++)
02327             FREE(oqca[i]);
02328         FREE(oqca);
02329         FREE(rtab);
02330         FREE(gtab);
02331         FREE(btab);
02332         return pixd;
02333     }
02334             
02335         /*------------------------------------------------------------*
02336          * General case: we will use colors in octcubes at maxlevel.  *
02337          * We also remove any colors that are not populated from      *
02338          * the colormap.                                              *
02339          *------------------------------------------------------------*/
02340         /* Prepare the OctcubeQuantCell array */
02341     if ((oqca = (OQCELL **)CALLOC(ncubes, sizeof(OQCELL *))) == NULL)
02342         return (PIX *)ERROR_PTR("oqca not made", procName, NULL);
02343     for (i = 0; i < ncubes; i++) {
02344         oqca[i] = (OQCELL *)CALLOC(1, sizeof(OQCELL));
02345         oqca[i]->n = 0.0;
02346     }
02347 
02348         /* Make the tables to map color to the octindex,
02349          * of which there are 'ncubes' at 'maxlevel' */
02350     makeRGBToIndexTables(&rtab, &gtab, &btab, maxlevel);
02351 
02352         /* Estimate the color distribution; we want to find the
02353          * most popular nextra colors at 'maxlevel' */
02354     for (i = 0; i < h; i += subsample) {
02355         lines = datas + i * wpls;
02356         for (j = 0; j < w; j += subsample) {
02357             pspixel = lines + j;
02358             extractRGBValues(*pspixel, &rval, &gval, &bval);
02359             getOctcubeIndexFromRGB(rval, gval, bval, rtab, gtab, btab, &index);
02360             oqca[index]->n += 1.0;
02361             oqca[index]->octindex = index;
02362             oqca[index]->rcum += rval;
02363             oqca[index]->gcum += gval;
02364             oqca[index]->bcum += bval;
02365         }
02366     }
02367 
02368         /* Transfer the OQCELL from the array, and order in a heap */
02369     lh = lheapCreate(512, L_SORT_DECREASING);
02370     for (i = 0; i < ncubes; i++)
02371         lheapAdd(lh, oqca[i]);
02372     FREE(oqca);  /* don't need this array */
02373 
02374         /* Prepare a new OctcubeQuantCell array, with maxcolors cells  */
02375     if ((oqca = (OQCELL **)CALLOC(maxcolors, sizeof(OQCELL *))) == NULL)
02376         return (PIX *)ERROR_PTR("oqca not made", procName, NULL);
02377     for (i = 0; i < nbase; i++) {  /* make nbase cells */
02378         oqca[i] = (OQCELL *)CALLOC(1, sizeof(OQCELL));
02379         oqca[i]->n = 0.0;
02380     }
02381 
02382         /* Remove the nextra most populated ones, and put them in the array */
02383     for (i = 0; i < nextra; i++) {
02384         oqc = (OQCELL *)lheapRemove(lh);
02385         oqc->n = 0.0;  /* reinit */
02386         oqc->rcum = 0;
02387         oqc->gcum = 0;
02388         oqc->bcum = 0;
02389         oqca[nbase + i] = oqc;  /* store it in the array */
02390     }
02391 
02392         /* Destroy the heap and its remaining contents */
02393     lheapDestroy(&lh, TRUE);
02394 
02395         /* Generate a lookup table from octindex at maxlevel
02396          * to color table index */
02397     if ((lut1 = (l_int32 *)CALLOC(ncubes, sizeof(l_int32))) == NULL)
02398         return (PIX *)ERROR_PTR("lut1 not made", procName, NULL);
02399     for (i = 0; i < nextra; i++)
02400         lut1[oqca[nbase + i]->octindex] = nbase + i;
02401     for (index = 0; index < ncubes; index++) {
02402         if (lut1[index] == 0)  /* not one of the extras; need to assign */
02403             lut1[index] = index >> 3;  /* remove the least significant bits */
02404 /*        fprintf(stderr, "lut1[%d] = %d\n", index, lut1[index]); */
02405     }
02406         
02407         /* Go through the entire image, gathering statistics and
02408          * assigning pixels to their quantized value */
02409     datad = pixGetData(pixd);
02410     wpld = pixGetWpl(pixd);
02411     for (i = 0; i < h; i++) {
02412         lines = datas + i * wpls;
02413         lined = datad + i * wpld;
02414         for (j = 0; j < w; j++) {
02415             pspixel = lines + j;
02416             extractRGBValues(*pspixel, &rval, &gval, &bval);
02417             getOctcubeIndexFromRGB(rval, gval, bval, rtab, gtab, btab, &index);
02418 /*            fprintf(stderr, "rval = %d, gval = %d, bval = %d, index = %d\n",
02419                     rval, gval, bval, index); */
02420             val = lut1[index];
02421             switch (bpp) {
02422             case 4:
02423                 SET_DATA_QBIT(lined, j, val);
02424                 break;
02425             case 8:
02426                 SET_DATA_BYTE(lined, j, val);
02427                 break;
02428             default:
02429                 return (PIX *)ERROR_PTR("bpp not 4 or 8!", procName, NULL);
02430                 break;
02431             }
02432             oqca[val]->n += 1.0;
02433             oqca[val]->rcum += rval;
02434             oqca[val]->gcum += gval;
02435             oqca[val]->bcum += bval;
02436         }
02437     }
02438     
02439         /* Compute averages, set up a colormap, and make a second
02440          * lut that converts from the color values currently in
02441          * the image to a minimal set */
02442     if ((lut2 = (l_int32 *)CALLOC(ncubes, sizeof(l_int32))) == NULL)
02443         return (PIX *)ERROR_PTR("lut2 not made", procName, NULL);
02444     cmap = pixcmapCreate(bpp);
02445     pixSetColormap(pixd, cmap);
02446     for (i = 0, index = 0; i < maxcolors; i++) {
02447         oqc = oqca[i];
02448         lut2[i] = index;
02449         if (oqc->n == 0)  /* no occupancy; don't bump up index */
02450             continue;
02451         oqc->rval = (l_int32)(oqc->rcum / oqc->n);
02452         oqc->gval = (l_int32)(oqc->gcum / oqc->n);
02453         oqc->bval = (l_int32)(oqc->bcum / oqc->n);
02454         pixcmapAddColor(cmap, oqc->rval, oqc->gval, oqc->bval);
02455         index++;
02456     }
02457 /*    pixcmapWriteStream(stderr, cmap); */
02458     actualcolors = pixcmapGetCount(cmap);
02459 /*    fprintf(stderr, "Number of different colors = %d\n", actualcolors); */
02460 
02461         /* Last time through the image; use the lookup table to
02462          * remap the pixel value to the minimal colormap */
02463     if (actualcolors < maxcolors) {
02464         for (i = 0; i < h; i++) {
02465             lined = datad + i * wpld;
02466             for (j = 0; j < w; j++) {
02467                 switch (bpp) {
02468                 case 4:
02469                     val = GET_DATA_QBIT(lined, j);
02470                     SET_DATA_QBIT(lined, j, lut2[val]);
02471                     break;
02472                 case 8:
02473                     val = GET_DATA_BYTE(lined, j);
02474                     SET_DATA_BYTE(lined, j, lut2[val]);
02475                     break;
02476                 }
02477             }
02478         }
02479     }
02480 
02481     for (i = 0; i < maxcolors; i++)
02482         FREE(oqca[i]);
02483     FREE(oqca);
02484     FREE(lut1);
02485     FREE(lut2);
02486     FREE(rtab);
02487     FREE(gtab);
02488     FREE(btab);
02489     return pixd;
02490 }
02491 
02492 
02493 /*-------------------------------------------------------------------------*
02494  *      Mixed color/gray quantization with specified number of colors      *
02495  *-------------------------------------------------------------------------*/
02496 /*!
02497  *  pixOctcubeQuantMixedWithGray()
02498  *
02499  *      Input:  pixs (32 bpp rgb)
02500  *              depth (of output pix)
02501  *              graylevels (grayscale)
02502  *              delta (threshold for deciding if a pix is color or grayscale)
02503  *      Return: pixd (quantized to octcube and gray levels) or null on error
02504  *
02505  *  Notes:
02506  *      (1) Generates a colormapped image, where the colormap table values
02507  *          have two components: octcube values representing pixels with
02508  *          color content, and grayscale values for the rest.
02509  *      (2) The threshold (delta) is the maximum allowable difference of
02510  *          the max abs value of | r - g |, | r - b | and | g - b |.
02511  *      (3) The octcube values are the averages of all pixels that are
02512  *          found in the octcube, and that are far enough from gray to
02513  *          be considered color.  This can roughly be visualized as all
02514  *          the points in the rgb color cube that are not within a "cylinder"
02515  *          of diameter approximately 'delta' along the main diagonal.
02516  *      (4) We want to guarantee full coverage of the rgb color space; thus,
02517  *          if the output depth is 4, the octlevel is 1 (2 x 2 x 2 = 8 cubes)
02518  *          and if the output depth is 8, the octlevel is 2 (4 x 4 x 4
02519  *          = 64 cubes).
02520  *      (5) Consequently, we have the following constraint on the number
02521  *          of allowed gray levels: for 4 bpp, 8; for 8 bpp, 192.
02522  */     
02523 PIX *
02524 pixOctcubeQuantMixedWithGray(PIX     *pixs,
02525                              l_int32  depth,
02526                              l_int32  graylevels,
02527                              l_int32  delta)
02528 {
02529 l_int32    w, h, wpls, wpld, i, j, size, octlevels;
02530 l_int32    rval, gval, bval, del, val, midval;
02531 l_int32   *carray, *rarray, *garray, *barray;
02532 l_int32   *tabval;
02533 l_uint32   octindex;
02534 l_uint32  *rtab, *gtab, *btab;
02535 l_uint32  *lines, *lined, *datas, *datad;
02536 PIX       *pixd;
02537 PIXCMAP   *cmap;
02538 
02539     PROCNAME("pixOctcubeQuantMixedWithGray");
02540 
02541     if (!pixs)
02542         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
02543     if (pixGetDepth(pixs) != 32)
02544         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
02545     if (depth == 4) {
02546         octlevels = 1;
02547         size = 8;   /* 2 ** 3 */
02548         if (graylevels > 8)
02549             return (PIX *)ERROR_PTR("max 8 gray levels", procName, NULL);
02550     }
02551     else if (depth == 8) {
02552         octlevels = 2;
02553         size = 64;   /* 2 ** 6 */
02554         if (graylevels > 192)
02555             return (PIX *)ERROR_PTR("max 192 gray levels", procName, NULL);
02556     }
02557     else
02558         return (PIX *)ERROR_PTR("output depth not 4 or 8 bpp", procName, NULL);
02559     
02560         /* Make octcube index tables */
02561     if (makeRGBToIndexTables(&rtab, &gtab, &btab, octlevels))
02562         return (PIX *)ERROR_PTR("tables not made", procName, NULL);
02563 
02564         /* Make octcube arrays for storing points in each cube */
02565     if ((carray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
02566         return (PIX *)ERROR_PTR("carray not made", procName, NULL);
02567     if ((rarray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
02568         return (PIX *)ERROR_PTR("rarray not made", procName, NULL);
02569     if ((garray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
02570         return (PIX *)ERROR_PTR("garray not made", procName, NULL);
02571     if ((barray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
02572         return (PIX *)ERROR_PTR("barray not made", procName, NULL);
02573 
02574         /* Make lookup table, using computed thresholds  */
02575     if ((tabval = makeGrayQuantIndexTable(graylevels)) == NULL)
02576         return (PIX *)ERROR_PTR("tabval not made", procName, NULL);
02577 
02578         /* Make colormapped output pixd */
02579     pixGetDimensions(pixs, &w, &h, NULL);
02580     if ((pixd = pixCreate(w, h, depth)) == NULL)
02581         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
02582     pixCopyResolution(pixd, pixs);
02583     pixCopyInputFormat(pixd, pixs);
02584     cmap = pixcmapCreate(depth);
02585     for (j = 0; j < size; j++)  /* reserve octcube colors */
02586         pixcmapAddColor(cmap, 1, 1, 1);  /* a color that won't be used */
02587     for (j = 0; j < graylevels; j++) {  /* set grayscale colors */
02588         val = (255 * j) / (graylevels - 1);
02589         pixcmapAddColor(cmap, val, val, val);
02590     }
02591     pixSetColormap(pixd, cmap);
02592     wpld = pixGetWpl(pixd);
02593     datad = pixGetData(pixd);
02594 
02595         /* Go through src image: assign dest pixels to colormap values
02596          * and compute average colors in each occupied octcube */
02597     datas = pixGetData(pixs);
02598     wpls = pixGetWpl(pixs);
02599     for (i = 0; i < h; i++) {
02600         lines = datas + i * wpls;
02601         lined = datad + i * wpld;
02602         for (j = 0; j < w; j++) {
02603             extractRGBValues(lines[j], &rval, &gval, &bval);
02604             if (rval > gval) {
02605                 if (gval > bval) {   /* r > g > b */
02606                     del = rval - bval;
02607                     midval = gval;
02608                 }
02609                 else {
02610                     if (rval > bval) {  /* r > b > g */
02611                         del = rval - gval;
02612                         midval = bval;
02613                     }
02614                     else {  /* b > r > g */
02615                         del = bval - gval;
02616                         midval = rval;
02617                     }
02618                 }
02619             }
02620             else  {  /* gval >= rval */
02621                 if (rval > bval) {  /* g > r > b */
02622                     del = gval - bval;
02623                     midval = rval;
02624                 }
02625                 else {
02626                     if (gval > bval) {  /* g > b > r */
02627                         del = gval - rval;
02628                         midval = bval;
02629                     }
02630                     else {  /* b > g > r */
02631                         del = bval - rval;
02632                         midval = gval;
02633                     }
02634                 }
02635             }
02636             if (del > delta) {  /* assign to color */
02637                 octindex = rtab[rval] | gtab[gval] | btab[bval];
02638                 carray[octindex]++;
02639                 rarray[octindex] += rval;
02640                 garray[octindex] += gval;
02641                 barray[octindex] += bval;
02642                 if (depth == 4)
02643                     SET_DATA_QBIT(lined, j, octindex);
02644                 else  /* depth == 8 */
02645                     SET_DATA_BYTE(lined, j, octindex);
02646             }
02647             else {  /* assign to grayscale */
02648                 val = size + tabval[midval];
02649                 if (depth == 4)
02650                     SET_DATA_QBIT(lined, j, val);
02651                 else  /* depth == 8 */
02652                     SET_DATA_BYTE(lined, j, val);
02653             }
02654         }
02655     }
02656 
02657         /* Average the colors in each bin and reset the colormap */
02658     for (i = 0; i < size; i++) {
02659         if (carray[i] > 0) {
02660             rarray[i] /= carray[i];
02661             garray[i] /= carray[i];
02662             barray[i] /= carray[i];
02663             pixcmapResetColor(cmap, i, rarray[i], garray[i], barray[i]);
02664         }
02665     }
02666 
02667     FREE(carray);
02668     FREE(rarray);
02669     FREE(garray);
02670     FREE(barray);
02671     FREE(rtab);
02672     FREE(gtab);
02673     FREE(btab);
02674     FREE(tabval);
02675     return pixd;
02676 }
02677 
02678 
02679 /*-------------------------------------------------------------------------*
02680  *             Fixed partition octcube quantization with 256 cells         *
02681  *-------------------------------------------------------------------------*/
02682 /*!
02683  *  pixFixedOctcubeQuant256()
02684  *
02685  *      Input:  pixs  (32 bpp; 24-bit color)
02686  *              ditherflag  (1 for dithering; 0 for no dithering)
02687  *      Return: pixd (8 bit with colormap), or null on error
02688  *
02689  *  This simple 1-pass color quantization works by breaking the
02690  *  color space into 256 pieces, with 3 bits quantized for each of
02691  *  red and green, and 2 bits quantized for blue.  We shortchange
02692  *  blue because the eye is least sensitive to blue.  This
02693  *  division of the color space is into two levels of octrees,
02694  *  followed by a further division by 4 (not 8), where both
02695  *  blue octrees have been combined in the third level. 
02696  *
02697  *  The color map is generated from the 256 color centers by
02698  *  taking the representative color to be the center of the
02699  *  cell volume.  This gives a maximum error in the red and
02700  *  green values of 16 levels, and a maximum error in the
02701  *  blue sample of 32 levels. 
02702  *
02703  *  Each pixel in the 24-bit color image is placed in its containing
02704  *  cell, given by the relevant MSbits of the red, green and blue
02705  *  samples.  An error-diffusion dithering is performed on each
02706  *  color sample to give the appearance of good average local color.
02707  *  Dithering is required; without it, the contouring and visible
02708  *  color errors are very bad.
02709  *
02710  *  I originally implemented this algorithm in two passes,
02711  *  where the first pass was used to compute the weighted average
02712  *  of each sample in each pre-allocated region of color space.
02713  *  The idea was to use these centroids in the dithering algorithm
02714  *  of the second pass, to reduce the average error that was
02715  *  being dithered.  However, with dithering, there is
02716  *  virtually no difference, so there is no reason to make the
02717  *  first pass.  Consequently, this 1-pass version just assigns
02718  *  the pixels to the centers of the pre-allocated cells.
02719  *  We use dithering to spread the difference between the sample
02720  *  value and the location of the center of the cell.  For speed
02721  *  and simplicity, we use integer dithering and propagate only
02722  *  to the right, down, and diagonally down-right, with ratios
02723  *  3/8, 3/8 and 1/4, respectively.  The results should be nearly
02724  *  as good, and a bit faster, with propagation only to the right
02725  *  and down.
02726  * 
02727  *  The algorithm is very fast, because there is no search,
02728  *  only fast generation of the cell index for each pixel.
02729  *  We use a simple mapping from the three 8 bit rgb samples
02730  *  to the 8 bit cell index; namely, (r7 r6 r5 g7 g6 g5 b7 b6).
02731  *  This is not in an octcube format, but it doesn't matter.
02732  *  There are no storage requirements.  We could keep a
02733  *  running average of the center of each sample in each
02734  *  cluster, rather than using the center of the cell, but
02735  *  this is just extra work, esp. with dithering.
02736  *
02737  *  This method gives surprisingly good results with dithering.
02738  *  However, without dithering, the loss of color accuracy is
02739  *  evident in regions that are very light or that have subtle
02740  *  blending of colors.
02741  */
02742 PIX *
02743 pixFixedOctcubeQuant256(PIX     *pixs,
02744                         l_int32  ditherflag)
02745 {
02746 l_uint8    index;
02747 l_int32    rval, gval, bval;
02748 l_int32    w, h, wpls, wpld, i, j, cindex;
02749 l_uint32  *rtab, *gtab, *btab;
02750 l_int32   *itab;
02751 l_uint32  *datas, *datad, *lines, *lined;
02752 PIX       *pixd;
02753 PIXCMAP   *cmap;
02754 
02755     PROCNAME("pixFixedOctcubeQuant256");
02756 
02757     if (!pixs)
02758         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
02759     if (pixGetDepth(pixs) != 32)
02760         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
02761 
02762         /* Do not dither if image is very small */
02763     pixGetDimensions(pixs, &w, &h, NULL);
02764     if (w < MIN_DITHER_SIZE && h < MIN_DITHER_SIZE && ditherflag == 1) {
02765         L_INFO("Small image: dithering turned off", procName);
02766         ditherflag = 0;
02767     }
02768 
02769         /* Find the centers of the 256 cells, each of which represents
02770          * the 3 MSBits of the red and green components, and the
02771          * 2 MSBits of the blue component.  This gives a mapping
02772          * from a "cube index" to the rgb values.  Save all 256
02773          * rgb values of these centers in a colormap.
02774          * For example, to get the red color of the cell center,
02775          * you take the 3 MSBits of to the index and add the
02776          * offset to the center of the cell, which is 0x10. */
02777     cmap = pixcmapCreate(8);
02778     for (cindex = 0; cindex < 256; cindex++) {
02779         rval = (cindex & 0xe0) | 0x10;
02780         gval = ((cindex << 3) & 0xe0) | 0x10;
02781         bval = ((cindex << 6) & 0xc0) | 0x20;
02782         pixcmapAddColor(cmap, rval, gval, bval);
02783     }
02784 
02785         /* Make output 8 bpp palette image */
02786     datas = pixGetData(pixs);
02787     wpls = pixGetWpl(pixs);
02788     if ((pixd = pixCreate(w, h, 8)) == NULL)
02789         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
02790     pixSetColormap(pixd, cmap);
02791     pixCopyResolution(pixd, pixs);
02792     pixCopyInputFormat(pixd, pixs);
02793     datad = pixGetData(pixd);
02794     wpld = pixGetWpl(pixd);
02795 
02796         /* Set dest pix values to colortable indices */
02797     if (ditherflag == 0) {   /* no dithering */
02798         for (i = 0; i < h; i++) {
02799             lines = datas + i * wpls;
02800             lined = datad + i * wpld;
02801             for (j = 0; j < w; j++) {
02802                 extractRGBValues(lines[j], &rval, &gval, &bval);
02803                 index = (rval & 0xe0) | ((gval >> 3) & 0x1c) | (bval >> 6);
02804                 SET_DATA_BYTE(lined, j, index);
02805             }
02806         }
02807     }
02808     else {  /* ditherflag == 1 */
02809             /* Set up conversion tables from rgb directly to the colormap
02810              * index.  However, the dithering function expects these tables
02811              * to generate an octcube index (+1), and the table itab[] to
02812              * convert to the colormap index.  So we make a trivial
02813              * itab[], that simply compensates for the -1 in
02814              * pixDitherOctindexWithCmap().   No cap is required on
02815              * the propagated difference.  */
02816         rtab = (l_uint32 *)CALLOC(256, sizeof(l_uint32));
02817         gtab = (l_uint32 *)CALLOC(256, sizeof(l_uint32));
02818         btab = (l_uint32 *)CALLOC(256, sizeof(l_uint32));
02819         itab = (l_int32 *)CALLOC(256, sizeof(l_int32));
02820         for (i = 0; i < 256; i++) {
02821             rtab[i] = i & 0xe0;
02822             gtab[i] = (i >> 3) & 0x1c;
02823             btab[i] = i >> 6;
02824             itab[i] = i + 1;
02825         }
02826         pixDitherOctindexWithCmap(pixs, pixd, rtab, gtab, btab, itab,
02827                                   FIXED_DIF_CAP);
02828         FREE(rtab);
02829         FREE(gtab);
02830         FREE(btab);
02831         FREE(itab);
02832     }
02833 
02834     return pixd;
02835 }
02836 
02837 
02838 /*---------------------------------------------------------------------------*
02839  *           Nearly exact quantization for images with few colors            *
02840  *---------------------------------------------------------------------------*/
02841 /*!
02842  *  pixFewColorsOctcubeQuant1()
02843  *
02844  *      Input:  pixs (32 bpp rgb)
02845  *              level (significant bits for each of RGB; valid in [1...6])
02846  *      Return: pixd (quantized to octcube) or null on error
02847  *
02848  *  Notes:
02849  *      (1) Generates a colormapped image, where the colormap table values
02850  *          are the averages of all pixels that are found in the octcube.
02851  *      (2) This fails if there are more than 256 colors (i.e., more
02852  *          than 256 occupied octcubes).
02853  *      (3) Often level 3 (512 octcubes) will succeed because not more
02854  *          than half of them are occupied with 1 or more pixels.
02855  *      (4) The depth of the result, which is either 2, 4 or 8 bpp,
02856  *          is the minimum required to hold the number of colors that
02857  *          are found.
02858  *      (5) This can be useful for quantizing orthographically generated
02859  *          images such as color maps, where there may be more than 256 colors
02860  *          because of aliasing or jpeg artifacts on text or lines, but
02861  *          there are a relatively small number of solid colors.  Then,
02862  *          use with level = 3 can often generate a compact and accurate
02863  *          representation of the original RGB image.  For this purpose,
02864  *          it is better than pixFewColorsOctcubeQuant2(), because it
02865  *          uses the average value of pixels in the octcube rather
02866  *          than the first found pixel.  It is also simpler to use,
02867  *          because it generates the histogram internally.
02868  */     
02869 PIX *
02870 pixFewColorsOctcubeQuant1(PIX     *pixs,
02871                           l_int32  level)
02872 {
02873 l_int32    w, h, wpls, wpld, i, j, depth, size, ncolors, index;
02874 l_int32    rval, gval, bval;
02875 l_int32   *carray, *rarray, *garray, *barray;
02876 l_uint32   octindex;
02877 l_uint32  *rtab, *gtab, *btab;
02878 l_uint32  *lines, *lined, *datas, *datad, *pspixel;
02879 PIX       *pixd;
02880 PIXCMAP   *cmap;
02881 
02882     PROCNAME("pixFewColorsOctcubeQuant1");
02883 
02884     if (!pixs)
02885         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
02886     if (pixGetDepth(pixs) != 32)
02887         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
02888     if (level < 1 || level > 6)
02889         return (PIX *)ERROR_PTR("invalid level", procName, NULL);
02890 
02891     if (octcubeGetCount(level, &size))  /* array size = 2 ** (3 * level) */
02892         return (PIX *)ERROR_PTR("size not returned", procName, NULL);
02893     if (makeRGBToIndexTables(&rtab, &gtab, &btab, level))
02894         return (PIX *)ERROR_PTR("tables not made", procName, NULL);
02895 
02896     if ((carray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
02897         return (PIX *)ERROR_PTR("carray not made", procName, NULL);
02898     if ((rarray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
02899         return (PIX *)ERROR_PTR("rarray not made", procName, NULL);
02900     if ((garray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
02901         return (PIX *)ERROR_PTR("garray not made", procName, NULL);
02902     if ((barray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
02903         return (PIX *)ERROR_PTR("barray not made", procName, NULL);
02904 
02905         /* Place the pixels in octcube leaves. */
02906     pixGetDimensions(pixs, &w, &h, NULL);
02907     datas = pixGetData(pixs);
02908     wpls = pixGetWpl(pixs);
02909     pixd = NULL;
02910     for (i = 0; i < h; i++) {
02911         lines = datas + i * wpls;
02912         for (j = 0; j < w; j++) {
02913             pspixel = lines + j;
02914             extractRGBValues(*pspixel, &rval, &gval, &bval);
02915             octindex = rtab[rval] | gtab[gval] | btab[bval];
02916             carray[octindex]++;
02917             rarray[octindex] += rval;
02918             garray[octindex] += gval;
02919             barray[octindex] += bval;
02920         }
02921     }
02922 
02923         /* Find the number of different colors */
02924     for (i = 0, ncolors = 0; i < size; i++) {
02925         if (carray[i] > 0)
02926             ncolors++;
02927     }
02928     if (ncolors > 256) {
02929         L_WARNING_INT("%d colors found; more than 256", procName, ncolors);
02930         goto array_cleanup;
02931     }
02932     if (ncolors <= 4)
02933         depth = 2;
02934     else if (ncolors <= 16)
02935         depth = 4;
02936     else
02937         depth = 8;
02938 
02939         /* Average the colors in each octcube leaf and add to colormap table;
02940          * then use carray to hold the colormap index + 1  */
02941     cmap = pixcmapCreate(depth);
02942     for (i = 0, index = 0; i < size; i++) {
02943         if (carray[i] > 0) {
02944             rarray[i] /= carray[i];
02945             garray[i] /= carray[i];
02946             barray[i] /= carray[i];
02947             pixcmapAddColor(cmap, rarray[i], garray[i], barray[i]);
02948             carray[i] = index + 1;  /* to avoid storing 0 */
02949             index++;
02950         }
02951     }
02952 
02953     pixd = pixCreate(w, h, depth);
02954     pixSetColormap(pixd, cmap);
02955     pixCopyResolution(pixd, pixs);
02956     pixCopyInputFormat(pixd, pixs);
02957     datad = pixGetData(pixd);
02958     wpld = pixGetWpl(pixd);
02959     for (i = 0; i < h; i++) {
02960         lines = datas + i * wpls;
02961         lined = datad + i * wpld;
02962         for (j = 0; j < w; j++) {
02963             pspixel = lines + j;
02964             extractRGBValues(*pspixel, &rval, &gval, &bval);
02965             octindex = rtab[rval] | gtab[gval] | btab[bval];
02966             switch (depth) 
02967             {
02968             case 2:
02969                 SET_DATA_DIBIT(lined, j, carray[octindex] - 1);
02970                 break;
02971             case 4:
02972                 SET_DATA_QBIT(lined, j, carray[octindex] - 1);
02973                 break;
02974             case 8:
02975                 SET_DATA_BYTE(lined, j, carray[octindex] - 1);
02976                 break;
02977             default:
02978                 L_WARNING("shouldn't get here", procName);
02979             }
02980         }
02981     }
02982 
02983 array_cleanup:
02984     FREE(carray);
02985     FREE(rarray);
02986     FREE(garray);
02987     FREE(barray);
02988     FREE(rtab);
02989     FREE(gtab);
02990     FREE(btab);
02991     return pixd;
02992 }
02993 
02994 
02995 /*!
02996  *  pixFewColorsOctcubeQuant2()
02997  *
02998  *      Input:  pixs (32 bpp rgb)
02999  *              level (of octcube indexing, for histogram: 3, 4, 5, 6)
03000  *              na (histogram of pixel occupation in octree leaves at
03001  *                  given level)
03002  *              ncolors (number of occupied octree leaves at given level)
03003  *              &nerrors (<optional return> num of pixels not exactly
03004  *                        represented in the colormap)
03005  *      Return: pixd (2, 4 or 8 bpp with colormap), or null on error
03006  *
03007  *  Notes:
03008  *      (1) Generates a colormapped image, where the colormap table values
03009  *          are the averages of all pixels that are found in the octcube.
03010  *      (2) This fails if there are more than 256 colors (i.e., more
03011  *          than 256 occupied octcubes).
03012  *      (3) Often level 3 (512 octcubes) will succeed because not more
03013  *          than half of them are occupied with 1 or more pixels.
03014  *      (4) For an image with not more than 256 colors, it is unlikely
03015  *          that two pixels of different color will fall in the same
03016  *          octcube at level = 4.   However it is possible, and this
03017  *          function optionally returns @nerrors, the number of pixels
03018  *          where, because more than one color is in the same octcube,
03019  *          the pixel color is not exactly reproduced in the colormap.
03020  *          The colormap for an occupied leaf of the octree contains
03021  *          the color of the first pixel encountered in that octcube.
03022  *      (5) This differs from pixFewColorsOctcubeQuant1(), which also
03023  *          requires not more than 256 occupied leaves, but represents
03024  *          the color of each leaf by an average over the pixels in
03025  *          that leaf.  This also requires precomputing the histogram
03026  *          of occupied octree leaves, which is generated using
03027  *          pixOctcubeHistogram().
03028  *      (6) This is used in pixConvertRGBToColormap() for images that
03029  *          are determined, by their histogram, to have relatively few
03030  *          colors.  This typically happens with orthographically
03031  *          produced images (as oppopsed to natural images), where
03032  *          it is expected that most of the pixels within a leaf
03033  *          octcube have exactly the same color, and quantization to
03034  *          that color is lossless.
03035  */     
03036 PIX *
03037 pixFewColorsOctcubeQuant2(PIX      *pixs,
03038                           l_int32   level,
03039                           NUMA     *na,
03040                           l_int32   ncolors,
03041                           l_int32  *pnerrors)
03042 {
03043 l_int32    w, h, wpls, wpld, i, j, nerrors;
03044 l_int32    ncubes, depth, cindex, oval;
03045 l_int32    rval, gval, bval;
03046 l_int32   *octarray;
03047 l_uint32   octindex;
03048 l_uint32  *rtab, *gtab, *btab;
03049 l_uint32  *lines, *lined, *datas, *datad, *ppixel;
03050 l_uint32  *colorarray;
03051 PIX       *pixd;
03052 PIXCMAP   *cmap;
03053 
03054     PROCNAME("pixFewColorsOctcubeQuant2");
03055 
03056     if (!pixs)
03057         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
03058     if (pixGetDepth(pixs) != 32)        
03059         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
03060     if (level < 3 || level > 6)
03061         return (PIX *)ERROR_PTR("level not in {4, 5, 6}", procName, NULL);
03062     if (ncolors > 256)
03063         return (PIX *)ERROR_PTR("ncolors > 256", procName, NULL);
03064     if (pnerrors)
03065         *pnerrors = UNDEF;
03066 
03067         /* Represent the image with a set of leaf octcubes
03068          * at 'level', one for each color. */
03069     if (makeRGBToIndexTables(&rtab, &gtab, &btab, level))
03070         return (PIX *)ERROR_PTR("tables not made", procName, NULL);
03071 
03072         /* Determine the output depth from the number of colors */
03073     pixGetDimensions(pixs, &w, &h, NULL);
03074     datas = pixGetData(pixs);
03075     wpls = pixGetWpl(pixs);
03076     if (ncolors <= 4)
03077         depth = 2;
03078     else if (ncolors <= 16)
03079         depth = 4;
03080     else  /* ncolors <= 256 */
03081         depth = 8;
03082         
03083     if ((pixd = pixCreate(w, h, depth)) == NULL)
03084         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
03085     pixCopyResolution(pixd, pixs);
03086     pixCopyInputFormat(pixd, pixs);
03087     datad = pixGetData(pixd);
03088     wpld = pixGetWpl(pixd);
03089 
03090         /* The octarray will give a ptr from the octcube to the colorarray */
03091     ncubes = numaGetCount(na);
03092     if ((octarray = (l_int32 *)CALLOC(ncubes, sizeof(l_int32))) == NULL)
03093         return (PIX *)ERROR_PTR("octarray not made", procName, NULL);
03094 
03095         /* The colorarray will hold the colors of the first pixel
03096          * that lands in the leaf octcube.  After filling, it is
03097          * used to generate the colormap.  */
03098     if ((colorarray = (l_uint32 *)CALLOC(ncolors + 1, sizeof(l_uint32)))
03099             == NULL)
03100         return (PIX *)ERROR_PTR("colorarray not made", procName, NULL);
03101 
03102         /* For each pixel, get the octree index for its leaf octcube.
03103          * Check if a pixel has already been found in this octcube.
03104          *   - If not yet found, save that color in the colorarray
03105          *     and save the cindex in the octarray.  
03106          *   - If already found, compare the pixel color with the
03107          *     color in the colorarray, and note if it differs.
03108          * Then set the dest pixel value to the cindex - 1, which
03109          * will be the cmap index for this color.  */
03110     cindex = 1;  /* start with 1 */ 
03111     nerrors = 0;
03112     for (i = 0; i < h; i++) {
03113         lines = datas + i * wpls;
03114         lined = datad + i * wpld;
03115         for (j = 0; j < w; j++) {
03116             ppixel = lines + j;
03117             extractRGBValues(*ppixel, &rval, &gval, &bval);
03118             octindex = rtab[rval] | gtab[gval] | btab[bval];
03119             oval = octarray[octindex];
03120             if (oval == 0) {
03121                 octarray[octindex] = cindex;
03122                 colorarray[cindex] = *ppixel;
03123                 setPixelLow(lined, j, depth, cindex - 1);
03124                 cindex++;
03125             }
03126             else {  /* already have seen this color; is it unique? */
03127                 setPixelLow(lined, j, depth, oval - 1);
03128                 if (colorarray[oval] != *ppixel)
03129                     nerrors++;
03130             }
03131         }
03132     }
03133     if (pnerrors)
03134         *pnerrors = nerrors;
03135 
03136 #if  DEBUG_FEW_COLORS
03137     fprintf(stderr, "ncubes = %d, ncolors = %d\n", ncubes, ncolors);
03138     for (i = 0; i < ncolors; i++)
03139         fprintf(stderr, "color[%d] = %x\n", i, colorarray[i + 1]);
03140 #endif  /* DEBUG_FEW_COLORS */
03141 
03142         /* Make the colormap. */
03143     cmap = pixcmapCreate(depth);
03144     for (i = 0; i < ncolors; i++) {
03145         ppixel = colorarray + i + 1;
03146         extractRGBValues(*ppixel, &rval, &gval, &bval);
03147         pixcmapAddColor(cmap, rval, gval, bval);
03148     }
03149     pixSetColormap(pixd, cmap);
03150 
03151     FREE(octarray);
03152     FREE(colorarray);
03153     FREE(rtab);
03154     FREE(gtab);
03155     FREE(btab);
03156     return pixd;
03157 }
03158 
03159 
03160 /*!
03161  *  pixFewColorsOctcubeQuantMixed()
03162  *
03163  *      Input:  pixs (32 bpp rgb)
03164  *              level (significant octcube bits for each of RGB;
03165  *                     valid in [1...6]; use 0 for default)
03166  *              darkthresh (threshold near black; if the lightest component
03167  *                          is below this, the pixel is not considered to
03168  *                          be gray or color; uses 0 for default)
03169  *              lightthresh (threshold near white; if the darkest component
03170  *                           is above this, the pixel is not considered to
03171  *                           be gray or color; use 0 for default)
03172  *              diffthresh (thresh for the max difference between component
03173  *                          values; for differences below this, the pixel
03174  *                          is considered to be gray; use 0 for default)
03175  *                          considered gray; use 0 for default)
03176  *              minfract (min fraction of pixels for gray histo bin;
03177  *                        use 0.0 for default)
03178  *              maxspan (max size of gray histo bin; use 0 for default)
03179  *      Return: pixd (8 bpp, quantized to octcube for pixels that are
03180  *                    not gray; gray pixels are quantized separately
03181  *                    over the full gray range), or null on error
03182  *
03183  *  Notes:
03184  *      (1) First runs pixFewColorsOctcubeQuant1().  If this succeeds,
03185  *          it separates the color from gray(ish) entries in the cmap,
03186  *          and re-quantizes the gray pixels.  The result has some pixels
03187  *          in color and others in gray.
03188  *      (2) This fails if there are more than 256 colors (i.e., more
03189  *          than 256 occupied octcubes in the color quantization).
03190  *      (3) Level 3 (512 octcubes) will usually succeed because not more
03191  *          than half of them are occupied with 1 or more pixels.
03192  *      (4) This uses the criterion from pixColorFraction() for deciding
03193  *          if a colormap entry is color; namely, if the color components
03194  *          are not too close to either black or white, and the maximum
03195  *          difference between component values equals or exceeds a threshold.
03196  *      (5) For quantizing the gray pixels, it uses a histogram-based
03197  *          method where input parameters determining the buckets are
03198  *          the minimum population fraction and the maximum allowed size.
03199  *      (6) Recommended input parameters are:
03200  *              @level:  3 or 4  (3 is default)
03201  *              @darkthresh:  20
03202  *              @lightthresh: 244
03203  *              @diffthresh: 20
03204  *              @minfract: 0.05
03205  *              @maxspan: 15
03206  *          These numbers are intended to be conservative (somewhat over-
03207  *          sensitive) in color detection,  It's usually better to pay
03208  *          extra with octcube quantization of a grayscale image than
03209  *          to use grayscale quantization on an image that has some
03210  *          actual color.  Input 0 on any of these to get the default.
03211  *      (7) This can be useful for quantizing orthographically generated
03212  *          images such as color maps, where there may be more than 256 colors
03213  *          because of aliasing or jpeg artifacts on text or lines, but
03214  *          there are a relatively small number of solid colors.  It usually
03215  *          gives results that are better than pixOctcubeQuantMixedWithGray(),
03216  *          both in size and appearance.  But it is a bit slower.
03217  */     
03218 PIX *
03219 pixFewColorsOctcubeQuantMixed(PIX       *pixs,
03220                               l_int32    level,
03221                               l_int32    darkthresh,
03222                               l_int32    lightthresh,
03223                               l_int32    diffthresh,
03224                               l_float32  minfract,
03225                               l_int32    maxspan)
03226 {
03227 l_int32    i, j, w, h, wplc, wplm, wpld, ncolors, index; 
03228 l_int32    rval, gval, bval, val, minval, maxval;
03229 l_int32   *lut;
03230 l_uint32  *datac, *datam, *datad, *linec, *linem, *lined;
03231 PIX       *pixc, *pixm, *pixg, *pixd;
03232 PIXCMAP   *cmap, *cmapd;
03233 
03234     PROCNAME("pixFewColorsOctcubeQuantMixed");
03235 
03236     if (!pixs || pixGetDepth(pixs) != 32)
03237         return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
03238     if (level <= 0) level = 3;
03239     if (level > 6) 
03240         return (PIX *)ERROR_PTR("invalid level", procName, NULL);
03241     if (darkthresh <= 0) darkthresh = 20;
03242     if (lightthresh <= 0) lightthresh = 244;
03243     if (diffthresh <= 0) diffthresh = 20;
03244     if (minfract <= 0.0) minfract = 0.05;
03245     if (maxspan <= 2) maxspan = 15;
03246 
03247         /* Start with a simple fixed octcube quantizer. */
03248     if ((pixc = pixFewColorsOctcubeQuant1(pixs, level)) == NULL)
03249         return (PIX *)ERROR_PTR("too many colors", procName, NULL);
03250 
03251         /* Identify and save color entries in the colormap.  Set up a LUT
03252          * that returns -1 for any gray pixel. */
03253     cmap = pixGetColormap(pixc);
03254     ncolors = pixcmapGetCount(cmap);
03255     cmapd = pixcmapCreate(8);
03256     lut = (l_int32 *)CALLOC(256, sizeof(l_int32));
03257     for (i = 0; i < 256; i++)
03258         lut[i] = -1;
03259     for (i = 0, index = 0; i < ncolors; i++) {
03260         pixcmapGetColor(cmap, i, &rval, &gval, &bval);
03261         minval = L_MIN(rval, gval);
03262         minval = L_MIN(minval, bval);
03263         if (minval > lightthresh)  /* near white */
03264             continue;
03265         maxval = L_MAX(rval, gval);
03266         maxval = L_MAX(maxval, bval);
03267         if (maxval < darkthresh)  /* near black */
03268             continue;
03269 
03270             /* Use the max diff between components to test for color */
03271         if (maxval - minval >= diffthresh) {
03272             pixcmapAddColor(cmapd, rval, gval, bval);
03273             lut[i] = index;
03274             index++;
03275         }
03276     }
03277 
03278         /* Generate dest pix with just the color pixels set to their
03279          * colormap indices.  At the same time, make a 1 bpp mask
03280          * of the non-color pixels */
03281     pixGetDimensions(pixs, &w, &h, NULL);
03282     pixd = pixCreate(w, h, 8);
03283     pixSetColormap(pixd, cmapd);
03284     pixm = pixCreate(w, h, 1);
03285     datac = pixGetData(pixc);
03286     datam = pixGetData(pixm);
03287     datad = pixGetData(pixd);
03288     wplc = pixGetWpl(pixc);
03289     wplm = pixGetWpl(pixm);
03290     wpld = pixGetWpl(pixd);
03291     for (i = 0; i < h; i++) {
03292         linec = datac + i * wplc;
03293         linem = datam + i * wplm;
03294         lined = datad + i * wpld;
03295         for (j = 0; j < w; j++) {
03296             val = GET_DATA_BYTE(linec, j);
03297             if (lut[val] == -1)
03298                 SET_DATA_BIT(linem, j);
03299             else
03300                 SET_DATA_BYTE(lined, j, lut[val]);
03301         }
03302     }
03303 
03304         /* Fill in the gray values.  Use a grayscale version of pixs
03305          * as input, along with the mask over the actual gray pixels. */
03306     pixg = pixConvertTo8(pixs, 0);
03307     pixGrayQuantFromHisto(pixd, pixg, pixm, minfract, maxspan);
03308 
03309     FREE(lut);
03310     pixDestroy(&pixc);
03311     pixDestroy(&pixm);
03312     pixDestroy(&pixg);
03313     return pixd;
03314 }
03315 
03316 
03317 /*---------------------------------------------------------------------------*
03318  *           Fixed partition octcube quantization with RGB output            *
03319  *---------------------------------------------------------------------------*/
03320 /*!
03321  *  pixFixedOctcubeQuantGenRGB()
03322  *
03323  *      Input:  pixs (32 bpp rgb)
03324  *              level (significant bits for each of r,g,b)
03325  *      Return: pixd (rgb; quantized to octcube centers), or null on error
03326  *
03327  *  Notes:
03328  *      (1) Unlike the other color quantization functions, this one
03329  *          generates an rgb image.
03330  *      (2) The pixel values are quantized to the center of each octcube
03331  *          (at the specified level) containing the pixel.  They are
03332  *          not quantized to the average of the pixels in that octcube.
03333  */     
03334 PIX *
03335 pixFixedOctcubeQuantGenRGB(PIX     *pixs,
03336                            l_int32  level)
03337 {
03338 l_int32    w, h, wpls, wpld, i, j;
03339 l_int32    rval, gval, bval;
03340 l_uint32   octindex;
03341 l_uint32  *rtab, *gtab, *btab;
03342 l_uint32  *lines, *lined, *datas, *datad;
03343 PIX       *pixd;
03344 
03345     PROCNAME("pixFixedOctcubeQuantGenRGB");
03346 
03347     if (!pixs)
03348         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
03349     if (pixGetDepth(pixs) != 32)
03350         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
03351     if (level < 1 || level > 6)
03352         return (PIX *)ERROR_PTR("level not in {1,...6}", procName, NULL);
03353 
03354     if (makeRGBToIndexTables(&rtab, &gtab, &btab, level))
03355         return (PIX *)ERROR_PTR("tables not made", procName, NULL);
03356 
03357     pixGetDimensions(pixs, &w, &h, NULL);
03358     pixd = pixCreate(w, h, 32);
03359     pixCopyResolution(pixd, pixs);
03360     pixCopyInputFormat(pixd, pixs);
03361     datad = pixGetData(pixd);
03362     wpld = pixGetWpl(pixd);
03363     datas = pixGetData(pixs);
03364     wpls = pixGetWpl(pixs);
03365     for (i = 0; i < h; i++) {
03366         lines = datas + i * wpls;
03367         lined = datad + i * wpld;
03368         for (j = 0; j < w; j++) {
03369             extractRGBValues(lines[j], &rval, &gval, &bval);
03370             octindex = rtab[rval] | gtab[gval] | btab[bval];
03371             getRGBFromOctcube(octindex, level, &rval, &gval, &bval);
03372             composeRGBPixel(rval, gval, bval, lined + j);
03373         }
03374     }
03375 
03376     FREE(rtab);
03377     FREE(gtab);
03378     FREE(btab);
03379     return pixd;
03380 }
03381 
03382 
03383 /*------------------------------------------------------------------*
03384  *          Color quantize RGB image using existing colormap        *
03385  *------------------------------------------------------------------*/
03386 /*!
03387  *  pixQuantFromCmap()
03388  *
03389  *      Input:  pixs  (8 bpp grayscale without cmap, or 32 bpp rgb)
03390  *              cmap  (to quantize to; insert copy into dest pix)
03391  *              mindepth (minimum depth of pixd: can be 2, 4 or 8 bpp)
03392  *              level (of octcube used for finding nearest color in cmap)
03393  *              metric (L_MANHATTAN_DISTANCE, L_EUCLIDEAN_DISTANCE)
03394  *      Return: pixd  (2, 4 or 8 bpp, colormapped), or null on error
03395  *
03396  *  Notes:
03397  *      (1) This is a top-level wrapper for quantizing either grayscale
03398  *          or rgb images to a specified colormap.
03399  *      (2) The actual output depth is constrained by @mindepth and
03400  *          by the number of colors in @cmap.
03401  *      (3) For grayscale, @level and @metric are ignored.
03402  *      (4) If the cmap has color and pixs is grayscale, the color is
03403  *          removed from the cmap before quantizing pixs.
03404  */
03405 PIX *
03406 pixQuantFromCmap(PIX      *pixs,
03407                  PIXCMAP  *cmap,
03408                  l_int32   mindepth,
03409                  l_int32   level,
03410                  l_int32   metric)
03411 {
03412 l_int32  d;
03413 
03414     PROCNAME("pixQuantFromCmap");
03415 
03416     if (!pixs)
03417         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
03418     if (mindepth != 2 && mindepth != 4 && mindepth != 8)
03419         return (PIX *)ERROR_PTR("invalid mindepth", procName, NULL);
03420     d = pixGetDepth(pixs);
03421     if (d == 8)
03422         return pixGrayQuantFromCmap(pixs, cmap, mindepth);
03423     else if (d == 32)
03424         return pixOctcubeQuantFromCmap(pixs, cmap, mindepth,
03425                                        level, metric);
03426     else
03427         return (PIX *)ERROR_PTR("d not 8 or 32 bpp", procName, NULL);
03428 }
03429 
03430 
03431 
03432 /*!
03433  *  pixOctcubeQuantFromCmap()
03434  *
03435  *      Input:  pixs  (32 bpp rgb)
03436  *              cmap  (to quantize to; insert copy into dest pix)
03437  *              mindepth (minimum depth of pixd: can be 2, 4 or 8 bpp)
03438  *              level (of octcube used for finding nearest color in cmap)
03439  *              metric (L_MANHATTAN_DISTANCE, L_EUCLIDEAN_DISTANCE)
03440  *      Return: pixd  (2, 4 or 8 bpp, colormapped), or null on error
03441  *
03442  *  Notes:
03443  *      (1) In typical use, we are doing an operation, such as 
03444  *          interpolative scaling, on a colormapped pix, where it is
03445  *          necessary to remove the colormap before the operation.
03446  *          We then want to re-quantize the RGB result using the same
03447  *          colormap.
03448  *      (2) The level is used to divide the color space into octcubes.
03449  *          Each input pixel is, in effect, placed at the center of an
03450  *          octcube at the given level, and it is mapped into the
03451  *          exact color (given in the colormap) that is the closest
03452  *          to that location.  We need to know that distance, for each color
03453  *          in the colormap.  The higher the level of the octtree, the smaller
03454  *          the octcubes in the color space, and hence the more accurately
03455  *          we can determine the closest color in the colormap; however,
03456  *          the size of the LUT, which is the total number of octcubes,
03457  *          increases by a factor of 8 for each increase of 1 level.
03458  *          The time required to acquire a level 4 mapping table, which has
03459  *          about 4K entries, is less than 1 msec, so that is the
03460  *          recommended minimum size to be used.  At that size, the 
03461  *          octcubes have their centers 16 units apart in each (r,g,b)
03462  *          direction.  If two colors are in the same octcube, the one
03463  *          closest to the center will always be chosen.  The maximum
03464  *          error for any component occurs when the correct color is
03465  *          at a cube corner and there is an incorrect color just inside
03466  *          the cube next to the opposite corner, giving an error of
03467  *          14 units (out of 256) for each component.   Using a level 5
03468  *          mapping table reduces the maximum error to 6 units.
03469  *      (3) Typically you should use the Euclidean metric, because the
03470  *          resulting voronoi cells (which are generated using the actual
03471  *          colormap values as seeds) are convex for Euclidean distance
03472  *          but not for Manhattan distance.  In terms of the octcubes,
03473  *          convexity of the voronoi cells means that if the 8 corners
03474  *          of any cube (of which the octcubes are special cases)
03475  *          are all within a cell, then every point in the cube will
03476  *          lie within the cell.
03477  *      (4) The depth of the output pixd is equal to the maximum of
03478  *          (a) @mindepth and (b) the minimum (2, 4 or 8 bpp) necessary
03479  *          to hold the indices in the colormap.
03480  *      (5) We build a mapping table from octcube to colormap index so
03481  *          that this function can run in a time (otherwise) independent
03482  *          of the number of colors in the colormap.  This avoids a
03483  *          brute-force search for the closest colormap color to each
03484  *          pixel in the image.
03485  *      (6) This is similar to the function pixAssignToNearestColor()
03486  *          used for color segmentation.
03487  *      (7) Except for very small images or when using level > 4,
03488  *          it takes very little time to generate the tables,
03489  *          compared to the generation of the colormapped dest pix,
03490  *          so one would not typically use the low-level version.
03491  */
03492 PIX *
03493 pixOctcubeQuantFromCmap(PIX      *pixs,
03494                         PIXCMAP  *cmap,
03495                         l_int32   mindepth,
03496                         l_int32   level,
03497                         l_int32   metric)
03498 {
03499 l_int32   *cmaptab;
03500 l_uint32  *rtab, *gtab, *btab;
03501 PIX       *pixd;
03502 
03503     PROCNAME("pixOctcubeQuantFromCmap");
03504 
03505     if (!pixs)
03506         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
03507     if (pixGetDepth(pixs) != 32)
03508         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
03509     if (!cmap)
03510         return (PIX *)ERROR_PTR("cmap not defined", procName, NULL);
03511     if (mindepth != 2 && mindepth != 4 && mindepth != 8)
03512         return (PIX *)ERROR_PTR("invalid mindepth", procName, NULL);
03513     if (level < 1 || level > 6)
03514         return (PIX *)ERROR_PTR("level not in {1...6}", procName, NULL);
03515     if (metric != L_MANHATTAN_DISTANCE && metric != L_EUCLIDEAN_DISTANCE)
03516         return (PIX *)ERROR_PTR("invalid metric", procName, NULL);
03517 
03518         /* Set up the tables to map rgb to the nearest colormap index */
03519     if (makeRGBToIndexTables(&rtab, &gtab, &btab, level))
03520         return (PIX *)ERROR_PTR("index tables not made", procName, NULL);
03521     if ((cmaptab = pixcmapToOctcubeLUT(cmap, level, metric)) == NULL)
03522         return (PIX *)ERROR_PTR("cmaptab not made", procName, NULL);
03523 
03524     pixd = pixOctcubeQuantFromCmapLUT(pixs, cmap, mindepth,
03525                                       cmaptab, rtab, gtab, btab);
03526 
03527     FREE(cmaptab);
03528     FREE(rtab);
03529     FREE(gtab);
03530     FREE(btab);
03531     return pixd;
03532 }
03533 
03534 
03535 /*!
03536  *  pixOctcubeQuantFromCmapLUT()
03537  *
03538  *      Input:  pixs  (32 bpp rgb)
03539  *              cmap  (to quantize to; insert copy into dest pix)
03540  *              mindepth (minimum depth of pixd: can be 2, 4 or 8 bpp)
03541  *              cmaptab  (table mapping from octindex to colormap index)
03542  *              rtab, gtab, btab (tables mapping from RGB to octindex)
03543  *      Return: pixd  (2, 4 or 8 bpp, colormapped), or null on error
03544  *
03545  *  Notes:
03546  *      (1) See the notes in the higher-level function
03547  *          pixOctcubeQuantFromCmap().  The octcube level for
03548  *          the generated octree is specified there, along with
03549  *          the distance metric for determining the closest
03550  *          color in the colormap to each octcube.
03551  *      (2) If the colormap, level and metric information have already
03552  *          been used to construct the set of mapping tables,
03553  *          this low-level function can be used directly (i.e.,
03554  *          independently of pixOctcubeQuantFromCmap()) to build
03555  *          a colormapped pix that uses the specified colormap.
03556  */
03557 PIX *
03558 pixOctcubeQuantFromCmapLUT(PIX       *pixs,
03559                            PIXCMAP   *cmap,
03560                            l_int32    mindepth,
03561                            l_int32   *cmaptab,
03562                            l_uint32  *rtab,
03563                            l_uint32  *gtab,
03564                            l_uint32  *btab)
03565 {
03566 l_int32    i, j, w, h, depth, wpls, wpld;
03567 l_int32    rval, gval, bval, index;
03568 l_uint32   octindex;
03569 l_uint32  *lines, *lined, *datas, *datad;
03570 PIX       *pixd;
03571 PIXCMAP   *cmapc;
03572 
03573     PROCNAME("pixOctcubeQuantFromCmapLUT");
03574 
03575     if (!pixs)
03576         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
03577     if (pixGetDepth(pixs) != 32)
03578         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
03579     if (!cmap)
03580         return (PIX *)ERROR_PTR("cmap not defined", procName, NULL);
03581     if (mindepth != 2 && mindepth != 4 && mindepth != 8)
03582         return (PIX *)ERROR_PTR("invalid mindepth", procName, NULL);
03583     if (!rtab || !gtab || !btab || !cmaptab)
03584         return (PIX *)ERROR_PTR("tables not all defined", procName, NULL);
03585 
03586         /* Init dest pix (with minimum bpp depending on cmap) */
03587     pixcmapGetMinDepth(cmap, &depth);
03588     depth = L_MAX(depth, mindepth);
03589     pixGetDimensions(pixs, &w, &h, NULL);
03590     if ((pixd = pixCreate(w, h, depth)) == NULL)
03591         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
03592     cmapc = pixcmapCopy(cmap);
03593     pixSetColormap(pixd, cmapc);
03594     pixCopyResolution(pixd, pixs);
03595     pixCopyInputFormat(pixd, pixs);
03596 
03597         /* Insert the colormap index of the color nearest to the input pixel */
03598     datas = pixGetData(pixs);
03599     datad = pixGetData(pixd);
03600     wpls = pixGetWpl(pixs);
03601     wpld = pixGetWpl(pixd);
03602     for (i = 0; i < h; i++) {
03603         lines = datas + i * wpls;
03604         lined = datad + i * wpld;
03605         for (j = 0; j < w; j++) {
03606             extractRGBValues(lines[j], &rval, &gval, &bval);
03607                 /* Map from rgb to octcube index */
03608             getOctcubeIndexFromRGB(rval, gval, bval, rtab, gtab, btab,
03609                                    &octindex);
03610                 /* Map from octcube index to nearest colormap index */
03611             index = cmaptab[octindex];
03612             if (depth == 2)
03613                 SET_DATA_DIBIT(lined, j, index);
03614             else if (depth == 4)
03615                 SET_DATA_QBIT(lined, j, index);
03616             else  /* depth == 8 */
03617                 SET_DATA_BYTE(lined, j, index);
03618         }
03619     }
03620 
03621     return pixd;
03622 }
03623 
03624 
03625 /*---------------------------------------------------------------------------*
03626  *                       Generation of octcube histogram                     *
03627  *---------------------------------------------------------------------------*/
03628 /*!
03629  *  pixOctcubeHistogram()
03630  *
03631  *      Input:  pixs (32 bpp rgb)
03632  *              level (significant bits for each of RGB; valid in [1...6])
03633  *              &ncolors (<optional return> number of occupied cubes)
03634  *      Return: numa (histogram of color pixels, or null on error)
03635  *
03636  *  Notes:
03637  *      (1) Input NULL for &ncolors to prevent computation and return value.
03638  */     
03639 NUMA *
03640 pixOctcubeHistogram(PIX      *pixs,
03641                     l_int32   level,
03642                     l_int32  *pncolors)
03643 {
03644 l_int32     size, i, j, w, h, wpl, ncolors, val;
03645 l_int32     rval, gval, bval;
03646 l_uint32    octindex;
03647 l_uint32   *rtab, *gtab, *btab;
03648 l_uint32   *data, *line;
03649 l_float32  *array;
03650 NUMA       *na;
03651 
03652     PROCNAME("pixOctcubeHistogram");
03653 
03654     if (pncolors) *pncolors = 0;
03655     if (!pixs)
03656         return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
03657     if (pixGetDepth(pixs) != 32)
03658         return (NUMA *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
03659 
03660     pixGetDimensions(pixs, &w, &h, NULL);
03661     wpl = pixGetWpl(pixs);
03662     data = pixGetData(pixs);
03663 
03664     if (octcubeGetCount(level, &size))  /* array size = 2 ** (3 * level) */
03665         return (NUMA *)ERROR_PTR("size not returned", procName, NULL);
03666     if (makeRGBToIndexTables(&rtab, &gtab, &btab, level))
03667         return (NUMA *)ERROR_PTR("tables not made", procName, NULL);
03668 
03669     if ((na = numaCreate(size)) == NULL)
03670         return (NUMA *)ERROR_PTR("na not made", procName, NULL);
03671     numaSetCount(na, size);
03672     array = numaGetFArray(na, L_NOCOPY);
03673 
03674     for (i = 0; i < h; i++) {
03675         line = data + i * wpl;
03676         for (j = 0; j < w; j++) {
03677             extractRGBValues(line[j], &rval, &gval, &bval);
03678             octindex = rtab[rval] | gtab[gval] | btab[bval];
03679 #if DEBUG_OCTINDEX
03680             if ((level == 1 && octindex > 7) ||
03681                 (level == 2 && octindex > 63) ||
03682                 (level == 3 && octindex > 511) ||
03683                 (level == 4 && octindex > 4097) ||
03684                 (level == 5 && octindex > 32783) ||
03685                 (level == 6 && octindex > 262271)) {
03686                 fprintf(stderr, "level = %d, octindex = %d, index error!\n",
03687                         level, octindex);
03688                 continue;
03689             }
03690 #endif  /* DEBUG_OCTINDEX */
03691               array[octindex] += 1.0;
03692         }
03693     }
03694 
03695     if (pncolors) {
03696         for (i = 0, ncolors = 0; i < size; i++) {
03697             numaGetIValue(na, i, &val);
03698             if (val > 0)
03699                 ncolors++;
03700         }
03701         *pncolors = ncolors;
03702     }
03703 
03704     FREE(rtab);
03705     FREE(gtab);
03706     FREE(btab);
03707     return na;
03708 }
03709 
03710 
03711 /*------------------------------------------------------------------*
03712  *              Get filled octcube table from colormap              *
03713  *------------------------------------------------------------------*/
03714 /*!
03715  *  pixcmapToOctcubeLUT()
03716  *
03717  *      Input:  cmap
03718  *              level (significant bits for each of RGB; valid in [1...6])
03719  *              metric (L_MANHATTAN_DISTANCE, L_EUCLIDEAN_DISTANCE)
03720  *      Return: tab[2**(3 * level)]
03721  *
03722  *  Notes:
03723  *      (1) This function is used to quickly find the colormap color
03724  *          that is closest to any rgb color.  It is used to assign
03725  *          rgb colors to an existing colormap.  It can be very expensive
03726  *          to search through the entire colormap for the closest color
03727  *          to each pixel.  Instead, we first set up this table, which is
03728  *          populated by the colormap index nearest to each octcube
03729  *          color.  Then we go through the image; for each pixel,
03730  *          do two table lookups: first to generate the octcube index
03731  *          from rgb and second to use this table to read out the
03732  *          colormap index.
03733  *      (2) Do a slight modification for white and black.  For level = 4,
03734  *          each octcube size is 16.  The center of the whitest octcube
03735  *          is at (248, 248, 248), which is closer to 242 than 255.
03736  *          Consequently, any gray color between 242 and 254 will
03737  *          be selected, even if white (255, 255, 255) exists.  This is
03738  *          typically not optimal, because the original color was
03739  *          likely white.  Therefore, if white exists in the colormap,
03740  *          use it for any rgb color that falls into the most white octcube.
03741  *          Do the similar thing for black.
03742  *      (3) Here are the actual function calls for quantizing to a
03743  *          specified colormap:
03744  *            - first make the tables that map from rgb --> octcube index
03745  *                     makeRGBToIndexTables()
03746  *            - then for each pixel:
03747  *                * use the tables to get the octcube index
03748  *                     getOctcubeIndexFromRGB()
03749  *                * use this table to get the nearest color in the colormap
03750  *                     cmap_index = tab[index]
03751  *      (4) Distance can be either manhattan or euclidean.
03752  *      (5) In typical use, level = 4 gives reasonable results, and
03753  *          level = 5 is slightly better.  When this function is used
03754  *          for color segmentation, there are typically a small number
03755  *          of colors and the number of levels can be small (e.g., level = 3).
03756  */
03757 l_int32 *
03758 pixcmapToOctcubeLUT(PIXCMAP  *cmap,
03759                     l_int32   level,
03760                     l_int32   metric)
03761 {
03762 l_int32    i, k, size, ncolors, mindist, dist, mincolor, index;
03763 l_int32    rval, gval, bval;  /* color at center of the octcube */
03764 l_int32   *rmap, *gmap, *bmap, *tab;
03765 
03766     PROCNAME("pixcmapToOctcubeLUT");
03767 
03768     if (!cmap)
03769         return (l_int32 *)ERROR_PTR("cmap not defined", procName, NULL);
03770     if (level < 1 || level > 6)
03771         return (l_int32 *)ERROR_PTR("level not in {1...6}", procName, NULL);
03772     if (metric != L_MANHATTAN_DISTANCE && metric != L_EUCLIDEAN_DISTANCE)
03773         return (l_int32 *)ERROR_PTR("invalid metric", procName, NULL);
03774 
03775     if (octcubeGetCount(level, &size))  /* array size = 2 ** (3 * level) */
03776         return (l_int32 *)ERROR_PTR("size not returned", procName, NULL);
03777     if ((tab = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
03778         return (l_int32 *)ERROR_PTR("tab not allocated", procName, NULL);
03779 
03780     ncolors = pixcmapGetCount(cmap);
03781     pixcmapToArrays(cmap, &rmap, &gmap, &bmap);
03782 
03783         /* Assign based on the closest octcube center to the cmap color */
03784     for (i = 0; i < size; i++) {
03785         getRGBFromOctcube(i, level, &rval, &gval, &bval);
03786         mindist = 1000000;
03787         mincolor = 0;  /* irrelevant init */
03788         for (k = 0; k < ncolors; k++) {
03789             if (metric == L_MANHATTAN_DISTANCE) {
03790                 dist = L_ABS(rval - rmap[k]) + L_ABS(gval - gmap[k]) +
03791                        L_ABS(bval - bmap[k]);
03792             }
03793             else {  /* L_EUCLIDEAN_DISTANCE */
03794                 dist = (rval - rmap[k]) * (rval - rmap[k]) +
03795                        (gval - gmap[k]) * (gval - gmap[k]) +
03796                        (bval - bmap[k]) * (bval - bmap[k]);
03797             }
03798             if (dist < mindist) {
03799                 mindist = dist;
03800                 mincolor = k;
03801             }
03802         }
03803         tab[i] = mincolor;
03804     }
03805 
03806         /* Reset black and white if available in the colormap.
03807          * The darkest octcube is at octindex 0.
03808          * The lightest octcube is at the max octindex. */
03809     pixcmapGetNearestIndex(cmap, 0, 0, 0, &index);
03810     pixcmapGetColor(cmap, index, &rval, &gval, &bval);
03811     if (rval < 7 && gval < 7 && bval < 7) {
03812         tab[0] = index;
03813     }
03814     pixcmapGetNearestIndex(cmap, 255, 255, 255, &index);
03815     pixcmapGetColor(cmap, index, &rval, &gval, &bval);
03816     if (rval > 248 && gval > 248 && bval > 248) {
03817         tab[(1 << (3 * level)) - 1] = index;
03818     }
03819 
03820     FREE(rmap);
03821     FREE(gmap);
03822     FREE(bmap);
03823     return tab;
03824 }
03825 
03826 
03827 /*------------------------------------------------------------------*
03828  *               Strip out unused elements in colormap              *
03829  *------------------------------------------------------------------*/
03830 /*!
03831  *  pixRemoveUnusedColors()
03832  *
03833  *      Input:  pixs  (colormapped)
03834  *      Return: 0 if OK, 1 on error
03835  *
03836  *  Notes:
03837  *      (1) This is an in-place operation.
03838  *      (2) If the image doesn't have a colormap, returns without error.
03839  *      (3) Unusued colors are removed from the colormap, and the
03840  *          image pixels are re-numbered.
03841  */
03842 l_int32
03843 pixRemoveUnusedColors(PIX  *pixs)
03844 {
03845 l_int32     i, j, w, h, d, nc, wpls, val, newval, index, zerofound;
03846 l_int32     rval, gval, bval;
03847 l_uint32   *datas, *lines;
03848 l_int32    *histo, *map1, *map2;
03849 PIXCMAP    *cmap, *cmapd;
03850 
03851     PROCNAME("pixRemoveUnusedColors");
03852 
03853     if (!pixs)
03854         return ERROR_INT("pixs not defined", procName, 1);
03855     if ((cmap = pixGetColormap(pixs)) == NULL)
03856         return 0;
03857 
03858     d = pixGetDepth(pixs);
03859     if (d != 2 && d != 4 && d != 8)
03860         return ERROR_INT("d not in {2, 4, 8}", procName, 1);
03861 
03862         /* Find which indices are actually used */
03863     nc = pixcmapGetCount(cmap);
03864     if ((histo = (l_int32 *)CALLOC(nc, sizeof(l_int32))) == NULL)
03865         return ERROR_INT("histo not made", procName, 1);
03866     pixGetDimensions(pixs, &w, &h, NULL);
03867     wpls = pixGetWpl(pixs);
03868     datas = pixGetData(pixs);
03869     for (i = 0; i < h; i++) {
03870         lines = datas + i * wpls;
03871         for (j = 0; j < w; j++) {
03872             switch (d)
03873             {
03874             case 2:
03875                 val = GET_DATA_DIBIT(lines, j);
03876                 break;
03877             case 4:
03878                 val = GET_DATA_QBIT(lines, j);
03879                 break;
03880             case 8:
03881                 val = GET_DATA_BYTE(lines, j);
03882                 break;
03883             default:
03884                 return ERROR_INT("switch ran off end!", procName, 1);
03885             }
03886             if (val >= nc) {
03887                 L_WARNING("cmap index out of bounds!", procName);
03888                 continue;
03889             }
03890             histo[val]++;
03891         }
03892     }
03893 
03894         /* Check if there are any zeroes.  If none, quit. */
03895     zerofound = FALSE;
03896     for (i = 0; i < nc; i++) {
03897         if (histo[i] == 0) {
03898             zerofound = TRUE;
03899             break;
03900         }
03901     }
03902     if (!zerofound) {
03903       FREE(histo);
03904       return 0;
03905     }
03906 
03907         /* Generate mapping tables between indices */
03908     if ((map1 = (l_int32 *)CALLOC(nc, sizeof(l_int32))) == NULL)
03909         return ERROR_INT("map1 not made", procName, 1);
03910     if ((map2 = (l_int32 *)CALLOC(nc, sizeof(l_int32))) == NULL)
03911         return ERROR_INT("map2 not made", procName, 1);
03912     index = 0;
03913     for (i = 0; i < nc; i++) {
03914         if (histo[i] != 0) {
03915             map1[index] = i;  /* get old index from new */
03916             map2[i] = index;  /* get new index from old */
03917             index++;
03918         }
03919     }
03920 
03921         /* Generate new colormap and attach to pixs */
03922     cmapd = pixcmapCreate(d);
03923     for (i = 0; i < index; i++) {
03924         pixcmapGetColor(cmap, map1[i], &rval, &gval, &bval);
03925         pixcmapAddColor(cmapd, rval, gval, bval);
03926     }
03927     pixSetColormap(pixs, cmapd);
03928 
03929         /* Map pixel (index) values to new cmap */
03930     for (i = 0; i < h; i++) {
03931         lines = datas + i * wpls;
03932         for (j = 0; j < w; j++) {
03933             switch (d)
03934             {
03935             case 2:
03936                 val = GET_DATA_DIBIT(lines, j);
03937                 newval = map2[val];
03938                 SET_DATA_DIBIT(lines, j, newval);
03939                 break;
03940             case 4:
03941                 val = GET_DATA_QBIT(lines, j);
03942                 newval = map2[val];
03943                 SET_DATA_QBIT(lines, j, newval);
03944                 break;
03945             case 8:
03946                 val = GET_DATA_BYTE(lines, j);
03947                 newval = map2[val];
03948                 SET_DATA_BYTE(lines, j, newval);
03949                 break;
03950             default:
03951                 return ERROR_INT("switch ran off end!", procName, 1);
03952             }
03953         }
03954     }
03955         
03956     FREE(histo);
03957     FREE(map1);
03958     FREE(map2);
03959     return 0;
03960 }
03961 
03962 
03963 /*------------------------------------------------------------------*
03964  *      Find number of occupied octcubes at the specified level     *
03965  *------------------------------------------------------------------*/
03966 /*!
03967  *  pixNumberOccupiedOctcubes()
03968  *
03969  *      Input:  pix (32 bpp)
03970  *              level (of octcube)
03971  *              mincount (minimum num pixels in an octcube to be counted;
03972  *                        -1 to not use)
03973  *              minfract (minimum fract of pixels in an octcube to be
03974  *                        counted; -1 to not use)
03975  *              &ncolors (<return> number of occupied octcubes)
03976  *      Return: 0 if OK, 1 on error
03977  *
03978  *  Notes:
03979  *      (1) Exactly one of (@mincount, @minfract) must be -1, so, e.g.,
03980  *          if @mincount == -1, then we use @minfract.
03981  *      (2) If all occupied octcubes are to count, set @mincount == 1.
03982  *          Setting @minfract == 0.0 is taken to mean the same thing.
03983  */
03984 l_int32
03985 pixNumberOccupiedOctcubes(PIX       *pix,
03986                           l_int32    level,
03987                           l_int32    mincount,
03988                           l_float32  minfract,
03989                           l_int32   *pncolors)
03990 {
03991 l_int32    i, j, w, h, d, wpl, ncolors, size, octindex;
03992 l_int32    rval, gval, bval;
03993 l_int32   *carray;
03994 l_uint32  *data, *line, *rtab, *gtab, *btab;
03995 
03996     PROCNAME("pixNumberOccupiedOctcubes");
03997 
03998     if (!pncolors)
03999         return ERROR_INT("&ncolors not defined", procName, 1);
04000     *pncolors = 0;
04001     if (!pix)
04002         return ERROR_INT("pix not defined", procName, 1);
04003     pixGetDimensions(pix, &w, &h, &d);
04004     if (d != 32)
04005         return ERROR_INT("pix not 32 bpp", procName, 1);
04006     if (level < 1 || level > 6)
04007         return ERROR_INT("invalid level", procName, 1);
04008     if ((mincount < 0 && minfract < 0) || (mincount >= 0.0 && minfract >= 0.0))
04009         return ERROR_INT("invalid mincount/minfract", procName, 1);
04010     if (mincount == 0 || minfract == 0.0)
04011         mincount = 1;
04012     else if (minfract > 0.0)
04013         mincount = L_MIN(1, (l_int32)(minfract * w * h));
04014 
04015     if (octcubeGetCount(level, &size))  /* array size = 2 ** (3 * level) */
04016         return ERROR_INT("size not returned", procName, 1);
04017     if (makeRGBToIndexTables(&rtab, &gtab, &btab, level))
04018         return ERROR_INT("tables not made", procName, 1);
04019     if ((carray = (l_int32 *)CALLOC(size, sizeof(l_int32))) == NULL)
04020         return ERROR_INT("carray not made", procName, 1);
04021 
04022         /* Mark the occupied octcube leaves */
04023     data = pixGetData(pix);
04024     wpl = pixGetWpl(pix);
04025     for (i = 0; i < h; i++) {
04026         line = data + i * wpl;
04027         for (j = 0; j < w; j++) {
04028             extractRGBValues(line[j], &rval, &gval, &bval);
04029             octindex = rtab[rval] | gtab[gval] | btab[bval];
04030             carray[octindex]++;
04031         }
04032     }
04033 
04034         /* Count them */
04035     for (i = 0, ncolors = 0; i < size; i++) {
04036         if (carray[i] >= mincount)
04037             ncolors++;
04038     }
04039     *pncolors = ncolors;
04040 
04041     FREE(carray);
04042     FREE(rtab);
04043     FREE(gtab);
04044     FREE(btab);
04045     return 0;
04046 }
04047 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines