Leptonica 1.68
C Image Processing Library
|
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, >ab, &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, >ab, &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, >ab, &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, >ab, &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, >ab2, &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, >ab, &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, >ab, &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, >ab, &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, >ab, &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, >ab, &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, >ab, &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, >ab, &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, >ab, &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, >ab, &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