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