xref: /aosp_15_r20/external/libjpeg-turbo/jquant2.c (revision dfc6aa5c1cfd4bc4e2018dc74aa96e29ee49c6da)
1*dfc6aa5cSAndroid Build Coastguard Worker /*
2*dfc6aa5cSAndroid Build Coastguard Worker  * jquant2.c
3*dfc6aa5cSAndroid Build Coastguard Worker  *
4*dfc6aa5cSAndroid Build Coastguard Worker  * This file was part of the Independent JPEG Group's software:
5*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 1991-1996, Thomas G. Lane.
6*dfc6aa5cSAndroid Build Coastguard Worker  * libjpeg-turbo Modifications:
7*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 2009, 2014-2015, 2020, D. R. Commander.
8*dfc6aa5cSAndroid Build Coastguard Worker  * For conditions of distribution and use, see the accompanying README.ijg
9*dfc6aa5cSAndroid Build Coastguard Worker  * file.
10*dfc6aa5cSAndroid Build Coastguard Worker  *
11*dfc6aa5cSAndroid Build Coastguard Worker  * This file contains 2-pass color quantization (color mapping) routines.
12*dfc6aa5cSAndroid Build Coastguard Worker  * These routines provide selection of a custom color map for an image,
13*dfc6aa5cSAndroid Build Coastguard Worker  * followed by mapping of the image to that color map, with optional
14*dfc6aa5cSAndroid Build Coastguard Worker  * Floyd-Steinberg dithering.
15*dfc6aa5cSAndroid Build Coastguard Worker  * It is also possible to use just the second pass to map to an arbitrary
16*dfc6aa5cSAndroid Build Coastguard Worker  * externally-given color map.
17*dfc6aa5cSAndroid Build Coastguard Worker  *
18*dfc6aa5cSAndroid Build Coastguard Worker  * Note: ordered dithering is not supported, since there isn't any fast
19*dfc6aa5cSAndroid Build Coastguard Worker  * way to compute intercolor distances; it's unclear that ordered dither's
20*dfc6aa5cSAndroid Build Coastguard Worker  * fundamental assumptions even hold with an irregularly spaced color map.
21*dfc6aa5cSAndroid Build Coastguard Worker  */
22*dfc6aa5cSAndroid Build Coastguard Worker 
23*dfc6aa5cSAndroid Build Coastguard Worker #define JPEG_INTERNALS
24*dfc6aa5cSAndroid Build Coastguard Worker #include "jinclude.h"
25*dfc6aa5cSAndroid Build Coastguard Worker #include "jpeglib.h"
26*dfc6aa5cSAndroid Build Coastguard Worker 
27*dfc6aa5cSAndroid Build Coastguard Worker #ifdef QUANT_2PASS_SUPPORTED
28*dfc6aa5cSAndroid Build Coastguard Worker 
29*dfc6aa5cSAndroid Build Coastguard Worker 
30*dfc6aa5cSAndroid Build Coastguard Worker /*
31*dfc6aa5cSAndroid Build Coastguard Worker  * This module implements the well-known Heckbert paradigm for color
32*dfc6aa5cSAndroid Build Coastguard Worker  * quantization.  Most of the ideas used here can be traced back to
33*dfc6aa5cSAndroid Build Coastguard Worker  * Heckbert's seminal paper
34*dfc6aa5cSAndroid Build Coastguard Worker  *   Heckbert, Paul.  "Color Image Quantization for Frame Buffer Display",
35*dfc6aa5cSAndroid Build Coastguard Worker  *   Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304.
36*dfc6aa5cSAndroid Build Coastguard Worker  *
37*dfc6aa5cSAndroid Build Coastguard Worker  * In the first pass over the image, we accumulate a histogram showing the
38*dfc6aa5cSAndroid Build Coastguard Worker  * usage count of each possible color.  To keep the histogram to a reasonable
39*dfc6aa5cSAndroid Build Coastguard Worker  * size, we reduce the precision of the input; typical practice is to retain
40*dfc6aa5cSAndroid Build Coastguard Worker  * 5 or 6 bits per color, so that 8 or 4 different input values are counted
41*dfc6aa5cSAndroid Build Coastguard Worker  * in the same histogram cell.
42*dfc6aa5cSAndroid Build Coastguard Worker  *
43*dfc6aa5cSAndroid Build Coastguard Worker  * Next, the color-selection step begins with a box representing the whole
44*dfc6aa5cSAndroid Build Coastguard Worker  * color space, and repeatedly splits the "largest" remaining box until we
45*dfc6aa5cSAndroid Build Coastguard Worker  * have as many boxes as desired colors.  Then the mean color in each
46*dfc6aa5cSAndroid Build Coastguard Worker  * remaining box becomes one of the possible output colors.
47*dfc6aa5cSAndroid Build Coastguard Worker  *
48*dfc6aa5cSAndroid Build Coastguard Worker  * The second pass over the image maps each input pixel to the closest output
49*dfc6aa5cSAndroid Build Coastguard Worker  * color (optionally after applying a Floyd-Steinberg dithering correction).
50*dfc6aa5cSAndroid Build Coastguard Worker  * This mapping is logically trivial, but making it go fast enough requires
51*dfc6aa5cSAndroid Build Coastguard Worker  * considerable care.
52*dfc6aa5cSAndroid Build Coastguard Worker  *
53*dfc6aa5cSAndroid Build Coastguard Worker  * Heckbert-style quantizers vary a good deal in their policies for choosing
54*dfc6aa5cSAndroid Build Coastguard Worker  * the "largest" box and deciding where to cut it.  The particular policies
55*dfc6aa5cSAndroid Build Coastguard Worker  * used here have proved out well in experimental comparisons, but better ones
56*dfc6aa5cSAndroid Build Coastguard Worker  * may yet be found.
57*dfc6aa5cSAndroid Build Coastguard Worker  *
58*dfc6aa5cSAndroid Build Coastguard Worker  * In earlier versions of the IJG code, this module quantized in YCbCr color
59*dfc6aa5cSAndroid Build Coastguard Worker  * space, processing the raw upsampled data without a color conversion step.
60*dfc6aa5cSAndroid Build Coastguard Worker  * This allowed the color conversion math to be done only once per colormap
61*dfc6aa5cSAndroid Build Coastguard Worker  * entry, not once per pixel.  However, that optimization precluded other
62*dfc6aa5cSAndroid Build Coastguard Worker  * useful optimizations (such as merging color conversion with upsampling)
63*dfc6aa5cSAndroid Build Coastguard Worker  * and it also interfered with desired capabilities such as quantizing to an
64*dfc6aa5cSAndroid Build Coastguard Worker  * externally-supplied colormap.  We have therefore abandoned that approach.
65*dfc6aa5cSAndroid Build Coastguard Worker  * The present code works in the post-conversion color space, typically RGB.
66*dfc6aa5cSAndroid Build Coastguard Worker  *
67*dfc6aa5cSAndroid Build Coastguard Worker  * To improve the visual quality of the results, we actually work in scaled
68*dfc6aa5cSAndroid Build Coastguard Worker  * RGB space, giving G distances more weight than R, and R in turn more than
69*dfc6aa5cSAndroid Build Coastguard Worker  * B.  To do everything in integer math, we must use integer scale factors.
70*dfc6aa5cSAndroid Build Coastguard Worker  * The 2/3/1 scale factors used here correspond loosely to the relative
71*dfc6aa5cSAndroid Build Coastguard Worker  * weights of the colors in the NTSC grayscale equation.
72*dfc6aa5cSAndroid Build Coastguard Worker  * If you want to use this code to quantize a non-RGB color space, you'll
73*dfc6aa5cSAndroid Build Coastguard Worker  * probably need to change these scale factors.
74*dfc6aa5cSAndroid Build Coastguard Worker  */
75*dfc6aa5cSAndroid Build Coastguard Worker 
76*dfc6aa5cSAndroid Build Coastguard Worker #define R_SCALE  2              /* scale R distances by this much */
77*dfc6aa5cSAndroid Build Coastguard Worker #define G_SCALE  3              /* scale G distances by this much */
78*dfc6aa5cSAndroid Build Coastguard Worker #define B_SCALE  1              /* and B by this much */
79*dfc6aa5cSAndroid Build Coastguard Worker 
80*dfc6aa5cSAndroid Build Coastguard Worker static const int c_scales[3] = { R_SCALE, G_SCALE, B_SCALE };
81*dfc6aa5cSAndroid Build Coastguard Worker #define C0_SCALE  c_scales[rgb_red[cinfo->out_color_space]]
82*dfc6aa5cSAndroid Build Coastguard Worker #define C1_SCALE  c_scales[rgb_green[cinfo->out_color_space]]
83*dfc6aa5cSAndroid Build Coastguard Worker #define C2_SCALE  c_scales[rgb_blue[cinfo->out_color_space]]
84*dfc6aa5cSAndroid Build Coastguard Worker 
85*dfc6aa5cSAndroid Build Coastguard Worker /*
86*dfc6aa5cSAndroid Build Coastguard Worker  * First we have the histogram data structure and routines for creating it.
87*dfc6aa5cSAndroid Build Coastguard Worker  *
88*dfc6aa5cSAndroid Build Coastguard Worker  * The number of bits of precision can be adjusted by changing these symbols.
89*dfc6aa5cSAndroid Build Coastguard Worker  * We recommend keeping 6 bits for G and 5 each for R and B.
90*dfc6aa5cSAndroid Build Coastguard Worker  * If you have plenty of memory and cycles, 6 bits all around gives marginally
91*dfc6aa5cSAndroid Build Coastguard Worker  * better results; if you are short of memory, 5 bits all around will save
92*dfc6aa5cSAndroid Build Coastguard Worker  * some space but degrade the results.
93*dfc6aa5cSAndroid Build Coastguard Worker  * To maintain a fully accurate histogram, we'd need to allocate a "long"
94*dfc6aa5cSAndroid Build Coastguard Worker  * (preferably unsigned long) for each cell.  In practice this is overkill;
95*dfc6aa5cSAndroid Build Coastguard Worker  * we can get by with 16 bits per cell.  Few of the cell counts will overflow,
96*dfc6aa5cSAndroid Build Coastguard Worker  * and clamping those that do overflow to the maximum value will give close-
97*dfc6aa5cSAndroid Build Coastguard Worker  * enough results.  This reduces the recommended histogram size from 256Kb
98*dfc6aa5cSAndroid Build Coastguard Worker  * to 128Kb, which is a useful savings on PC-class machines.
99*dfc6aa5cSAndroid Build Coastguard Worker  * (In the second pass the histogram space is re-used for pixel mapping data;
100*dfc6aa5cSAndroid Build Coastguard Worker  * in that capacity, each cell must be able to store zero to the number of
101*dfc6aa5cSAndroid Build Coastguard Worker  * desired colors.  16 bits/cell is plenty for that too.)
102*dfc6aa5cSAndroid Build Coastguard Worker  * Since the JPEG code is intended to run in small memory model on 80x86
103*dfc6aa5cSAndroid Build Coastguard Worker  * machines, we can't just allocate the histogram in one chunk.  Instead
104*dfc6aa5cSAndroid Build Coastguard Worker  * of a true 3-D array, we use a row of pointers to 2-D arrays.  Each
105*dfc6aa5cSAndroid Build Coastguard Worker  * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and
106*dfc6aa5cSAndroid Build Coastguard Worker  * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries.
107*dfc6aa5cSAndroid Build Coastguard Worker  */
108*dfc6aa5cSAndroid Build Coastguard Worker 
109*dfc6aa5cSAndroid Build Coastguard Worker #define MAXNUMCOLORS  (MAXJSAMPLE + 1) /* maximum size of colormap */
110*dfc6aa5cSAndroid Build Coastguard Worker 
111*dfc6aa5cSAndroid Build Coastguard Worker /* These will do the right thing for either R,G,B or B,G,R color order,
112*dfc6aa5cSAndroid Build Coastguard Worker  * but you may not like the results for other color orders.
113*dfc6aa5cSAndroid Build Coastguard Worker  */
114*dfc6aa5cSAndroid Build Coastguard Worker #define HIST_C0_BITS  5         /* bits of precision in R/B histogram */
115*dfc6aa5cSAndroid Build Coastguard Worker #define HIST_C1_BITS  6         /* bits of precision in G histogram */
116*dfc6aa5cSAndroid Build Coastguard Worker #define HIST_C2_BITS  5         /* bits of precision in B/R histogram */
117*dfc6aa5cSAndroid Build Coastguard Worker 
118*dfc6aa5cSAndroid Build Coastguard Worker /* Number of elements along histogram axes. */
119*dfc6aa5cSAndroid Build Coastguard Worker #define HIST_C0_ELEMS  (1 << HIST_C0_BITS)
120*dfc6aa5cSAndroid Build Coastguard Worker #define HIST_C1_ELEMS  (1 << HIST_C1_BITS)
121*dfc6aa5cSAndroid Build Coastguard Worker #define HIST_C2_ELEMS  (1 << HIST_C2_BITS)
122*dfc6aa5cSAndroid Build Coastguard Worker 
123*dfc6aa5cSAndroid Build Coastguard Worker /* These are the amounts to shift an input value to get a histogram index. */
124*dfc6aa5cSAndroid Build Coastguard Worker #define C0_SHIFT  (BITS_IN_JSAMPLE - HIST_C0_BITS)
125*dfc6aa5cSAndroid Build Coastguard Worker #define C1_SHIFT  (BITS_IN_JSAMPLE - HIST_C1_BITS)
126*dfc6aa5cSAndroid Build Coastguard Worker #define C2_SHIFT  (BITS_IN_JSAMPLE - HIST_C2_BITS)
127*dfc6aa5cSAndroid Build Coastguard Worker 
128*dfc6aa5cSAndroid Build Coastguard Worker 
129*dfc6aa5cSAndroid Build Coastguard Worker typedef UINT16 histcell;        /* histogram cell; prefer an unsigned type */
130*dfc6aa5cSAndroid Build Coastguard Worker 
131*dfc6aa5cSAndroid Build Coastguard Worker typedef histcell *histptr;      /* for pointers to histogram cells */
132*dfc6aa5cSAndroid Build Coastguard Worker 
133*dfc6aa5cSAndroid Build Coastguard Worker typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the array */
134*dfc6aa5cSAndroid Build Coastguard Worker typedef hist1d *hist2d;         /* type for the 2nd-level pointers */
135*dfc6aa5cSAndroid Build Coastguard Worker typedef hist2d *hist3d;         /* type for top-level pointer */
136*dfc6aa5cSAndroid Build Coastguard Worker 
137*dfc6aa5cSAndroid Build Coastguard Worker 
138*dfc6aa5cSAndroid Build Coastguard Worker /* Declarations for Floyd-Steinberg dithering.
139*dfc6aa5cSAndroid Build Coastguard Worker  *
140*dfc6aa5cSAndroid Build Coastguard Worker  * Errors are accumulated into the array fserrors[], at a resolution of
141*dfc6aa5cSAndroid Build Coastguard Worker  * 1/16th of a pixel count.  The error at a given pixel is propagated
142*dfc6aa5cSAndroid Build Coastguard Worker  * to its not-yet-processed neighbors using the standard F-S fractions,
143*dfc6aa5cSAndroid Build Coastguard Worker  *              ...     (here)  7/16
144*dfc6aa5cSAndroid Build Coastguard Worker  *              3/16    5/16    1/16
145*dfc6aa5cSAndroid Build Coastguard Worker  * We work left-to-right on even rows, right-to-left on odd rows.
146*dfc6aa5cSAndroid Build Coastguard Worker  *
147*dfc6aa5cSAndroid Build Coastguard Worker  * We can get away with a single array (holding one row's worth of errors)
148*dfc6aa5cSAndroid Build Coastguard Worker  * by using it to store the current row's errors at pixel columns not yet
149*dfc6aa5cSAndroid Build Coastguard Worker  * processed, but the next row's errors at columns already processed.  We
150*dfc6aa5cSAndroid Build Coastguard Worker  * need only a few extra variables to hold the errors immediately around the
151*dfc6aa5cSAndroid Build Coastguard Worker  * current column.  (If we are lucky, those variables are in registers, but
152*dfc6aa5cSAndroid Build Coastguard Worker  * even if not, they're probably cheaper to access than array elements are.)
153*dfc6aa5cSAndroid Build Coastguard Worker  *
154*dfc6aa5cSAndroid Build Coastguard Worker  * The fserrors[] array has (#columns + 2) entries; the extra entry at
155*dfc6aa5cSAndroid Build Coastguard Worker  * each end saves us from special-casing the first and last pixels.
156*dfc6aa5cSAndroid Build Coastguard Worker  * Each entry is three values long, one value for each color component.
157*dfc6aa5cSAndroid Build Coastguard Worker  */
158*dfc6aa5cSAndroid Build Coastguard Worker 
159*dfc6aa5cSAndroid Build Coastguard Worker #if BITS_IN_JSAMPLE == 8
160*dfc6aa5cSAndroid Build Coastguard Worker typedef INT16 FSERROR;          /* 16 bits should be enough */
161*dfc6aa5cSAndroid Build Coastguard Worker typedef int LOCFSERROR;         /* use 'int' for calculation temps */
162*dfc6aa5cSAndroid Build Coastguard Worker #else
163*dfc6aa5cSAndroid Build Coastguard Worker typedef JLONG FSERROR;          /* may need more than 16 bits */
164*dfc6aa5cSAndroid Build Coastguard Worker typedef JLONG LOCFSERROR;       /* be sure calculation temps are big enough */
165*dfc6aa5cSAndroid Build Coastguard Worker #endif
166*dfc6aa5cSAndroid Build Coastguard Worker 
167*dfc6aa5cSAndroid Build Coastguard Worker typedef FSERROR *FSERRPTR;      /* pointer to error array */
168*dfc6aa5cSAndroid Build Coastguard Worker 
169*dfc6aa5cSAndroid Build Coastguard Worker 
170*dfc6aa5cSAndroid Build Coastguard Worker /* Private subobject */
171*dfc6aa5cSAndroid Build Coastguard Worker 
172*dfc6aa5cSAndroid Build Coastguard Worker typedef struct {
173*dfc6aa5cSAndroid Build Coastguard Worker   struct jpeg_color_quantizer pub; /* public fields */
174*dfc6aa5cSAndroid Build Coastguard Worker 
175*dfc6aa5cSAndroid Build Coastguard Worker   /* Space for the eventually created colormap is stashed here */
176*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPARRAY sv_colormap;       /* colormap allocated at init time */
177*dfc6aa5cSAndroid Build Coastguard Worker   int desired;                  /* desired # of colors = size of colormap */
178*dfc6aa5cSAndroid Build Coastguard Worker 
179*dfc6aa5cSAndroid Build Coastguard Worker   /* Variables for accumulating image statistics */
180*dfc6aa5cSAndroid Build Coastguard Worker   hist3d histogram;             /* pointer to the histogram */
181*dfc6aa5cSAndroid Build Coastguard Worker 
182*dfc6aa5cSAndroid Build Coastguard Worker   boolean needs_zeroed;         /* TRUE if next pass must zero histogram */
183*dfc6aa5cSAndroid Build Coastguard Worker 
184*dfc6aa5cSAndroid Build Coastguard Worker   /* Variables for Floyd-Steinberg dithering */
185*dfc6aa5cSAndroid Build Coastguard Worker   FSERRPTR fserrors;            /* accumulated errors */
186*dfc6aa5cSAndroid Build Coastguard Worker   boolean on_odd_row;           /* flag to remember which row we are on */
187*dfc6aa5cSAndroid Build Coastguard Worker   int *error_limiter;           /* table for clamping the applied error */
188*dfc6aa5cSAndroid Build Coastguard Worker } my_cquantizer;
189*dfc6aa5cSAndroid Build Coastguard Worker 
190*dfc6aa5cSAndroid Build Coastguard Worker typedef my_cquantizer *my_cquantize_ptr;
191*dfc6aa5cSAndroid Build Coastguard Worker 
192*dfc6aa5cSAndroid Build Coastguard Worker 
193*dfc6aa5cSAndroid Build Coastguard Worker /*
194*dfc6aa5cSAndroid Build Coastguard Worker  * Prescan some rows of pixels.
195*dfc6aa5cSAndroid Build Coastguard Worker  * In this module the prescan simply updates the histogram, which has been
196*dfc6aa5cSAndroid Build Coastguard Worker  * initialized to zeroes by start_pass.
197*dfc6aa5cSAndroid Build Coastguard Worker  * An output_buf parameter is required by the method signature, but no data
198*dfc6aa5cSAndroid Build Coastguard Worker  * is actually output (in fact the buffer controller is probably passing a
199*dfc6aa5cSAndroid Build Coastguard Worker  * NULL pointer).
200*dfc6aa5cSAndroid Build Coastguard Worker  */
201*dfc6aa5cSAndroid Build Coastguard Worker 
202*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
prescan_quantize(j_decompress_ptr cinfo,JSAMPARRAY input_buf,JSAMPARRAY output_buf,int num_rows)203*dfc6aa5cSAndroid Build Coastguard Worker prescan_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
204*dfc6aa5cSAndroid Build Coastguard Worker                  JSAMPARRAY output_buf, int num_rows)
205*dfc6aa5cSAndroid Build Coastguard Worker {
206*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
207*dfc6aa5cSAndroid Build Coastguard Worker   register JSAMPROW ptr;
208*dfc6aa5cSAndroid Build Coastguard Worker   register histptr histp;
209*dfc6aa5cSAndroid Build Coastguard Worker   register hist3d histogram = cquantize->histogram;
210*dfc6aa5cSAndroid Build Coastguard Worker   int row;
211*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION col;
212*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION width = cinfo->output_width;
213*dfc6aa5cSAndroid Build Coastguard Worker 
214*dfc6aa5cSAndroid Build Coastguard Worker   for (row = 0; row < num_rows; row++) {
215*dfc6aa5cSAndroid Build Coastguard Worker     ptr = input_buf[row];
216*dfc6aa5cSAndroid Build Coastguard Worker     for (col = width; col > 0; col--) {
217*dfc6aa5cSAndroid Build Coastguard Worker       /* get pixel value and index into the histogram */
218*dfc6aa5cSAndroid Build Coastguard Worker       histp = &histogram[ptr[0] >> C0_SHIFT]
219*dfc6aa5cSAndroid Build Coastguard Worker                         [ptr[1] >> C1_SHIFT]
220*dfc6aa5cSAndroid Build Coastguard Worker                         [ptr[2] >> C2_SHIFT];
221*dfc6aa5cSAndroid Build Coastguard Worker       /* increment, check for overflow and undo increment if so. */
222*dfc6aa5cSAndroid Build Coastguard Worker       if (++(*histp) <= 0)
223*dfc6aa5cSAndroid Build Coastguard Worker         (*histp)--;
224*dfc6aa5cSAndroid Build Coastguard Worker       ptr += 3;
225*dfc6aa5cSAndroid Build Coastguard Worker     }
226*dfc6aa5cSAndroid Build Coastguard Worker   }
227*dfc6aa5cSAndroid Build Coastguard Worker }
228*dfc6aa5cSAndroid Build Coastguard Worker 
229*dfc6aa5cSAndroid Build Coastguard Worker 
230*dfc6aa5cSAndroid Build Coastguard Worker /*
231*dfc6aa5cSAndroid Build Coastguard Worker  * Next we have the really interesting routines: selection of a colormap
232*dfc6aa5cSAndroid Build Coastguard Worker  * given the completed histogram.
233*dfc6aa5cSAndroid Build Coastguard Worker  * These routines work with a list of "boxes", each representing a rectangular
234*dfc6aa5cSAndroid Build Coastguard Worker  * subset of the input color space (to histogram precision).
235*dfc6aa5cSAndroid Build Coastguard Worker  */
236*dfc6aa5cSAndroid Build Coastguard Worker 
237*dfc6aa5cSAndroid Build Coastguard Worker typedef struct {
238*dfc6aa5cSAndroid Build Coastguard Worker   /* The bounds of the box (inclusive); expressed as histogram indexes */
239*dfc6aa5cSAndroid Build Coastguard Worker   int c0min, c0max;
240*dfc6aa5cSAndroid Build Coastguard Worker   int c1min, c1max;
241*dfc6aa5cSAndroid Build Coastguard Worker   int c2min, c2max;
242*dfc6aa5cSAndroid Build Coastguard Worker   /* The volume (actually 2-norm) of the box */
243*dfc6aa5cSAndroid Build Coastguard Worker   JLONG volume;
244*dfc6aa5cSAndroid Build Coastguard Worker   /* The number of nonzero histogram cells within this box */
245*dfc6aa5cSAndroid Build Coastguard Worker   long colorcount;
246*dfc6aa5cSAndroid Build Coastguard Worker } box;
247*dfc6aa5cSAndroid Build Coastguard Worker 
248*dfc6aa5cSAndroid Build Coastguard Worker typedef box *boxptr;
249*dfc6aa5cSAndroid Build Coastguard Worker 
250*dfc6aa5cSAndroid Build Coastguard Worker 
251*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boxptr)
find_biggest_color_pop(boxptr boxlist,int numboxes)252*dfc6aa5cSAndroid Build Coastguard Worker find_biggest_color_pop(boxptr boxlist, int numboxes)
253*dfc6aa5cSAndroid Build Coastguard Worker /* Find the splittable box with the largest color population */
254*dfc6aa5cSAndroid Build Coastguard Worker /* Returns NULL if no splittable boxes remain */
255*dfc6aa5cSAndroid Build Coastguard Worker {
256*dfc6aa5cSAndroid Build Coastguard Worker   register boxptr boxp;
257*dfc6aa5cSAndroid Build Coastguard Worker   register int i;
258*dfc6aa5cSAndroid Build Coastguard Worker   register long maxc = 0;
259*dfc6aa5cSAndroid Build Coastguard Worker   boxptr which = NULL;
260*dfc6aa5cSAndroid Build Coastguard Worker 
261*dfc6aa5cSAndroid Build Coastguard Worker   for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
262*dfc6aa5cSAndroid Build Coastguard Worker     if (boxp->colorcount > maxc && boxp->volume > 0) {
263*dfc6aa5cSAndroid Build Coastguard Worker       which = boxp;
264*dfc6aa5cSAndroid Build Coastguard Worker       maxc = boxp->colorcount;
265*dfc6aa5cSAndroid Build Coastguard Worker     }
266*dfc6aa5cSAndroid Build Coastguard Worker   }
267*dfc6aa5cSAndroid Build Coastguard Worker   return which;
268*dfc6aa5cSAndroid Build Coastguard Worker }
269*dfc6aa5cSAndroid Build Coastguard Worker 
270*dfc6aa5cSAndroid Build Coastguard Worker 
271*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boxptr)
find_biggest_volume(boxptr boxlist,int numboxes)272*dfc6aa5cSAndroid Build Coastguard Worker find_biggest_volume(boxptr boxlist, int numboxes)
273*dfc6aa5cSAndroid Build Coastguard Worker /* Find the splittable box with the largest (scaled) volume */
274*dfc6aa5cSAndroid Build Coastguard Worker /* Returns NULL if no splittable boxes remain */
275*dfc6aa5cSAndroid Build Coastguard Worker {
276*dfc6aa5cSAndroid Build Coastguard Worker   register boxptr boxp;
277*dfc6aa5cSAndroid Build Coastguard Worker   register int i;
278*dfc6aa5cSAndroid Build Coastguard Worker   register JLONG maxv = 0;
279*dfc6aa5cSAndroid Build Coastguard Worker   boxptr which = NULL;
280*dfc6aa5cSAndroid Build Coastguard Worker 
281*dfc6aa5cSAndroid Build Coastguard Worker   for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
282*dfc6aa5cSAndroid Build Coastguard Worker     if (boxp->volume > maxv) {
283*dfc6aa5cSAndroid Build Coastguard Worker       which = boxp;
284*dfc6aa5cSAndroid Build Coastguard Worker       maxv = boxp->volume;
285*dfc6aa5cSAndroid Build Coastguard Worker     }
286*dfc6aa5cSAndroid Build Coastguard Worker   }
287*dfc6aa5cSAndroid Build Coastguard Worker   return which;
288*dfc6aa5cSAndroid Build Coastguard Worker }
289*dfc6aa5cSAndroid Build Coastguard Worker 
290*dfc6aa5cSAndroid Build Coastguard Worker 
291*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
update_box(j_decompress_ptr cinfo,boxptr boxp)292*dfc6aa5cSAndroid Build Coastguard Worker update_box(j_decompress_ptr cinfo, boxptr boxp)
293*dfc6aa5cSAndroid Build Coastguard Worker /* Shrink the min/max bounds of a box to enclose only nonzero elements, */
294*dfc6aa5cSAndroid Build Coastguard Worker /* and recompute its volume and population */
295*dfc6aa5cSAndroid Build Coastguard Worker {
296*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
297*dfc6aa5cSAndroid Build Coastguard Worker   hist3d histogram = cquantize->histogram;
298*dfc6aa5cSAndroid Build Coastguard Worker   histptr histp;
299*dfc6aa5cSAndroid Build Coastguard Worker   int c0, c1, c2;
300*dfc6aa5cSAndroid Build Coastguard Worker   int c0min, c0max, c1min, c1max, c2min, c2max;
301*dfc6aa5cSAndroid Build Coastguard Worker   JLONG dist0, dist1, dist2;
302*dfc6aa5cSAndroid Build Coastguard Worker   long ccount;
303*dfc6aa5cSAndroid Build Coastguard Worker 
304*dfc6aa5cSAndroid Build Coastguard Worker   c0min = boxp->c0min;  c0max = boxp->c0max;
305*dfc6aa5cSAndroid Build Coastguard Worker   c1min = boxp->c1min;  c1max = boxp->c1max;
306*dfc6aa5cSAndroid Build Coastguard Worker   c2min = boxp->c2min;  c2max = boxp->c2max;
307*dfc6aa5cSAndroid Build Coastguard Worker 
308*dfc6aa5cSAndroid Build Coastguard Worker   if (c0max > c0min)
309*dfc6aa5cSAndroid Build Coastguard Worker     for (c0 = c0min; c0 <= c0max; c0++)
310*dfc6aa5cSAndroid Build Coastguard Worker       for (c1 = c1min; c1 <= c1max; c1++) {
311*dfc6aa5cSAndroid Build Coastguard Worker         histp = &histogram[c0][c1][c2min];
312*dfc6aa5cSAndroid Build Coastguard Worker         for (c2 = c2min; c2 <= c2max; c2++)
313*dfc6aa5cSAndroid Build Coastguard Worker           if (*histp++ != 0) {
314*dfc6aa5cSAndroid Build Coastguard Worker             boxp->c0min = c0min = c0;
315*dfc6aa5cSAndroid Build Coastguard Worker             goto have_c0min;
316*dfc6aa5cSAndroid Build Coastguard Worker           }
317*dfc6aa5cSAndroid Build Coastguard Worker       }
318*dfc6aa5cSAndroid Build Coastguard Worker have_c0min:
319*dfc6aa5cSAndroid Build Coastguard Worker   if (c0max > c0min)
320*dfc6aa5cSAndroid Build Coastguard Worker     for (c0 = c0max; c0 >= c0min; c0--)
321*dfc6aa5cSAndroid Build Coastguard Worker       for (c1 = c1min; c1 <= c1max; c1++) {
322*dfc6aa5cSAndroid Build Coastguard Worker         histp = &histogram[c0][c1][c2min];
323*dfc6aa5cSAndroid Build Coastguard Worker         for (c2 = c2min; c2 <= c2max; c2++)
324*dfc6aa5cSAndroid Build Coastguard Worker           if (*histp++ != 0) {
325*dfc6aa5cSAndroid Build Coastguard Worker             boxp->c0max = c0max = c0;
326*dfc6aa5cSAndroid Build Coastguard Worker             goto have_c0max;
327*dfc6aa5cSAndroid Build Coastguard Worker           }
328*dfc6aa5cSAndroid Build Coastguard Worker       }
329*dfc6aa5cSAndroid Build Coastguard Worker have_c0max:
330*dfc6aa5cSAndroid Build Coastguard Worker   if (c1max > c1min)
331*dfc6aa5cSAndroid Build Coastguard Worker     for (c1 = c1min; c1 <= c1max; c1++)
332*dfc6aa5cSAndroid Build Coastguard Worker       for (c0 = c0min; c0 <= c0max; c0++) {
333*dfc6aa5cSAndroid Build Coastguard Worker         histp = &histogram[c0][c1][c2min];
334*dfc6aa5cSAndroid Build Coastguard Worker         for (c2 = c2min; c2 <= c2max; c2++)
335*dfc6aa5cSAndroid Build Coastguard Worker           if (*histp++ != 0) {
336*dfc6aa5cSAndroid Build Coastguard Worker             boxp->c1min = c1min = c1;
337*dfc6aa5cSAndroid Build Coastguard Worker             goto have_c1min;
338*dfc6aa5cSAndroid Build Coastguard Worker           }
339*dfc6aa5cSAndroid Build Coastguard Worker       }
340*dfc6aa5cSAndroid Build Coastguard Worker have_c1min:
341*dfc6aa5cSAndroid Build Coastguard Worker   if (c1max > c1min)
342*dfc6aa5cSAndroid Build Coastguard Worker     for (c1 = c1max; c1 >= c1min; c1--)
343*dfc6aa5cSAndroid Build Coastguard Worker       for (c0 = c0min; c0 <= c0max; c0++) {
344*dfc6aa5cSAndroid Build Coastguard Worker         histp = &histogram[c0][c1][c2min];
345*dfc6aa5cSAndroid Build Coastguard Worker         for (c2 = c2min; c2 <= c2max; c2++)
346*dfc6aa5cSAndroid Build Coastguard Worker           if (*histp++ != 0) {
347*dfc6aa5cSAndroid Build Coastguard Worker             boxp->c1max = c1max = c1;
348*dfc6aa5cSAndroid Build Coastguard Worker             goto have_c1max;
349*dfc6aa5cSAndroid Build Coastguard Worker           }
350*dfc6aa5cSAndroid Build Coastguard Worker       }
351*dfc6aa5cSAndroid Build Coastguard Worker have_c1max:
352*dfc6aa5cSAndroid Build Coastguard Worker   if (c2max > c2min)
353*dfc6aa5cSAndroid Build Coastguard Worker     for (c2 = c2min; c2 <= c2max; c2++)
354*dfc6aa5cSAndroid Build Coastguard Worker       for (c0 = c0min; c0 <= c0max; c0++) {
355*dfc6aa5cSAndroid Build Coastguard Worker         histp = &histogram[c0][c1min][c2];
356*dfc6aa5cSAndroid Build Coastguard Worker         for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
357*dfc6aa5cSAndroid Build Coastguard Worker           if (*histp != 0) {
358*dfc6aa5cSAndroid Build Coastguard Worker             boxp->c2min = c2min = c2;
359*dfc6aa5cSAndroid Build Coastguard Worker             goto have_c2min;
360*dfc6aa5cSAndroid Build Coastguard Worker           }
361*dfc6aa5cSAndroid Build Coastguard Worker       }
362*dfc6aa5cSAndroid Build Coastguard Worker have_c2min:
363*dfc6aa5cSAndroid Build Coastguard Worker   if (c2max > c2min)
364*dfc6aa5cSAndroid Build Coastguard Worker     for (c2 = c2max; c2 >= c2min; c2--)
365*dfc6aa5cSAndroid Build Coastguard Worker       for (c0 = c0min; c0 <= c0max; c0++) {
366*dfc6aa5cSAndroid Build Coastguard Worker         histp = &histogram[c0][c1min][c2];
367*dfc6aa5cSAndroid Build Coastguard Worker         for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
368*dfc6aa5cSAndroid Build Coastguard Worker           if (*histp != 0) {
369*dfc6aa5cSAndroid Build Coastguard Worker             boxp->c2max = c2max = c2;
370*dfc6aa5cSAndroid Build Coastguard Worker             goto have_c2max;
371*dfc6aa5cSAndroid Build Coastguard Worker           }
372*dfc6aa5cSAndroid Build Coastguard Worker       }
373*dfc6aa5cSAndroid Build Coastguard Worker have_c2max:
374*dfc6aa5cSAndroid Build Coastguard Worker 
375*dfc6aa5cSAndroid Build Coastguard Worker   /* Update box volume.
376*dfc6aa5cSAndroid Build Coastguard Worker    * We use 2-norm rather than real volume here; this biases the method
377*dfc6aa5cSAndroid Build Coastguard Worker    * against making long narrow boxes, and it has the side benefit that
378*dfc6aa5cSAndroid Build Coastguard Worker    * a box is splittable iff norm > 0.
379*dfc6aa5cSAndroid Build Coastguard Worker    * Since the differences are expressed in histogram-cell units,
380*dfc6aa5cSAndroid Build Coastguard Worker    * we have to shift back to JSAMPLE units to get consistent distances;
381*dfc6aa5cSAndroid Build Coastguard Worker    * after which, we scale according to the selected distance scale factors.
382*dfc6aa5cSAndroid Build Coastguard Worker    */
383*dfc6aa5cSAndroid Build Coastguard Worker   dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
384*dfc6aa5cSAndroid Build Coastguard Worker   dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
385*dfc6aa5cSAndroid Build Coastguard Worker   dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
386*dfc6aa5cSAndroid Build Coastguard Worker   boxp->volume = dist0 * dist0 + dist1 * dist1 + dist2 * dist2;
387*dfc6aa5cSAndroid Build Coastguard Worker 
388*dfc6aa5cSAndroid Build Coastguard Worker   /* Now scan remaining volume of box and compute population */
389*dfc6aa5cSAndroid Build Coastguard Worker   ccount = 0;
390*dfc6aa5cSAndroid Build Coastguard Worker   for (c0 = c0min; c0 <= c0max; c0++)
391*dfc6aa5cSAndroid Build Coastguard Worker     for (c1 = c1min; c1 <= c1max; c1++) {
392*dfc6aa5cSAndroid Build Coastguard Worker       histp = &histogram[c0][c1][c2min];
393*dfc6aa5cSAndroid Build Coastguard Worker       for (c2 = c2min; c2 <= c2max; c2++, histp++)
394*dfc6aa5cSAndroid Build Coastguard Worker         if (*histp != 0) {
395*dfc6aa5cSAndroid Build Coastguard Worker           ccount++;
396*dfc6aa5cSAndroid Build Coastguard Worker         }
397*dfc6aa5cSAndroid Build Coastguard Worker     }
398*dfc6aa5cSAndroid Build Coastguard Worker   boxp->colorcount = ccount;
399*dfc6aa5cSAndroid Build Coastguard Worker }
400*dfc6aa5cSAndroid Build Coastguard Worker 
401*dfc6aa5cSAndroid Build Coastguard Worker 
402*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(int)
median_cut(j_decompress_ptr cinfo,boxptr boxlist,int numboxes,int desired_colors)403*dfc6aa5cSAndroid Build Coastguard Worker median_cut(j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
404*dfc6aa5cSAndroid Build Coastguard Worker            int desired_colors)
405*dfc6aa5cSAndroid Build Coastguard Worker /* Repeatedly select and split the largest box until we have enough boxes */
406*dfc6aa5cSAndroid Build Coastguard Worker {
407*dfc6aa5cSAndroid Build Coastguard Worker   int n, lb;
408*dfc6aa5cSAndroid Build Coastguard Worker   int c0, c1, c2, cmax;
409*dfc6aa5cSAndroid Build Coastguard Worker   register boxptr b1, b2;
410*dfc6aa5cSAndroid Build Coastguard Worker 
411*dfc6aa5cSAndroid Build Coastguard Worker   while (numboxes < desired_colors) {
412*dfc6aa5cSAndroid Build Coastguard Worker     /* Select box to split.
413*dfc6aa5cSAndroid Build Coastguard Worker      * Current algorithm: by population for first half, then by volume.
414*dfc6aa5cSAndroid Build Coastguard Worker      */
415*dfc6aa5cSAndroid Build Coastguard Worker     if (numboxes * 2 <= desired_colors) {
416*dfc6aa5cSAndroid Build Coastguard Worker       b1 = find_biggest_color_pop(boxlist, numboxes);
417*dfc6aa5cSAndroid Build Coastguard Worker     } else {
418*dfc6aa5cSAndroid Build Coastguard Worker       b1 = find_biggest_volume(boxlist, numboxes);
419*dfc6aa5cSAndroid Build Coastguard Worker     }
420*dfc6aa5cSAndroid Build Coastguard Worker     if (b1 == NULL)             /* no splittable boxes left! */
421*dfc6aa5cSAndroid Build Coastguard Worker       break;
422*dfc6aa5cSAndroid Build Coastguard Worker     b2 = &boxlist[numboxes];    /* where new box will go */
423*dfc6aa5cSAndroid Build Coastguard Worker     /* Copy the color bounds to the new box. */
424*dfc6aa5cSAndroid Build Coastguard Worker     b2->c0max = b1->c0max;  b2->c1max = b1->c1max;  b2->c2max = b1->c2max;
425*dfc6aa5cSAndroid Build Coastguard Worker     b2->c0min = b1->c0min;  b2->c1min = b1->c1min;  b2->c2min = b1->c2min;
426*dfc6aa5cSAndroid Build Coastguard Worker     /* Choose which axis to split the box on.
427*dfc6aa5cSAndroid Build Coastguard Worker      * Current algorithm: longest scaled axis.
428*dfc6aa5cSAndroid Build Coastguard Worker      * See notes in update_box about scaling distances.
429*dfc6aa5cSAndroid Build Coastguard Worker      */
430*dfc6aa5cSAndroid Build Coastguard Worker     c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE;
431*dfc6aa5cSAndroid Build Coastguard Worker     c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE;
432*dfc6aa5cSAndroid Build Coastguard Worker     c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE;
433*dfc6aa5cSAndroid Build Coastguard Worker     /* We want to break any ties in favor of green, then red, blue last.
434*dfc6aa5cSAndroid Build Coastguard Worker      * This code does the right thing for R,G,B or B,G,R color orders only.
435*dfc6aa5cSAndroid Build Coastguard Worker      */
436*dfc6aa5cSAndroid Build Coastguard Worker     if (rgb_red[cinfo->out_color_space] == 0) {
437*dfc6aa5cSAndroid Build Coastguard Worker       cmax = c1;  n = 1;
438*dfc6aa5cSAndroid Build Coastguard Worker       if (c0 > cmax) { cmax = c0;  n = 0; }
439*dfc6aa5cSAndroid Build Coastguard Worker       if (c2 > cmax) { n = 2; }
440*dfc6aa5cSAndroid Build Coastguard Worker     } else {
441*dfc6aa5cSAndroid Build Coastguard Worker       cmax = c1;  n = 1;
442*dfc6aa5cSAndroid Build Coastguard Worker       if (c2 > cmax) { cmax = c2;  n = 2; }
443*dfc6aa5cSAndroid Build Coastguard Worker       if (c0 > cmax) { n = 0; }
444*dfc6aa5cSAndroid Build Coastguard Worker     }
445*dfc6aa5cSAndroid Build Coastguard Worker     /* Choose split point along selected axis, and update box bounds.
446*dfc6aa5cSAndroid Build Coastguard Worker      * Current algorithm: split at halfway point.
447*dfc6aa5cSAndroid Build Coastguard Worker      * (Since the box has been shrunk to minimum volume,
448*dfc6aa5cSAndroid Build Coastguard Worker      * any split will produce two nonempty subboxes.)
449*dfc6aa5cSAndroid Build Coastguard Worker      * Note that lb value is max for lower box, so must be < old max.
450*dfc6aa5cSAndroid Build Coastguard Worker      */
451*dfc6aa5cSAndroid Build Coastguard Worker     switch (n) {
452*dfc6aa5cSAndroid Build Coastguard Worker     case 0:
453*dfc6aa5cSAndroid Build Coastguard Worker       lb = (b1->c0max + b1->c0min) / 2;
454*dfc6aa5cSAndroid Build Coastguard Worker       b1->c0max = lb;
455*dfc6aa5cSAndroid Build Coastguard Worker       b2->c0min = lb + 1;
456*dfc6aa5cSAndroid Build Coastguard Worker       break;
457*dfc6aa5cSAndroid Build Coastguard Worker     case 1:
458*dfc6aa5cSAndroid Build Coastguard Worker       lb = (b1->c1max + b1->c1min) / 2;
459*dfc6aa5cSAndroid Build Coastguard Worker       b1->c1max = lb;
460*dfc6aa5cSAndroid Build Coastguard Worker       b2->c1min = lb + 1;
461*dfc6aa5cSAndroid Build Coastguard Worker       break;
462*dfc6aa5cSAndroid Build Coastguard Worker     case 2:
463*dfc6aa5cSAndroid Build Coastguard Worker       lb = (b1->c2max + b1->c2min) / 2;
464*dfc6aa5cSAndroid Build Coastguard Worker       b1->c2max = lb;
465*dfc6aa5cSAndroid Build Coastguard Worker       b2->c2min = lb + 1;
466*dfc6aa5cSAndroid Build Coastguard Worker       break;
467*dfc6aa5cSAndroid Build Coastguard Worker     }
468*dfc6aa5cSAndroid Build Coastguard Worker     /* Update stats for boxes */
469*dfc6aa5cSAndroid Build Coastguard Worker     update_box(cinfo, b1);
470*dfc6aa5cSAndroid Build Coastguard Worker     update_box(cinfo, b2);
471*dfc6aa5cSAndroid Build Coastguard Worker     numboxes++;
472*dfc6aa5cSAndroid Build Coastguard Worker   }
473*dfc6aa5cSAndroid Build Coastguard Worker   return numboxes;
474*dfc6aa5cSAndroid Build Coastguard Worker }
475*dfc6aa5cSAndroid Build Coastguard Worker 
476*dfc6aa5cSAndroid Build Coastguard Worker 
477*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
compute_color(j_decompress_ptr cinfo,boxptr boxp,int icolor)478*dfc6aa5cSAndroid Build Coastguard Worker compute_color(j_decompress_ptr cinfo, boxptr boxp, int icolor)
479*dfc6aa5cSAndroid Build Coastguard Worker /* Compute representative color for a box, put it in colormap[icolor] */
480*dfc6aa5cSAndroid Build Coastguard Worker {
481*dfc6aa5cSAndroid Build Coastguard Worker   /* Current algorithm: mean weighted by pixels (not colors) */
482*dfc6aa5cSAndroid Build Coastguard Worker   /* Note it is important to get the rounding correct! */
483*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
484*dfc6aa5cSAndroid Build Coastguard Worker   hist3d histogram = cquantize->histogram;
485*dfc6aa5cSAndroid Build Coastguard Worker   histptr histp;
486*dfc6aa5cSAndroid Build Coastguard Worker   int c0, c1, c2;
487*dfc6aa5cSAndroid Build Coastguard Worker   int c0min, c0max, c1min, c1max, c2min, c2max;
488*dfc6aa5cSAndroid Build Coastguard Worker   long count;
489*dfc6aa5cSAndroid Build Coastguard Worker   long total = 0;
490*dfc6aa5cSAndroid Build Coastguard Worker   long c0total = 0;
491*dfc6aa5cSAndroid Build Coastguard Worker   long c1total = 0;
492*dfc6aa5cSAndroid Build Coastguard Worker   long c2total = 0;
493*dfc6aa5cSAndroid Build Coastguard Worker 
494*dfc6aa5cSAndroid Build Coastguard Worker   c0min = boxp->c0min;  c0max = boxp->c0max;
495*dfc6aa5cSAndroid Build Coastguard Worker   c1min = boxp->c1min;  c1max = boxp->c1max;
496*dfc6aa5cSAndroid Build Coastguard Worker   c2min = boxp->c2min;  c2max = boxp->c2max;
497*dfc6aa5cSAndroid Build Coastguard Worker 
498*dfc6aa5cSAndroid Build Coastguard Worker   for (c0 = c0min; c0 <= c0max; c0++)
499*dfc6aa5cSAndroid Build Coastguard Worker     for (c1 = c1min; c1 <= c1max; c1++) {
500*dfc6aa5cSAndroid Build Coastguard Worker       histp = &histogram[c0][c1][c2min];
501*dfc6aa5cSAndroid Build Coastguard Worker       for (c2 = c2min; c2 <= c2max; c2++) {
502*dfc6aa5cSAndroid Build Coastguard Worker         if ((count = *histp++) != 0) {
503*dfc6aa5cSAndroid Build Coastguard Worker           total += count;
504*dfc6aa5cSAndroid Build Coastguard Worker           c0total += ((c0 << C0_SHIFT) + ((1 << C0_SHIFT) >> 1)) * count;
505*dfc6aa5cSAndroid Build Coastguard Worker           c1total += ((c1 << C1_SHIFT) + ((1 << C1_SHIFT) >> 1)) * count;
506*dfc6aa5cSAndroid Build Coastguard Worker           c2total += ((c2 << C2_SHIFT) + ((1 << C2_SHIFT) >> 1)) * count;
507*dfc6aa5cSAndroid Build Coastguard Worker         }
508*dfc6aa5cSAndroid Build Coastguard Worker       }
509*dfc6aa5cSAndroid Build Coastguard Worker     }
510*dfc6aa5cSAndroid Build Coastguard Worker 
511*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->colormap[0][icolor] = (JSAMPLE)((c0total + (total >> 1)) / total);
512*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->colormap[1][icolor] = (JSAMPLE)((c1total + (total >> 1)) / total);
513*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->colormap[2][icolor] = (JSAMPLE)((c2total + (total >> 1)) / total);
514*dfc6aa5cSAndroid Build Coastguard Worker }
515*dfc6aa5cSAndroid Build Coastguard Worker 
516*dfc6aa5cSAndroid Build Coastguard Worker 
517*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
select_colors(j_decompress_ptr cinfo,int desired_colors)518*dfc6aa5cSAndroid Build Coastguard Worker select_colors(j_decompress_ptr cinfo, int desired_colors)
519*dfc6aa5cSAndroid Build Coastguard Worker /* Master routine for color selection */
520*dfc6aa5cSAndroid Build Coastguard Worker {
521*dfc6aa5cSAndroid Build Coastguard Worker   boxptr boxlist;
522*dfc6aa5cSAndroid Build Coastguard Worker   int numboxes;
523*dfc6aa5cSAndroid Build Coastguard Worker   int i;
524*dfc6aa5cSAndroid Build Coastguard Worker 
525*dfc6aa5cSAndroid Build Coastguard Worker   /* Allocate workspace for box list */
526*dfc6aa5cSAndroid Build Coastguard Worker   boxlist = (boxptr)(*cinfo->mem->alloc_small)
527*dfc6aa5cSAndroid Build Coastguard Worker     ((j_common_ptr)cinfo, JPOOL_IMAGE, desired_colors * sizeof(box));
528*dfc6aa5cSAndroid Build Coastguard Worker   /* Initialize one box containing whole space */
529*dfc6aa5cSAndroid Build Coastguard Worker   numboxes = 1;
530*dfc6aa5cSAndroid Build Coastguard Worker   boxlist[0].c0min = 0;
531*dfc6aa5cSAndroid Build Coastguard Worker   boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT;
532*dfc6aa5cSAndroid Build Coastguard Worker   boxlist[0].c1min = 0;
533*dfc6aa5cSAndroid Build Coastguard Worker   boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT;
534*dfc6aa5cSAndroid Build Coastguard Worker   boxlist[0].c2min = 0;
535*dfc6aa5cSAndroid Build Coastguard Worker   boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT;
536*dfc6aa5cSAndroid Build Coastguard Worker   /* Shrink it to actually-used volume and set its statistics */
537*dfc6aa5cSAndroid Build Coastguard Worker   update_box(cinfo, &boxlist[0]);
538*dfc6aa5cSAndroid Build Coastguard Worker   /* Perform median-cut to produce final box list */
539*dfc6aa5cSAndroid Build Coastguard Worker   numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
540*dfc6aa5cSAndroid Build Coastguard Worker   /* Compute the representative color for each box, fill colormap */
541*dfc6aa5cSAndroid Build Coastguard Worker   for (i = 0; i < numboxes; i++)
542*dfc6aa5cSAndroid Build Coastguard Worker     compute_color(cinfo, &boxlist[i], i);
543*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->actual_number_of_colors = numboxes;
544*dfc6aa5cSAndroid Build Coastguard Worker   TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes);
545*dfc6aa5cSAndroid Build Coastguard Worker }
546*dfc6aa5cSAndroid Build Coastguard Worker 
547*dfc6aa5cSAndroid Build Coastguard Worker 
548*dfc6aa5cSAndroid Build Coastguard Worker /*
549*dfc6aa5cSAndroid Build Coastguard Worker  * These routines are concerned with the time-critical task of mapping input
550*dfc6aa5cSAndroid Build Coastguard Worker  * colors to the nearest color in the selected colormap.
551*dfc6aa5cSAndroid Build Coastguard Worker  *
552*dfc6aa5cSAndroid Build Coastguard Worker  * We re-use the histogram space as an "inverse color map", essentially a
553*dfc6aa5cSAndroid Build Coastguard Worker  * cache for the results of nearest-color searches.  All colors within a
554*dfc6aa5cSAndroid Build Coastguard Worker  * histogram cell will be mapped to the same colormap entry, namely the one
555*dfc6aa5cSAndroid Build Coastguard Worker  * closest to the cell's center.  This may not be quite the closest entry to
556*dfc6aa5cSAndroid Build Coastguard Worker  * the actual input color, but it's almost as good.  A zero in the cache
557*dfc6aa5cSAndroid Build Coastguard Worker  * indicates we haven't found the nearest color for that cell yet; the array
558*dfc6aa5cSAndroid Build Coastguard Worker  * is cleared to zeroes before starting the mapping pass.  When we find the
559*dfc6aa5cSAndroid Build Coastguard Worker  * nearest color for a cell, its colormap index plus one is recorded in the
560*dfc6aa5cSAndroid Build Coastguard Worker  * cache for future use.  The pass2 scanning routines call fill_inverse_cmap
561*dfc6aa5cSAndroid Build Coastguard Worker  * when they need to use an unfilled entry in the cache.
562*dfc6aa5cSAndroid Build Coastguard Worker  *
563*dfc6aa5cSAndroid Build Coastguard Worker  * Our method of efficiently finding nearest colors is based on the "locally
564*dfc6aa5cSAndroid Build Coastguard Worker  * sorted search" idea described by Heckbert and on the incremental distance
565*dfc6aa5cSAndroid Build Coastguard Worker  * calculation described by Spencer W. Thomas in chapter III.1 of Graphics
566*dfc6aa5cSAndroid Build Coastguard Worker  * Gems II (James Arvo, ed.  Academic Press, 1991).  Thomas points out that
567*dfc6aa5cSAndroid Build Coastguard Worker  * the distances from a given colormap entry to each cell of the histogram can
568*dfc6aa5cSAndroid Build Coastguard Worker  * be computed quickly using an incremental method: the differences between
569*dfc6aa5cSAndroid Build Coastguard Worker  * distances to adjacent cells themselves differ by a constant.  This allows a
570*dfc6aa5cSAndroid Build Coastguard Worker  * fairly fast implementation of the "brute force" approach of computing the
571*dfc6aa5cSAndroid Build Coastguard Worker  * distance from every colormap entry to every histogram cell.  Unfortunately,
572*dfc6aa5cSAndroid Build Coastguard Worker  * it needs a work array to hold the best-distance-so-far for each histogram
573*dfc6aa5cSAndroid Build Coastguard Worker  * cell (because the inner loop has to be over cells, not colormap entries).
574*dfc6aa5cSAndroid Build Coastguard Worker  * The work array elements have to be JLONGs, so the work array would need
575*dfc6aa5cSAndroid Build Coastguard Worker  * 256Kb at our recommended precision.  This is not feasible in DOS machines.
576*dfc6aa5cSAndroid Build Coastguard Worker  *
577*dfc6aa5cSAndroid Build Coastguard Worker  * To get around these problems, we apply Thomas' method to compute the
578*dfc6aa5cSAndroid Build Coastguard Worker  * nearest colors for only the cells within a small subbox of the histogram.
579*dfc6aa5cSAndroid Build Coastguard Worker  * The work array need be only as big as the subbox, so the memory usage
580*dfc6aa5cSAndroid Build Coastguard Worker  * problem is solved.  Furthermore, we need not fill subboxes that are never
581*dfc6aa5cSAndroid Build Coastguard Worker  * referenced in pass2; many images use only part of the color gamut, so a
582*dfc6aa5cSAndroid Build Coastguard Worker  * fair amount of work is saved.  An additional advantage of this
583*dfc6aa5cSAndroid Build Coastguard Worker  * approach is that we can apply Heckbert's locality criterion to quickly
584*dfc6aa5cSAndroid Build Coastguard Worker  * eliminate colormap entries that are far away from the subbox; typically
585*dfc6aa5cSAndroid Build Coastguard Worker  * three-fourths of the colormap entries are rejected by Heckbert's criterion,
586*dfc6aa5cSAndroid Build Coastguard Worker  * and we need not compute their distances to individual cells in the subbox.
587*dfc6aa5cSAndroid Build Coastguard Worker  * The speed of this approach is heavily influenced by the subbox size: too
588*dfc6aa5cSAndroid Build Coastguard Worker  * small means too much overhead, too big loses because Heckbert's criterion
589*dfc6aa5cSAndroid Build Coastguard Worker  * can't eliminate as many colormap entries.  Empirically the best subbox
590*dfc6aa5cSAndroid Build Coastguard Worker  * size seems to be about 1/512th of the histogram (1/8th in each direction).
591*dfc6aa5cSAndroid Build Coastguard Worker  *
592*dfc6aa5cSAndroid Build Coastguard Worker  * Thomas' article also describes a refined method which is asymptotically
593*dfc6aa5cSAndroid Build Coastguard Worker  * faster than the brute-force method, but it is also far more complex and
594*dfc6aa5cSAndroid Build Coastguard Worker  * cannot efficiently be applied to small subboxes.  It is therefore not
595*dfc6aa5cSAndroid Build Coastguard Worker  * useful for programs intended to be portable to DOS machines.  On machines
596*dfc6aa5cSAndroid Build Coastguard Worker  * with plenty of memory, filling the whole histogram in one shot with Thomas'
597*dfc6aa5cSAndroid Build Coastguard Worker  * refined method might be faster than the present code --- but then again,
598*dfc6aa5cSAndroid Build Coastguard Worker  * it might not be any faster, and it's certainly more complicated.
599*dfc6aa5cSAndroid Build Coastguard Worker  */
600*dfc6aa5cSAndroid Build Coastguard Worker 
601*dfc6aa5cSAndroid Build Coastguard Worker 
602*dfc6aa5cSAndroid Build Coastguard Worker /* log2(histogram cells in update box) for each axis; this can be adjusted */
603*dfc6aa5cSAndroid Build Coastguard Worker #define BOX_C0_LOG  (HIST_C0_BITS - 3)
604*dfc6aa5cSAndroid Build Coastguard Worker #define BOX_C1_LOG  (HIST_C1_BITS - 3)
605*dfc6aa5cSAndroid Build Coastguard Worker #define BOX_C2_LOG  (HIST_C2_BITS - 3)
606*dfc6aa5cSAndroid Build Coastguard Worker 
607*dfc6aa5cSAndroid Build Coastguard Worker #define BOX_C0_ELEMS  (1 << BOX_C0_LOG) /* # of hist cells in update box */
608*dfc6aa5cSAndroid Build Coastguard Worker #define BOX_C1_ELEMS  (1 << BOX_C1_LOG)
609*dfc6aa5cSAndroid Build Coastguard Worker #define BOX_C2_ELEMS  (1 << BOX_C2_LOG)
610*dfc6aa5cSAndroid Build Coastguard Worker 
611*dfc6aa5cSAndroid Build Coastguard Worker #define BOX_C0_SHIFT  (C0_SHIFT + BOX_C0_LOG)
612*dfc6aa5cSAndroid Build Coastguard Worker #define BOX_C1_SHIFT  (C1_SHIFT + BOX_C1_LOG)
613*dfc6aa5cSAndroid Build Coastguard Worker #define BOX_C2_SHIFT  (C2_SHIFT + BOX_C2_LOG)
614*dfc6aa5cSAndroid Build Coastguard Worker 
615*dfc6aa5cSAndroid Build Coastguard Worker 
616*dfc6aa5cSAndroid Build Coastguard Worker /*
617*dfc6aa5cSAndroid Build Coastguard Worker  * The next three routines implement inverse colormap filling.  They could
618*dfc6aa5cSAndroid Build Coastguard Worker  * all be folded into one big routine, but splitting them up this way saves
619*dfc6aa5cSAndroid Build Coastguard Worker  * some stack space (the mindist[] and bestdist[] arrays need not coexist)
620*dfc6aa5cSAndroid Build Coastguard Worker  * and may allow some compilers to produce better code by registerizing more
621*dfc6aa5cSAndroid Build Coastguard Worker  * inner-loop variables.
622*dfc6aa5cSAndroid Build Coastguard Worker  */
623*dfc6aa5cSAndroid Build Coastguard Worker 
624*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(int)
find_nearby_colors(j_decompress_ptr cinfo,int minc0,int minc1,int minc2,JSAMPLE colorlist[])625*dfc6aa5cSAndroid Build Coastguard Worker find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
626*dfc6aa5cSAndroid Build Coastguard Worker                    JSAMPLE colorlist[])
627*dfc6aa5cSAndroid Build Coastguard Worker /* Locate the colormap entries close enough to an update box to be candidates
628*dfc6aa5cSAndroid Build Coastguard Worker  * for the nearest entry to some cell(s) in the update box.  The update box
629*dfc6aa5cSAndroid Build Coastguard Worker  * is specified by the center coordinates of its first cell.  The number of
630*dfc6aa5cSAndroid Build Coastguard Worker  * candidate colormap entries is returned, and their colormap indexes are
631*dfc6aa5cSAndroid Build Coastguard Worker  * placed in colorlist[].
632*dfc6aa5cSAndroid Build Coastguard Worker  * This routine uses Heckbert's "locally sorted search" criterion to select
633*dfc6aa5cSAndroid Build Coastguard Worker  * the colors that need further consideration.
634*dfc6aa5cSAndroid Build Coastguard Worker  */
635*dfc6aa5cSAndroid Build Coastguard Worker {
636*dfc6aa5cSAndroid Build Coastguard Worker   int numcolors = cinfo->actual_number_of_colors;
637*dfc6aa5cSAndroid Build Coastguard Worker   int maxc0, maxc1, maxc2;
638*dfc6aa5cSAndroid Build Coastguard Worker   int centerc0, centerc1, centerc2;
639*dfc6aa5cSAndroid Build Coastguard Worker   int i, x, ncolors;
640*dfc6aa5cSAndroid Build Coastguard Worker   JLONG minmaxdist, min_dist, max_dist, tdist;
641*dfc6aa5cSAndroid Build Coastguard Worker   JLONG mindist[MAXNUMCOLORS];  /* min distance to colormap entry i */
642*dfc6aa5cSAndroid Build Coastguard Worker 
643*dfc6aa5cSAndroid Build Coastguard Worker   /* Compute true coordinates of update box's upper corner and center.
644*dfc6aa5cSAndroid Build Coastguard Worker    * Actually we compute the coordinates of the center of the upper-corner
645*dfc6aa5cSAndroid Build Coastguard Worker    * histogram cell, which are the upper bounds of the volume we care about.
646*dfc6aa5cSAndroid Build Coastguard Worker    * Note that since ">>" rounds down, the "center" values may be closer to
647*dfc6aa5cSAndroid Build Coastguard Worker    * min than to max; hence comparisons to them must be "<=", not "<".
648*dfc6aa5cSAndroid Build Coastguard Worker    */
649*dfc6aa5cSAndroid Build Coastguard Worker   maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));
650*dfc6aa5cSAndroid Build Coastguard Worker   centerc0 = (minc0 + maxc0) >> 1;
651*dfc6aa5cSAndroid Build Coastguard Worker   maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));
652*dfc6aa5cSAndroid Build Coastguard Worker   centerc1 = (minc1 + maxc1) >> 1;
653*dfc6aa5cSAndroid Build Coastguard Worker   maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));
654*dfc6aa5cSAndroid Build Coastguard Worker   centerc2 = (minc2 + maxc2) >> 1;
655*dfc6aa5cSAndroid Build Coastguard Worker 
656*dfc6aa5cSAndroid Build Coastguard Worker   /* For each color in colormap, find:
657*dfc6aa5cSAndroid Build Coastguard Worker    *  1. its minimum squared-distance to any point in the update box
658*dfc6aa5cSAndroid Build Coastguard Worker    *     (zero if color is within update box);
659*dfc6aa5cSAndroid Build Coastguard Worker    *  2. its maximum squared-distance to any point in the update box.
660*dfc6aa5cSAndroid Build Coastguard Worker    * Both of these can be found by considering only the corners of the box.
661*dfc6aa5cSAndroid Build Coastguard Worker    * We save the minimum distance for each color in mindist[];
662*dfc6aa5cSAndroid Build Coastguard Worker    * only the smallest maximum distance is of interest.
663*dfc6aa5cSAndroid Build Coastguard Worker    */
664*dfc6aa5cSAndroid Build Coastguard Worker   minmaxdist = 0x7FFFFFFFL;
665*dfc6aa5cSAndroid Build Coastguard Worker 
666*dfc6aa5cSAndroid Build Coastguard Worker   for (i = 0; i < numcolors; i++) {
667*dfc6aa5cSAndroid Build Coastguard Worker     /* We compute the squared-c0-distance term, then add in the other two. */
668*dfc6aa5cSAndroid Build Coastguard Worker     x = cinfo->colormap[0][i];
669*dfc6aa5cSAndroid Build Coastguard Worker     if (x < minc0) {
670*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - minc0) * C0_SCALE;
671*dfc6aa5cSAndroid Build Coastguard Worker       min_dist = tdist * tdist;
672*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - maxc0) * C0_SCALE;
673*dfc6aa5cSAndroid Build Coastguard Worker       max_dist = tdist * tdist;
674*dfc6aa5cSAndroid Build Coastguard Worker     } else if (x > maxc0) {
675*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - maxc0) * C0_SCALE;
676*dfc6aa5cSAndroid Build Coastguard Worker       min_dist = tdist * tdist;
677*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - minc0) * C0_SCALE;
678*dfc6aa5cSAndroid Build Coastguard Worker       max_dist = tdist * tdist;
679*dfc6aa5cSAndroid Build Coastguard Worker     } else {
680*dfc6aa5cSAndroid Build Coastguard Worker       /* within cell range so no contribution to min_dist */
681*dfc6aa5cSAndroid Build Coastguard Worker       min_dist = 0;
682*dfc6aa5cSAndroid Build Coastguard Worker       if (x <= centerc0) {
683*dfc6aa5cSAndroid Build Coastguard Worker         tdist = (x - maxc0) * C0_SCALE;
684*dfc6aa5cSAndroid Build Coastguard Worker         max_dist = tdist * tdist;
685*dfc6aa5cSAndroid Build Coastguard Worker       } else {
686*dfc6aa5cSAndroid Build Coastguard Worker         tdist = (x - minc0) * C0_SCALE;
687*dfc6aa5cSAndroid Build Coastguard Worker         max_dist = tdist * tdist;
688*dfc6aa5cSAndroid Build Coastguard Worker       }
689*dfc6aa5cSAndroid Build Coastguard Worker     }
690*dfc6aa5cSAndroid Build Coastguard Worker 
691*dfc6aa5cSAndroid Build Coastguard Worker     x = cinfo->colormap[1][i];
692*dfc6aa5cSAndroid Build Coastguard Worker     if (x < minc1) {
693*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - minc1) * C1_SCALE;
694*dfc6aa5cSAndroid Build Coastguard Worker       min_dist += tdist * tdist;
695*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - maxc1) * C1_SCALE;
696*dfc6aa5cSAndroid Build Coastguard Worker       max_dist += tdist * tdist;
697*dfc6aa5cSAndroid Build Coastguard Worker     } else if (x > maxc1) {
698*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - maxc1) * C1_SCALE;
699*dfc6aa5cSAndroid Build Coastguard Worker       min_dist += tdist * tdist;
700*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - minc1) * C1_SCALE;
701*dfc6aa5cSAndroid Build Coastguard Worker       max_dist += tdist * tdist;
702*dfc6aa5cSAndroid Build Coastguard Worker     } else {
703*dfc6aa5cSAndroid Build Coastguard Worker       /* within cell range so no contribution to min_dist */
704*dfc6aa5cSAndroid Build Coastguard Worker       if (x <= centerc1) {
705*dfc6aa5cSAndroid Build Coastguard Worker         tdist = (x - maxc1) * C1_SCALE;
706*dfc6aa5cSAndroid Build Coastguard Worker         max_dist += tdist * tdist;
707*dfc6aa5cSAndroid Build Coastguard Worker       } else {
708*dfc6aa5cSAndroid Build Coastguard Worker         tdist = (x - minc1) * C1_SCALE;
709*dfc6aa5cSAndroid Build Coastguard Worker         max_dist += tdist * tdist;
710*dfc6aa5cSAndroid Build Coastguard Worker       }
711*dfc6aa5cSAndroid Build Coastguard Worker     }
712*dfc6aa5cSAndroid Build Coastguard Worker 
713*dfc6aa5cSAndroid Build Coastguard Worker     x = cinfo->colormap[2][i];
714*dfc6aa5cSAndroid Build Coastguard Worker     if (x < minc2) {
715*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - minc2) * C2_SCALE;
716*dfc6aa5cSAndroid Build Coastguard Worker       min_dist += tdist * tdist;
717*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - maxc2) * C2_SCALE;
718*dfc6aa5cSAndroid Build Coastguard Worker       max_dist += tdist * tdist;
719*dfc6aa5cSAndroid Build Coastguard Worker     } else if (x > maxc2) {
720*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - maxc2) * C2_SCALE;
721*dfc6aa5cSAndroid Build Coastguard Worker       min_dist += tdist * tdist;
722*dfc6aa5cSAndroid Build Coastguard Worker       tdist = (x - minc2) * C2_SCALE;
723*dfc6aa5cSAndroid Build Coastguard Worker       max_dist += tdist * tdist;
724*dfc6aa5cSAndroid Build Coastguard Worker     } else {
725*dfc6aa5cSAndroid Build Coastguard Worker       /* within cell range so no contribution to min_dist */
726*dfc6aa5cSAndroid Build Coastguard Worker       if (x <= centerc2) {
727*dfc6aa5cSAndroid Build Coastguard Worker         tdist = (x - maxc2) * C2_SCALE;
728*dfc6aa5cSAndroid Build Coastguard Worker         max_dist += tdist * tdist;
729*dfc6aa5cSAndroid Build Coastguard Worker       } else {
730*dfc6aa5cSAndroid Build Coastguard Worker         tdist = (x - minc2) * C2_SCALE;
731*dfc6aa5cSAndroid Build Coastguard Worker         max_dist += tdist * tdist;
732*dfc6aa5cSAndroid Build Coastguard Worker       }
733*dfc6aa5cSAndroid Build Coastguard Worker     }
734*dfc6aa5cSAndroid Build Coastguard Worker 
735*dfc6aa5cSAndroid Build Coastguard Worker     mindist[i] = min_dist;      /* save away the results */
736*dfc6aa5cSAndroid Build Coastguard Worker     if (max_dist < minmaxdist)
737*dfc6aa5cSAndroid Build Coastguard Worker       minmaxdist = max_dist;
738*dfc6aa5cSAndroid Build Coastguard Worker   }
739*dfc6aa5cSAndroid Build Coastguard Worker 
740*dfc6aa5cSAndroid Build Coastguard Worker   /* Now we know that no cell in the update box is more than minmaxdist
741*dfc6aa5cSAndroid Build Coastguard Worker    * away from some colormap entry.  Therefore, only colors that are
742*dfc6aa5cSAndroid Build Coastguard Worker    * within minmaxdist of some part of the box need be considered.
743*dfc6aa5cSAndroid Build Coastguard Worker    */
744*dfc6aa5cSAndroid Build Coastguard Worker   ncolors = 0;
745*dfc6aa5cSAndroid Build Coastguard Worker   for (i = 0; i < numcolors; i++) {
746*dfc6aa5cSAndroid Build Coastguard Worker     if (mindist[i] <= minmaxdist)
747*dfc6aa5cSAndroid Build Coastguard Worker       colorlist[ncolors++] = (JSAMPLE)i;
748*dfc6aa5cSAndroid Build Coastguard Worker   }
749*dfc6aa5cSAndroid Build Coastguard Worker   return ncolors;
750*dfc6aa5cSAndroid Build Coastguard Worker }
751*dfc6aa5cSAndroid Build Coastguard Worker 
752*dfc6aa5cSAndroid Build Coastguard Worker 
753*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
find_best_colors(j_decompress_ptr cinfo,int minc0,int minc1,int minc2,int numcolors,JSAMPLE colorlist[],JSAMPLE bestcolor[])754*dfc6aa5cSAndroid Build Coastguard Worker find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
755*dfc6aa5cSAndroid Build Coastguard Worker                  int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
756*dfc6aa5cSAndroid Build Coastguard Worker /* Find the closest colormap entry for each cell in the update box,
757*dfc6aa5cSAndroid Build Coastguard Worker  * given the list of candidate colors prepared by find_nearby_colors.
758*dfc6aa5cSAndroid Build Coastguard Worker  * Return the indexes of the closest entries in the bestcolor[] array.
759*dfc6aa5cSAndroid Build Coastguard Worker  * This routine uses Thomas' incremental distance calculation method to
760*dfc6aa5cSAndroid Build Coastguard Worker  * find the distance from a colormap entry to successive cells in the box.
761*dfc6aa5cSAndroid Build Coastguard Worker  */
762*dfc6aa5cSAndroid Build Coastguard Worker {
763*dfc6aa5cSAndroid Build Coastguard Worker   int ic0, ic1, ic2;
764*dfc6aa5cSAndroid Build Coastguard Worker   int i, icolor;
765*dfc6aa5cSAndroid Build Coastguard Worker   register JLONG *bptr;         /* pointer into bestdist[] array */
766*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPLE *cptr;                /* pointer into bestcolor[] array */
767*dfc6aa5cSAndroid Build Coastguard Worker   JLONG dist0, dist1;           /* initial distance values */
768*dfc6aa5cSAndroid Build Coastguard Worker   register JLONG dist2;         /* current distance in inner loop */
769*dfc6aa5cSAndroid Build Coastguard Worker   JLONG xx0, xx1;               /* distance increments */
770*dfc6aa5cSAndroid Build Coastguard Worker   register JLONG xx2;
771*dfc6aa5cSAndroid Build Coastguard Worker   JLONG inc0, inc1, inc2;       /* initial values for increments */
772*dfc6aa5cSAndroid Build Coastguard Worker   /* This array holds the distance to the nearest-so-far color for each cell */
773*dfc6aa5cSAndroid Build Coastguard Worker   JLONG bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
774*dfc6aa5cSAndroid Build Coastguard Worker 
775*dfc6aa5cSAndroid Build Coastguard Worker   /* Initialize best-distance for each cell of the update box */
776*dfc6aa5cSAndroid Build Coastguard Worker   bptr = bestdist;
777*dfc6aa5cSAndroid Build Coastguard Worker   for (i = BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS - 1; i >= 0; i--)
778*dfc6aa5cSAndroid Build Coastguard Worker     *bptr++ = 0x7FFFFFFFL;
779*dfc6aa5cSAndroid Build Coastguard Worker 
780*dfc6aa5cSAndroid Build Coastguard Worker   /* For each color selected by find_nearby_colors,
781*dfc6aa5cSAndroid Build Coastguard Worker    * compute its distance to the center of each cell in the box.
782*dfc6aa5cSAndroid Build Coastguard Worker    * If that's less than best-so-far, update best distance and color number.
783*dfc6aa5cSAndroid Build Coastguard Worker    */
784*dfc6aa5cSAndroid Build Coastguard Worker 
785*dfc6aa5cSAndroid Build Coastguard Worker   /* Nominal steps between cell centers ("x" in Thomas article) */
786*dfc6aa5cSAndroid Build Coastguard Worker #define STEP_C0  ((1 << C0_SHIFT) * C0_SCALE)
787*dfc6aa5cSAndroid Build Coastguard Worker #define STEP_C1  ((1 << C1_SHIFT) * C1_SCALE)
788*dfc6aa5cSAndroid Build Coastguard Worker #define STEP_C2  ((1 << C2_SHIFT) * C2_SCALE)
789*dfc6aa5cSAndroid Build Coastguard Worker 
790*dfc6aa5cSAndroid Build Coastguard Worker   for (i = 0; i < numcolors; i++) {
791*dfc6aa5cSAndroid Build Coastguard Worker     icolor = colorlist[i];
792*dfc6aa5cSAndroid Build Coastguard Worker     /* Compute (square of) distance from minc0/c1/c2 to this color */
793*dfc6aa5cSAndroid Build Coastguard Worker     inc0 = (minc0 - cinfo->colormap[0][icolor]) * C0_SCALE;
794*dfc6aa5cSAndroid Build Coastguard Worker     dist0 = inc0 * inc0;
795*dfc6aa5cSAndroid Build Coastguard Worker     inc1 = (minc1 - cinfo->colormap[1][icolor]) * C1_SCALE;
796*dfc6aa5cSAndroid Build Coastguard Worker     dist0 += inc1 * inc1;
797*dfc6aa5cSAndroid Build Coastguard Worker     inc2 = (minc2 - cinfo->colormap[2][icolor]) * C2_SCALE;
798*dfc6aa5cSAndroid Build Coastguard Worker     dist0 += inc2 * inc2;
799*dfc6aa5cSAndroid Build Coastguard Worker     /* Form the initial difference increments */
800*dfc6aa5cSAndroid Build Coastguard Worker     inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
801*dfc6aa5cSAndroid Build Coastguard Worker     inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
802*dfc6aa5cSAndroid Build Coastguard Worker     inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;
803*dfc6aa5cSAndroid Build Coastguard Worker     /* Now loop over all cells in box, updating distance per Thomas method */
804*dfc6aa5cSAndroid Build Coastguard Worker     bptr = bestdist;
805*dfc6aa5cSAndroid Build Coastguard Worker     cptr = bestcolor;
806*dfc6aa5cSAndroid Build Coastguard Worker     xx0 = inc0;
807*dfc6aa5cSAndroid Build Coastguard Worker     for (ic0 = BOX_C0_ELEMS - 1; ic0 >= 0; ic0--) {
808*dfc6aa5cSAndroid Build Coastguard Worker       dist1 = dist0;
809*dfc6aa5cSAndroid Build Coastguard Worker       xx1 = inc1;
810*dfc6aa5cSAndroid Build Coastguard Worker       for (ic1 = BOX_C1_ELEMS - 1; ic1 >= 0; ic1--) {
811*dfc6aa5cSAndroid Build Coastguard Worker         dist2 = dist1;
812*dfc6aa5cSAndroid Build Coastguard Worker         xx2 = inc2;
813*dfc6aa5cSAndroid Build Coastguard Worker         for (ic2 = BOX_C2_ELEMS - 1; ic2 >= 0; ic2--) {
814*dfc6aa5cSAndroid Build Coastguard Worker           if (dist2 < *bptr) {
815*dfc6aa5cSAndroid Build Coastguard Worker             *bptr = dist2;
816*dfc6aa5cSAndroid Build Coastguard Worker             *cptr = (JSAMPLE)icolor;
817*dfc6aa5cSAndroid Build Coastguard Worker           }
818*dfc6aa5cSAndroid Build Coastguard Worker           dist2 += xx2;
819*dfc6aa5cSAndroid Build Coastguard Worker           xx2 += 2 * STEP_C2 * STEP_C2;
820*dfc6aa5cSAndroid Build Coastguard Worker           bptr++;
821*dfc6aa5cSAndroid Build Coastguard Worker           cptr++;
822*dfc6aa5cSAndroid Build Coastguard Worker         }
823*dfc6aa5cSAndroid Build Coastguard Worker         dist1 += xx1;
824*dfc6aa5cSAndroid Build Coastguard Worker         xx1 += 2 * STEP_C1 * STEP_C1;
825*dfc6aa5cSAndroid Build Coastguard Worker       }
826*dfc6aa5cSAndroid Build Coastguard Worker       dist0 += xx0;
827*dfc6aa5cSAndroid Build Coastguard Worker       xx0 += 2 * STEP_C0 * STEP_C0;
828*dfc6aa5cSAndroid Build Coastguard Worker     }
829*dfc6aa5cSAndroid Build Coastguard Worker   }
830*dfc6aa5cSAndroid Build Coastguard Worker }
831*dfc6aa5cSAndroid Build Coastguard Worker 
832*dfc6aa5cSAndroid Build Coastguard Worker 
833*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
fill_inverse_cmap(j_decompress_ptr cinfo,int c0,int c1,int c2)834*dfc6aa5cSAndroid Build Coastguard Worker fill_inverse_cmap(j_decompress_ptr cinfo, int c0, int c1, int c2)
835*dfc6aa5cSAndroid Build Coastguard Worker /* Fill the inverse-colormap entries in the update box that contains */
836*dfc6aa5cSAndroid Build Coastguard Worker /* histogram cell c0/c1/c2.  (Only that one cell MUST be filled, but */
837*dfc6aa5cSAndroid Build Coastguard Worker /* we can fill as many others as we wish.) */
838*dfc6aa5cSAndroid Build Coastguard Worker {
839*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
840*dfc6aa5cSAndroid Build Coastguard Worker   hist3d histogram = cquantize->histogram;
841*dfc6aa5cSAndroid Build Coastguard Worker   int minc0, minc1, minc2;      /* lower left corner of update box */
842*dfc6aa5cSAndroid Build Coastguard Worker   int ic0, ic1, ic2;
843*dfc6aa5cSAndroid Build Coastguard Worker   register JSAMPLE *cptr;       /* pointer into bestcolor[] array */
844*dfc6aa5cSAndroid Build Coastguard Worker   register histptr cachep;      /* pointer into main cache array */
845*dfc6aa5cSAndroid Build Coastguard Worker   /* This array lists the candidate colormap indexes. */
846*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPLE colorlist[MAXNUMCOLORS];
847*dfc6aa5cSAndroid Build Coastguard Worker   int numcolors;                /* number of candidate colors */
848*dfc6aa5cSAndroid Build Coastguard Worker   /* This array holds the actually closest colormap index for each cell. */
849*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
850*dfc6aa5cSAndroid Build Coastguard Worker 
851*dfc6aa5cSAndroid Build Coastguard Worker   /* Convert cell coordinates to update box ID */
852*dfc6aa5cSAndroid Build Coastguard Worker   c0 >>= BOX_C0_LOG;
853*dfc6aa5cSAndroid Build Coastguard Worker   c1 >>= BOX_C1_LOG;
854*dfc6aa5cSAndroid Build Coastguard Worker   c2 >>= BOX_C2_LOG;
855*dfc6aa5cSAndroid Build Coastguard Worker 
856*dfc6aa5cSAndroid Build Coastguard Worker   /* Compute true coordinates of update box's origin corner.
857*dfc6aa5cSAndroid Build Coastguard Worker    * Actually we compute the coordinates of the center of the corner
858*dfc6aa5cSAndroid Build Coastguard Worker    * histogram cell, which are the lower bounds of the volume we care about.
859*dfc6aa5cSAndroid Build Coastguard Worker    */
860*dfc6aa5cSAndroid Build Coastguard Worker   minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
861*dfc6aa5cSAndroid Build Coastguard Worker   minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
862*dfc6aa5cSAndroid Build Coastguard Worker   minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
863*dfc6aa5cSAndroid Build Coastguard Worker 
864*dfc6aa5cSAndroid Build Coastguard Worker   /* Determine which colormap entries are close enough to be candidates
865*dfc6aa5cSAndroid Build Coastguard Worker    * for the nearest entry to some cell in the update box.
866*dfc6aa5cSAndroid Build Coastguard Worker    */
867*dfc6aa5cSAndroid Build Coastguard Worker   numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist);
868*dfc6aa5cSAndroid Build Coastguard Worker 
869*dfc6aa5cSAndroid Build Coastguard Worker   /* Determine the actually nearest colors. */
870*dfc6aa5cSAndroid Build Coastguard Worker   find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist,
871*dfc6aa5cSAndroid Build Coastguard Worker                    bestcolor);
872*dfc6aa5cSAndroid Build Coastguard Worker 
873*dfc6aa5cSAndroid Build Coastguard Worker   /* Save the best color numbers (plus 1) in the main cache array */
874*dfc6aa5cSAndroid Build Coastguard Worker   c0 <<= BOX_C0_LOG;            /* convert ID back to base cell indexes */
875*dfc6aa5cSAndroid Build Coastguard Worker   c1 <<= BOX_C1_LOG;
876*dfc6aa5cSAndroid Build Coastguard Worker   c2 <<= BOX_C2_LOG;
877*dfc6aa5cSAndroid Build Coastguard Worker   cptr = bestcolor;
878*dfc6aa5cSAndroid Build Coastguard Worker   for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
879*dfc6aa5cSAndroid Build Coastguard Worker     for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
880*dfc6aa5cSAndroid Build Coastguard Worker       cachep = &histogram[c0 + ic0][c1 + ic1][c2];
881*dfc6aa5cSAndroid Build Coastguard Worker       for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
882*dfc6aa5cSAndroid Build Coastguard Worker         *cachep++ = (histcell)((*cptr++) + 1);
883*dfc6aa5cSAndroid Build Coastguard Worker       }
884*dfc6aa5cSAndroid Build Coastguard Worker     }
885*dfc6aa5cSAndroid Build Coastguard Worker   }
886*dfc6aa5cSAndroid Build Coastguard Worker }
887*dfc6aa5cSAndroid Build Coastguard Worker 
888*dfc6aa5cSAndroid Build Coastguard Worker 
889*dfc6aa5cSAndroid Build Coastguard Worker /*
890*dfc6aa5cSAndroid Build Coastguard Worker  * Map some rows of pixels to the output colormapped representation.
891*dfc6aa5cSAndroid Build Coastguard Worker  */
892*dfc6aa5cSAndroid Build Coastguard Worker 
893*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
pass2_no_dither(j_decompress_ptr cinfo,JSAMPARRAY input_buf,JSAMPARRAY output_buf,int num_rows)894*dfc6aa5cSAndroid Build Coastguard Worker pass2_no_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
895*dfc6aa5cSAndroid Build Coastguard Worker                 JSAMPARRAY output_buf, int num_rows)
896*dfc6aa5cSAndroid Build Coastguard Worker /* This version performs no dithering */
897*dfc6aa5cSAndroid Build Coastguard Worker {
898*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
899*dfc6aa5cSAndroid Build Coastguard Worker   hist3d histogram = cquantize->histogram;
900*dfc6aa5cSAndroid Build Coastguard Worker   register JSAMPROW inptr, outptr;
901*dfc6aa5cSAndroid Build Coastguard Worker   register histptr cachep;
902*dfc6aa5cSAndroid Build Coastguard Worker   register int c0, c1, c2;
903*dfc6aa5cSAndroid Build Coastguard Worker   int row;
904*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION col;
905*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION width = cinfo->output_width;
906*dfc6aa5cSAndroid Build Coastguard Worker 
907*dfc6aa5cSAndroid Build Coastguard Worker   for (row = 0; row < num_rows; row++) {
908*dfc6aa5cSAndroid Build Coastguard Worker     inptr = input_buf[row];
909*dfc6aa5cSAndroid Build Coastguard Worker     outptr = output_buf[row];
910*dfc6aa5cSAndroid Build Coastguard Worker     for (col = width; col > 0; col--) {
911*dfc6aa5cSAndroid Build Coastguard Worker       /* get pixel value and index into the cache */
912*dfc6aa5cSAndroid Build Coastguard Worker       c0 = (*inptr++) >> C0_SHIFT;
913*dfc6aa5cSAndroid Build Coastguard Worker       c1 = (*inptr++) >> C1_SHIFT;
914*dfc6aa5cSAndroid Build Coastguard Worker       c2 = (*inptr++) >> C2_SHIFT;
915*dfc6aa5cSAndroid Build Coastguard Worker       cachep = &histogram[c0][c1][c2];
916*dfc6aa5cSAndroid Build Coastguard Worker       /* If we have not seen this color before, find nearest colormap entry */
917*dfc6aa5cSAndroid Build Coastguard Worker       /* and update the cache */
918*dfc6aa5cSAndroid Build Coastguard Worker       if (*cachep == 0)
919*dfc6aa5cSAndroid Build Coastguard Worker         fill_inverse_cmap(cinfo, c0, c1, c2);
920*dfc6aa5cSAndroid Build Coastguard Worker       /* Now emit the colormap index for this cell */
921*dfc6aa5cSAndroid Build Coastguard Worker       *outptr++ = (JSAMPLE)(*cachep - 1);
922*dfc6aa5cSAndroid Build Coastguard Worker     }
923*dfc6aa5cSAndroid Build Coastguard Worker   }
924*dfc6aa5cSAndroid Build Coastguard Worker }
925*dfc6aa5cSAndroid Build Coastguard Worker 
926*dfc6aa5cSAndroid Build Coastguard Worker 
927*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
pass2_fs_dither(j_decompress_ptr cinfo,JSAMPARRAY input_buf,JSAMPARRAY output_buf,int num_rows)928*dfc6aa5cSAndroid Build Coastguard Worker pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
929*dfc6aa5cSAndroid Build Coastguard Worker                 JSAMPARRAY output_buf, int num_rows)
930*dfc6aa5cSAndroid Build Coastguard Worker /* This version performs Floyd-Steinberg dithering */
931*dfc6aa5cSAndroid Build Coastguard Worker {
932*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
933*dfc6aa5cSAndroid Build Coastguard Worker   hist3d histogram = cquantize->histogram;
934*dfc6aa5cSAndroid Build Coastguard Worker   register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */
935*dfc6aa5cSAndroid Build Coastguard Worker   LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */
936*dfc6aa5cSAndroid Build Coastguard Worker   LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */
937*dfc6aa5cSAndroid Build Coastguard Worker   register FSERRPTR errorptr;   /* => fserrors[] at column before current */
938*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPROW inptr;               /* => current input pixel */
939*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPROW outptr;              /* => current output pixel */
940*dfc6aa5cSAndroid Build Coastguard Worker   histptr cachep;
941*dfc6aa5cSAndroid Build Coastguard Worker   int dir;                      /* +1 or -1 depending on direction */
942*dfc6aa5cSAndroid Build Coastguard Worker   int dir3;                     /* 3*dir, for advancing inptr & errorptr */
943*dfc6aa5cSAndroid Build Coastguard Worker   int row;
944*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION col;
945*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION width = cinfo->output_width;
946*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPLE *range_limit = cinfo->sample_range_limit;
947*dfc6aa5cSAndroid Build Coastguard Worker   int *error_limit = cquantize->error_limiter;
948*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPROW colormap0 = cinfo->colormap[0];
949*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPROW colormap1 = cinfo->colormap[1];
950*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPROW colormap2 = cinfo->colormap[2];
951*dfc6aa5cSAndroid Build Coastguard Worker   SHIFT_TEMPS
952*dfc6aa5cSAndroid Build Coastguard Worker 
953*dfc6aa5cSAndroid Build Coastguard Worker   for (row = 0; row < num_rows; row++) {
954*dfc6aa5cSAndroid Build Coastguard Worker     inptr = input_buf[row];
955*dfc6aa5cSAndroid Build Coastguard Worker     outptr = output_buf[row];
956*dfc6aa5cSAndroid Build Coastguard Worker     if (cquantize->on_odd_row) {
957*dfc6aa5cSAndroid Build Coastguard Worker       /* work right to left in this row */
958*dfc6aa5cSAndroid Build Coastguard Worker       inptr += (width - 1) * 3; /* so point to rightmost pixel */
959*dfc6aa5cSAndroid Build Coastguard Worker       outptr += width - 1;
960*dfc6aa5cSAndroid Build Coastguard Worker       dir = -1;
961*dfc6aa5cSAndroid Build Coastguard Worker       dir3 = -3;
962*dfc6aa5cSAndroid Build Coastguard Worker       errorptr = cquantize->fserrors + (width + 1) * 3; /* => entry after last column */
963*dfc6aa5cSAndroid Build Coastguard Worker       cquantize->on_odd_row = FALSE; /* flip for next time */
964*dfc6aa5cSAndroid Build Coastguard Worker     } else {
965*dfc6aa5cSAndroid Build Coastguard Worker       /* work left to right in this row */
966*dfc6aa5cSAndroid Build Coastguard Worker       dir = 1;
967*dfc6aa5cSAndroid Build Coastguard Worker       dir3 = 3;
968*dfc6aa5cSAndroid Build Coastguard Worker       errorptr = cquantize->fserrors; /* => entry before first real column */
969*dfc6aa5cSAndroid Build Coastguard Worker       cquantize->on_odd_row = TRUE; /* flip for next time */
970*dfc6aa5cSAndroid Build Coastguard Worker     }
971*dfc6aa5cSAndroid Build Coastguard Worker     /* Preset error values: no error propagated to first pixel from left */
972*dfc6aa5cSAndroid Build Coastguard Worker     cur0 = cur1 = cur2 = 0;
973*dfc6aa5cSAndroid Build Coastguard Worker     /* and no error propagated to row below yet */
974*dfc6aa5cSAndroid Build Coastguard Worker     belowerr0 = belowerr1 = belowerr2 = 0;
975*dfc6aa5cSAndroid Build Coastguard Worker     bpreverr0 = bpreverr1 = bpreverr2 = 0;
976*dfc6aa5cSAndroid Build Coastguard Worker 
977*dfc6aa5cSAndroid Build Coastguard Worker     for (col = width; col > 0; col--) {
978*dfc6aa5cSAndroid Build Coastguard Worker       /* curN holds the error propagated from the previous pixel on the
979*dfc6aa5cSAndroid Build Coastguard Worker        * current line.  Add the error propagated from the previous line
980*dfc6aa5cSAndroid Build Coastguard Worker        * to form the complete error correction term for this pixel, and
981*dfc6aa5cSAndroid Build Coastguard Worker        * round the error term (which is expressed * 16) to an integer.
982*dfc6aa5cSAndroid Build Coastguard Worker        * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
983*dfc6aa5cSAndroid Build Coastguard Worker        * for either sign of the error value.
984*dfc6aa5cSAndroid Build Coastguard Worker        * Note: errorptr points to *previous* column's array entry.
985*dfc6aa5cSAndroid Build Coastguard Worker        */
986*dfc6aa5cSAndroid Build Coastguard Worker       cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3 + 0] + 8, 4);
987*dfc6aa5cSAndroid Build Coastguard Worker       cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3 + 1] + 8, 4);
988*dfc6aa5cSAndroid Build Coastguard Worker       cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3 + 2] + 8, 4);
989*dfc6aa5cSAndroid Build Coastguard Worker       /* Limit the error using transfer function set by init_error_limit.
990*dfc6aa5cSAndroid Build Coastguard Worker        * See comments with init_error_limit for rationale.
991*dfc6aa5cSAndroid Build Coastguard Worker        */
992*dfc6aa5cSAndroid Build Coastguard Worker       cur0 = error_limit[cur0];
993*dfc6aa5cSAndroid Build Coastguard Worker       cur1 = error_limit[cur1];
994*dfc6aa5cSAndroid Build Coastguard Worker       cur2 = error_limit[cur2];
995*dfc6aa5cSAndroid Build Coastguard Worker       /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
996*dfc6aa5cSAndroid Build Coastguard Worker        * The maximum error is +- MAXJSAMPLE (or less with error limiting);
997*dfc6aa5cSAndroid Build Coastguard Worker        * this sets the required size of the range_limit array.
998*dfc6aa5cSAndroid Build Coastguard Worker        */
999*dfc6aa5cSAndroid Build Coastguard Worker       cur0 += inptr[0];
1000*dfc6aa5cSAndroid Build Coastguard Worker       cur1 += inptr[1];
1001*dfc6aa5cSAndroid Build Coastguard Worker       cur2 += inptr[2];
1002*dfc6aa5cSAndroid Build Coastguard Worker       cur0 = range_limit[cur0];
1003*dfc6aa5cSAndroid Build Coastguard Worker       cur1 = range_limit[cur1];
1004*dfc6aa5cSAndroid Build Coastguard Worker       cur2 = range_limit[cur2];
1005*dfc6aa5cSAndroid Build Coastguard Worker       /* Index into the cache with adjusted pixel value */
1006*dfc6aa5cSAndroid Build Coastguard Worker       cachep =
1007*dfc6aa5cSAndroid Build Coastguard Worker         &histogram[cur0 >> C0_SHIFT][cur1 >> C1_SHIFT][cur2 >> C2_SHIFT];
1008*dfc6aa5cSAndroid Build Coastguard Worker       /* If we have not seen this color before, find nearest colormap */
1009*dfc6aa5cSAndroid Build Coastguard Worker       /* entry and update the cache */
1010*dfc6aa5cSAndroid Build Coastguard Worker       if (*cachep == 0)
1011*dfc6aa5cSAndroid Build Coastguard Worker         fill_inverse_cmap(cinfo, cur0 >> C0_SHIFT, cur1 >> C1_SHIFT,
1012*dfc6aa5cSAndroid Build Coastguard Worker                           cur2 >> C2_SHIFT);
1013*dfc6aa5cSAndroid Build Coastguard Worker       /* Now emit the colormap index for this cell */
1014*dfc6aa5cSAndroid Build Coastguard Worker       {
1015*dfc6aa5cSAndroid Build Coastguard Worker         register int pixcode = *cachep - 1;
1016*dfc6aa5cSAndroid Build Coastguard Worker         *outptr = (JSAMPLE)pixcode;
1017*dfc6aa5cSAndroid Build Coastguard Worker         /* Compute representation error for this pixel */
1018*dfc6aa5cSAndroid Build Coastguard Worker         cur0 -= colormap0[pixcode];
1019*dfc6aa5cSAndroid Build Coastguard Worker         cur1 -= colormap1[pixcode];
1020*dfc6aa5cSAndroid Build Coastguard Worker         cur2 -= colormap2[pixcode];
1021*dfc6aa5cSAndroid Build Coastguard Worker       }
1022*dfc6aa5cSAndroid Build Coastguard Worker       /* Compute error fractions to be propagated to adjacent pixels.
1023*dfc6aa5cSAndroid Build Coastguard Worker        * Add these into the running sums, and simultaneously shift the
1024*dfc6aa5cSAndroid Build Coastguard Worker        * next-line error sums left by 1 column.
1025*dfc6aa5cSAndroid Build Coastguard Worker        */
1026*dfc6aa5cSAndroid Build Coastguard Worker       {
1027*dfc6aa5cSAndroid Build Coastguard Worker         register LOCFSERROR bnexterr;
1028*dfc6aa5cSAndroid Build Coastguard Worker 
1029*dfc6aa5cSAndroid Build Coastguard Worker         bnexterr = cur0;        /* Process component 0 */
1030*dfc6aa5cSAndroid Build Coastguard Worker         errorptr[0] = (FSERROR)(bpreverr0 + cur0 * 3);
1031*dfc6aa5cSAndroid Build Coastguard Worker         bpreverr0 = belowerr0 + cur0 * 5;
1032*dfc6aa5cSAndroid Build Coastguard Worker         belowerr0 = bnexterr;
1033*dfc6aa5cSAndroid Build Coastguard Worker         cur0 *= 7;
1034*dfc6aa5cSAndroid Build Coastguard Worker         bnexterr = cur1;        /* Process component 1 */
1035*dfc6aa5cSAndroid Build Coastguard Worker         errorptr[1] = (FSERROR)(bpreverr1 + cur1 * 3);
1036*dfc6aa5cSAndroid Build Coastguard Worker         bpreverr1 = belowerr1 + cur1 * 5;
1037*dfc6aa5cSAndroid Build Coastguard Worker         belowerr1 = bnexterr;
1038*dfc6aa5cSAndroid Build Coastguard Worker         cur1 *= 7;
1039*dfc6aa5cSAndroid Build Coastguard Worker         bnexterr = cur2;        /* Process component 2 */
1040*dfc6aa5cSAndroid Build Coastguard Worker         errorptr[2] = (FSERROR)(bpreverr2 + cur2 * 3);
1041*dfc6aa5cSAndroid Build Coastguard Worker         bpreverr2 = belowerr2 + cur2 * 5;
1042*dfc6aa5cSAndroid Build Coastguard Worker         belowerr2 = bnexterr;
1043*dfc6aa5cSAndroid Build Coastguard Worker         cur2 *= 7;
1044*dfc6aa5cSAndroid Build Coastguard Worker       }
1045*dfc6aa5cSAndroid Build Coastguard Worker       /* At this point curN contains the 7/16 error value to be propagated
1046*dfc6aa5cSAndroid Build Coastguard Worker        * to the next pixel on the current line, and all the errors for the
1047*dfc6aa5cSAndroid Build Coastguard Worker        * next line have been shifted over.  We are therefore ready to move on.
1048*dfc6aa5cSAndroid Build Coastguard Worker        */
1049*dfc6aa5cSAndroid Build Coastguard Worker       inptr += dir3;            /* Advance pixel pointers to next column */
1050*dfc6aa5cSAndroid Build Coastguard Worker       outptr += dir;
1051*dfc6aa5cSAndroid Build Coastguard Worker       errorptr += dir3;         /* advance errorptr to current column */
1052*dfc6aa5cSAndroid Build Coastguard Worker     }
1053*dfc6aa5cSAndroid Build Coastguard Worker     /* Post-loop cleanup: we must unload the final error values into the
1054*dfc6aa5cSAndroid Build Coastguard Worker      * final fserrors[] entry.  Note we need not unload belowerrN because
1055*dfc6aa5cSAndroid Build Coastguard Worker      * it is for the dummy column before or after the actual array.
1056*dfc6aa5cSAndroid Build Coastguard Worker      */
1057*dfc6aa5cSAndroid Build Coastguard Worker     errorptr[0] = (FSERROR)bpreverr0; /* unload prev errs into array */
1058*dfc6aa5cSAndroid Build Coastguard Worker     errorptr[1] = (FSERROR)bpreverr1;
1059*dfc6aa5cSAndroid Build Coastguard Worker     errorptr[2] = (FSERROR)bpreverr2;
1060*dfc6aa5cSAndroid Build Coastguard Worker   }
1061*dfc6aa5cSAndroid Build Coastguard Worker }
1062*dfc6aa5cSAndroid Build Coastguard Worker 
1063*dfc6aa5cSAndroid Build Coastguard Worker 
1064*dfc6aa5cSAndroid Build Coastguard Worker /*
1065*dfc6aa5cSAndroid Build Coastguard Worker  * Initialize the error-limiting transfer function (lookup table).
1066*dfc6aa5cSAndroid Build Coastguard Worker  * The raw F-S error computation can potentially compute error values of up to
1067*dfc6aa5cSAndroid Build Coastguard Worker  * +- MAXJSAMPLE.  But we want the maximum correction applied to a pixel to be
1068*dfc6aa5cSAndroid Build Coastguard Worker  * much less, otherwise obviously wrong pixels will be created.  (Typical
1069*dfc6aa5cSAndroid Build Coastguard Worker  * effects include weird fringes at color-area boundaries, isolated bright
1070*dfc6aa5cSAndroid Build Coastguard Worker  * pixels in a dark area, etc.)  The standard advice for avoiding this problem
1071*dfc6aa5cSAndroid Build Coastguard Worker  * is to ensure that the "corners" of the color cube are allocated as output
1072*dfc6aa5cSAndroid Build Coastguard Worker  * colors; then repeated errors in the same direction cannot cause cascading
1073*dfc6aa5cSAndroid Build Coastguard Worker  * error buildup.  However, that only prevents the error from getting
1074*dfc6aa5cSAndroid Build Coastguard Worker  * completely out of hand; Aaron Giles reports that error limiting improves
1075*dfc6aa5cSAndroid Build Coastguard Worker  * the results even with corner colors allocated.
1076*dfc6aa5cSAndroid Build Coastguard Worker  * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty
1077*dfc6aa5cSAndroid Build Coastguard Worker  * well, but the smoother transfer function used below is even better.  Thanks
1078*dfc6aa5cSAndroid Build Coastguard Worker  * to Aaron Giles for this idea.
1079*dfc6aa5cSAndroid Build Coastguard Worker  */
1080*dfc6aa5cSAndroid Build Coastguard Worker 
1081*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
init_error_limit(j_decompress_ptr cinfo)1082*dfc6aa5cSAndroid Build Coastguard Worker init_error_limit(j_decompress_ptr cinfo)
1083*dfc6aa5cSAndroid Build Coastguard Worker /* Allocate and fill in the error_limiter table */
1084*dfc6aa5cSAndroid Build Coastguard Worker {
1085*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
1086*dfc6aa5cSAndroid Build Coastguard Worker   int *table;
1087*dfc6aa5cSAndroid Build Coastguard Worker   int in, out;
1088*dfc6aa5cSAndroid Build Coastguard Worker 
1089*dfc6aa5cSAndroid Build Coastguard Worker   table = (int *)(*cinfo->mem->alloc_small)
1090*dfc6aa5cSAndroid Build Coastguard Worker     ((j_common_ptr)cinfo, JPOOL_IMAGE, (MAXJSAMPLE * 2 + 1) * sizeof(int));
1091*dfc6aa5cSAndroid Build Coastguard Worker   table += MAXJSAMPLE;          /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */
1092*dfc6aa5cSAndroid Build Coastguard Worker   cquantize->error_limiter = table;
1093*dfc6aa5cSAndroid Build Coastguard Worker 
1094*dfc6aa5cSAndroid Build Coastguard Worker #define STEPSIZE  ((MAXJSAMPLE + 1) / 16)
1095*dfc6aa5cSAndroid Build Coastguard Worker   /* Map errors 1:1 up to +- MAXJSAMPLE/16 */
1096*dfc6aa5cSAndroid Build Coastguard Worker   out = 0;
1097*dfc6aa5cSAndroid Build Coastguard Worker   for (in = 0; in < STEPSIZE; in++, out++) {
1098*dfc6aa5cSAndroid Build Coastguard Worker     table[in] = out;  table[-in] = -out;
1099*dfc6aa5cSAndroid Build Coastguard Worker   }
1100*dfc6aa5cSAndroid Build Coastguard Worker   /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */
1101*dfc6aa5cSAndroid Build Coastguard Worker   for (; in < STEPSIZE * 3; in++, out += (in & 1) ? 0 : 1) {
1102*dfc6aa5cSAndroid Build Coastguard Worker     table[in] = out;  table[-in] = -out;
1103*dfc6aa5cSAndroid Build Coastguard Worker   }
1104*dfc6aa5cSAndroid Build Coastguard Worker   /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */
1105*dfc6aa5cSAndroid Build Coastguard Worker   for (; in <= MAXJSAMPLE; in++) {
1106*dfc6aa5cSAndroid Build Coastguard Worker     table[in] = out;  table[-in] = -out;
1107*dfc6aa5cSAndroid Build Coastguard Worker   }
1108*dfc6aa5cSAndroid Build Coastguard Worker #undef STEPSIZE
1109*dfc6aa5cSAndroid Build Coastguard Worker }
1110*dfc6aa5cSAndroid Build Coastguard Worker 
1111*dfc6aa5cSAndroid Build Coastguard Worker 
1112*dfc6aa5cSAndroid Build Coastguard Worker /*
1113*dfc6aa5cSAndroid Build Coastguard Worker  * Finish up at the end of each pass.
1114*dfc6aa5cSAndroid Build Coastguard Worker  */
1115*dfc6aa5cSAndroid Build Coastguard Worker 
1116*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
finish_pass1(j_decompress_ptr cinfo)1117*dfc6aa5cSAndroid Build Coastguard Worker finish_pass1(j_decompress_ptr cinfo)
1118*dfc6aa5cSAndroid Build Coastguard Worker {
1119*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
1120*dfc6aa5cSAndroid Build Coastguard Worker 
1121*dfc6aa5cSAndroid Build Coastguard Worker   /* Select the representative colors and fill in cinfo->colormap */
1122*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->colormap = cquantize->sv_colormap;
1123*dfc6aa5cSAndroid Build Coastguard Worker   select_colors(cinfo, cquantize->desired);
1124*dfc6aa5cSAndroid Build Coastguard Worker   /* Force next pass to zero the color index table */
1125*dfc6aa5cSAndroid Build Coastguard Worker   cquantize->needs_zeroed = TRUE;
1126*dfc6aa5cSAndroid Build Coastguard Worker }
1127*dfc6aa5cSAndroid Build Coastguard Worker 
1128*dfc6aa5cSAndroid Build Coastguard Worker 
1129*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
finish_pass2(j_decompress_ptr cinfo)1130*dfc6aa5cSAndroid Build Coastguard Worker finish_pass2(j_decompress_ptr cinfo)
1131*dfc6aa5cSAndroid Build Coastguard Worker {
1132*dfc6aa5cSAndroid Build Coastguard Worker   /* no work */
1133*dfc6aa5cSAndroid Build Coastguard Worker }
1134*dfc6aa5cSAndroid Build Coastguard Worker 
1135*dfc6aa5cSAndroid Build Coastguard Worker 
1136*dfc6aa5cSAndroid Build Coastguard Worker /*
1137*dfc6aa5cSAndroid Build Coastguard Worker  * Initialize for each processing pass.
1138*dfc6aa5cSAndroid Build Coastguard Worker  */
1139*dfc6aa5cSAndroid Build Coastguard Worker 
1140*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
start_pass_2_quant(j_decompress_ptr cinfo,boolean is_pre_scan)1141*dfc6aa5cSAndroid Build Coastguard Worker start_pass_2_quant(j_decompress_ptr cinfo, boolean is_pre_scan)
1142*dfc6aa5cSAndroid Build Coastguard Worker {
1143*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
1144*dfc6aa5cSAndroid Build Coastguard Worker   hist3d histogram = cquantize->histogram;
1145*dfc6aa5cSAndroid Build Coastguard Worker   int i;
1146*dfc6aa5cSAndroid Build Coastguard Worker 
1147*dfc6aa5cSAndroid Build Coastguard Worker   /* Only F-S dithering or no dithering is supported. */
1148*dfc6aa5cSAndroid Build Coastguard Worker   /* If user asks for ordered dither, give them F-S. */
1149*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->dither_mode != JDITHER_NONE)
1150*dfc6aa5cSAndroid Build Coastguard Worker     cinfo->dither_mode = JDITHER_FS;
1151*dfc6aa5cSAndroid Build Coastguard Worker 
1152*dfc6aa5cSAndroid Build Coastguard Worker   if (is_pre_scan) {
1153*dfc6aa5cSAndroid Build Coastguard Worker     /* Set up method pointers */
1154*dfc6aa5cSAndroid Build Coastguard Worker     cquantize->pub.color_quantize = prescan_quantize;
1155*dfc6aa5cSAndroid Build Coastguard Worker     cquantize->pub.finish_pass = finish_pass1;
1156*dfc6aa5cSAndroid Build Coastguard Worker     cquantize->needs_zeroed = TRUE; /* Always zero histogram */
1157*dfc6aa5cSAndroid Build Coastguard Worker   } else {
1158*dfc6aa5cSAndroid Build Coastguard Worker     /* Set up method pointers */
1159*dfc6aa5cSAndroid Build Coastguard Worker     if (cinfo->dither_mode == JDITHER_FS)
1160*dfc6aa5cSAndroid Build Coastguard Worker       cquantize->pub.color_quantize = pass2_fs_dither;
1161*dfc6aa5cSAndroid Build Coastguard Worker     else
1162*dfc6aa5cSAndroid Build Coastguard Worker       cquantize->pub.color_quantize = pass2_no_dither;
1163*dfc6aa5cSAndroid Build Coastguard Worker     cquantize->pub.finish_pass = finish_pass2;
1164*dfc6aa5cSAndroid Build Coastguard Worker 
1165*dfc6aa5cSAndroid Build Coastguard Worker     /* Make sure color count is acceptable */
1166*dfc6aa5cSAndroid Build Coastguard Worker     i = cinfo->actual_number_of_colors;
1167*dfc6aa5cSAndroid Build Coastguard Worker     if (i < 1)
1168*dfc6aa5cSAndroid Build Coastguard Worker       ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1);
1169*dfc6aa5cSAndroid Build Coastguard Worker     if (i > MAXNUMCOLORS)
1170*dfc6aa5cSAndroid Build Coastguard Worker       ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
1171*dfc6aa5cSAndroid Build Coastguard Worker 
1172*dfc6aa5cSAndroid Build Coastguard Worker     if (cinfo->dither_mode == JDITHER_FS) {
1173*dfc6aa5cSAndroid Build Coastguard Worker       size_t arraysize =
1174*dfc6aa5cSAndroid Build Coastguard Worker         (size_t)((cinfo->output_width + 2) * (3 * sizeof(FSERROR)));
1175*dfc6aa5cSAndroid Build Coastguard Worker       /* Allocate Floyd-Steinberg workspace if we didn't already. */
1176*dfc6aa5cSAndroid Build Coastguard Worker       if (cquantize->fserrors == NULL)
1177*dfc6aa5cSAndroid Build Coastguard Worker         cquantize->fserrors = (FSERRPTR)(*cinfo->mem->alloc_large)
1178*dfc6aa5cSAndroid Build Coastguard Worker           ((j_common_ptr)cinfo, JPOOL_IMAGE, arraysize);
1179*dfc6aa5cSAndroid Build Coastguard Worker       /* Initialize the propagated errors to zero. */
1180*dfc6aa5cSAndroid Build Coastguard Worker       jzero_far((void *)cquantize->fserrors, arraysize);
1181*dfc6aa5cSAndroid Build Coastguard Worker       /* Make the error-limit table if we didn't already. */
1182*dfc6aa5cSAndroid Build Coastguard Worker       if (cquantize->error_limiter == NULL)
1183*dfc6aa5cSAndroid Build Coastguard Worker         init_error_limit(cinfo);
1184*dfc6aa5cSAndroid Build Coastguard Worker       cquantize->on_odd_row = FALSE;
1185*dfc6aa5cSAndroid Build Coastguard Worker     }
1186*dfc6aa5cSAndroid Build Coastguard Worker 
1187*dfc6aa5cSAndroid Build Coastguard Worker   }
1188*dfc6aa5cSAndroid Build Coastguard Worker   /* Zero the histogram or inverse color map, if necessary */
1189*dfc6aa5cSAndroid Build Coastguard Worker   if (cquantize->needs_zeroed) {
1190*dfc6aa5cSAndroid Build Coastguard Worker     for (i = 0; i < HIST_C0_ELEMS; i++) {
1191*dfc6aa5cSAndroid Build Coastguard Worker       jzero_far((void *)histogram[i],
1192*dfc6aa5cSAndroid Build Coastguard Worker                 HIST_C1_ELEMS * HIST_C2_ELEMS * sizeof(histcell));
1193*dfc6aa5cSAndroid Build Coastguard Worker     }
1194*dfc6aa5cSAndroid Build Coastguard Worker     cquantize->needs_zeroed = FALSE;
1195*dfc6aa5cSAndroid Build Coastguard Worker   }
1196*dfc6aa5cSAndroid Build Coastguard Worker }
1197*dfc6aa5cSAndroid Build Coastguard Worker 
1198*dfc6aa5cSAndroid Build Coastguard Worker 
1199*dfc6aa5cSAndroid Build Coastguard Worker /*
1200*dfc6aa5cSAndroid Build Coastguard Worker  * Switch to a new external colormap between output passes.
1201*dfc6aa5cSAndroid Build Coastguard Worker  */
1202*dfc6aa5cSAndroid Build Coastguard Worker 
1203*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
new_color_map_2_quant(j_decompress_ptr cinfo)1204*dfc6aa5cSAndroid Build Coastguard Worker new_color_map_2_quant(j_decompress_ptr cinfo)
1205*dfc6aa5cSAndroid Build Coastguard Worker {
1206*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
1207*dfc6aa5cSAndroid Build Coastguard Worker 
1208*dfc6aa5cSAndroid Build Coastguard Worker   /* Reset the inverse color map */
1209*dfc6aa5cSAndroid Build Coastguard Worker   cquantize->needs_zeroed = TRUE;
1210*dfc6aa5cSAndroid Build Coastguard Worker }
1211*dfc6aa5cSAndroid Build Coastguard Worker 
1212*dfc6aa5cSAndroid Build Coastguard Worker 
1213*dfc6aa5cSAndroid Build Coastguard Worker /*
1214*dfc6aa5cSAndroid Build Coastguard Worker  * Module initialization routine for 2-pass color quantization.
1215*dfc6aa5cSAndroid Build Coastguard Worker  */
1216*dfc6aa5cSAndroid Build Coastguard Worker 
1217*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(void)
jinit_2pass_quantizer(j_decompress_ptr cinfo)1218*dfc6aa5cSAndroid Build Coastguard Worker jinit_2pass_quantizer(j_decompress_ptr cinfo)
1219*dfc6aa5cSAndroid Build Coastguard Worker {
1220*dfc6aa5cSAndroid Build Coastguard Worker   my_cquantize_ptr cquantize;
1221*dfc6aa5cSAndroid Build Coastguard Worker   int i;
1222*dfc6aa5cSAndroid Build Coastguard Worker 
1223*dfc6aa5cSAndroid Build Coastguard Worker   cquantize = (my_cquantize_ptr)
1224*dfc6aa5cSAndroid Build Coastguard Worker     (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
1225*dfc6aa5cSAndroid Build Coastguard Worker                                 sizeof(my_cquantizer));
1226*dfc6aa5cSAndroid Build Coastguard Worker   cinfo->cquantize = (struct jpeg_color_quantizer *)cquantize;
1227*dfc6aa5cSAndroid Build Coastguard Worker   cquantize->pub.start_pass = start_pass_2_quant;
1228*dfc6aa5cSAndroid Build Coastguard Worker   cquantize->pub.new_color_map = new_color_map_2_quant;
1229*dfc6aa5cSAndroid Build Coastguard Worker   cquantize->fserrors = NULL;   /* flag optional arrays not allocated */
1230*dfc6aa5cSAndroid Build Coastguard Worker   cquantize->error_limiter = NULL;
1231*dfc6aa5cSAndroid Build Coastguard Worker 
1232*dfc6aa5cSAndroid Build Coastguard Worker   /* Make sure jdmaster didn't give me a case I can't handle */
1233*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->out_color_components != 3)
1234*dfc6aa5cSAndroid Build Coastguard Worker     ERREXIT(cinfo, JERR_NOTIMPL);
1235*dfc6aa5cSAndroid Build Coastguard Worker 
1236*dfc6aa5cSAndroid Build Coastguard Worker   /* Allocate the histogram/inverse colormap storage */
1237*dfc6aa5cSAndroid Build Coastguard Worker   cquantize->histogram = (hist3d)(*cinfo->mem->alloc_small)
1238*dfc6aa5cSAndroid Build Coastguard Worker     ((j_common_ptr)cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * sizeof(hist2d));
1239*dfc6aa5cSAndroid Build Coastguard Worker   for (i = 0; i < HIST_C0_ELEMS; i++) {
1240*dfc6aa5cSAndroid Build Coastguard Worker     cquantize->histogram[i] = (hist2d)(*cinfo->mem->alloc_large)
1241*dfc6aa5cSAndroid Build Coastguard Worker       ((j_common_ptr)cinfo, JPOOL_IMAGE,
1242*dfc6aa5cSAndroid Build Coastguard Worker        HIST_C1_ELEMS * HIST_C2_ELEMS * sizeof(histcell));
1243*dfc6aa5cSAndroid Build Coastguard Worker   }
1244*dfc6aa5cSAndroid Build Coastguard Worker   cquantize->needs_zeroed = TRUE; /* histogram is garbage now */
1245*dfc6aa5cSAndroid Build Coastguard Worker 
1246*dfc6aa5cSAndroid Build Coastguard Worker   /* Allocate storage for the completed colormap, if required.
1247*dfc6aa5cSAndroid Build Coastguard Worker    * We do this now since it may affect the memory manager's space
1248*dfc6aa5cSAndroid Build Coastguard Worker    * calculations.
1249*dfc6aa5cSAndroid Build Coastguard Worker    */
1250*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->enable_2pass_quant) {
1251*dfc6aa5cSAndroid Build Coastguard Worker     /* Make sure color count is acceptable */
1252*dfc6aa5cSAndroid Build Coastguard Worker     int desired = cinfo->desired_number_of_colors;
1253*dfc6aa5cSAndroid Build Coastguard Worker     /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
1254*dfc6aa5cSAndroid Build Coastguard Worker     if (desired < 8)
1255*dfc6aa5cSAndroid Build Coastguard Worker       ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
1256*dfc6aa5cSAndroid Build Coastguard Worker     /* Make sure colormap indexes can be represented by JSAMPLEs */
1257*dfc6aa5cSAndroid Build Coastguard Worker     if (desired > MAXNUMCOLORS)
1258*dfc6aa5cSAndroid Build Coastguard Worker       ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
1259*dfc6aa5cSAndroid Build Coastguard Worker     cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
1260*dfc6aa5cSAndroid Build Coastguard Worker       ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)desired, (JDIMENSION)3);
1261*dfc6aa5cSAndroid Build Coastguard Worker     cquantize->desired = desired;
1262*dfc6aa5cSAndroid Build Coastguard Worker   } else
1263*dfc6aa5cSAndroid Build Coastguard Worker     cquantize->sv_colormap = NULL;
1264*dfc6aa5cSAndroid Build Coastguard Worker 
1265*dfc6aa5cSAndroid Build Coastguard Worker   /* Only F-S dithering or no dithering is supported. */
1266*dfc6aa5cSAndroid Build Coastguard Worker   /* If user asks for ordered dither, give them F-S. */
1267*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->dither_mode != JDITHER_NONE)
1268*dfc6aa5cSAndroid Build Coastguard Worker     cinfo->dither_mode = JDITHER_FS;
1269*dfc6aa5cSAndroid Build Coastguard Worker 
1270*dfc6aa5cSAndroid Build Coastguard Worker   /* Allocate Floyd-Steinberg workspace if necessary.
1271*dfc6aa5cSAndroid Build Coastguard Worker    * This isn't really needed until pass 2, but again it may affect the memory
1272*dfc6aa5cSAndroid Build Coastguard Worker    * manager's space calculations.  Although we will cope with a later change
1273*dfc6aa5cSAndroid Build Coastguard Worker    * in dither_mode, we do not promise to honor max_memory_to_use if
1274*dfc6aa5cSAndroid Build Coastguard Worker    * dither_mode changes.
1275*dfc6aa5cSAndroid Build Coastguard Worker    */
1276*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->dither_mode == JDITHER_FS) {
1277*dfc6aa5cSAndroid Build Coastguard Worker     cquantize->fserrors = (FSERRPTR)(*cinfo->mem->alloc_large)
1278*dfc6aa5cSAndroid Build Coastguard Worker       ((j_common_ptr)cinfo, JPOOL_IMAGE,
1279*dfc6aa5cSAndroid Build Coastguard Worker        (size_t)((cinfo->output_width + 2) * (3 * sizeof(FSERROR))));
1280*dfc6aa5cSAndroid Build Coastguard Worker     /* Might as well create the error-limiting table too. */
1281*dfc6aa5cSAndroid Build Coastguard Worker     init_error_limit(cinfo);
1282*dfc6aa5cSAndroid Build Coastguard Worker   }
1283*dfc6aa5cSAndroid Build Coastguard Worker }
1284*dfc6aa5cSAndroid Build Coastguard Worker 
1285*dfc6aa5cSAndroid Build Coastguard Worker #endif /* QUANT_2PASS_SUPPORTED */
1286