ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

jquant1.c
Go to the documentation of this file.
00001 /*
00002  * jquant1.c
00003  *
00004  * Copyright (C) 1991-1996, Thomas G. Lane.
00005  * This file is part of the Independent JPEG Group's software.
00006  * For conditions of distribution and use, see the accompanying README file.
00007  *
00008  * This file contains 1-pass color quantization (color mapping) routines.
00009  * These routines provide mapping to a fixed color map using equally spaced
00010  * color values.  Optional Floyd-Steinberg or ordered dithering is available.
00011  */
00012 
00013 #define JPEG_INTERNALS
00014 #include "jinclude.h"
00015 #include "jpeglib.h"
00016 
00017 #ifdef QUANT_1PASS_SUPPORTED
00018 
00019 
00020 /*
00021  * The main purpose of 1-pass quantization is to provide a fast, if not very
00022  * high quality, colormapped output capability.  A 2-pass quantizer usually
00023  * gives better visual quality; however, for quantized grayscale output this
00024  * quantizer is perfectly adequate.  Dithering is highly recommended with this
00025  * quantizer, though you can turn it off if you really want to.
00026  *
00027  * In 1-pass quantization the colormap must be chosen in advance of seeing the
00028  * image.  We use a map consisting of all combinations of Ncolors[i] color
00029  * values for the i'th component.  The Ncolors[] values are chosen so that
00030  * their product, the total number of colors, is no more than that requested.
00031  * (In most cases, the product will be somewhat less.)
00032  *
00033  * Since the colormap is orthogonal, the representative value for each color
00034  * component can be determined without considering the other components;
00035  * then these indexes can be combined into a colormap index by a standard
00036  * N-dimensional-array-subscript calculation.  Most of the arithmetic involved
00037  * can be precalculated and stored in the lookup table colorindex[].
00038  * colorindex[i][j] maps pixel value j in component i to the nearest
00039  * representative value (grid plane) for that component; this index is
00040  * multiplied by the array stride for component i, so that the
00041  * index of the colormap entry closest to a given pixel value is just
00042  *    sum( colorindex[component-number][pixel-component-value] )
00043  * Aside from being fast, this scheme allows for variable spacing between
00044  * representative values with no additional lookup cost.
00045  *
00046  * If gamma correction has been applied in color conversion, it might be wise
00047  * to adjust the color grid spacing so that the representative colors are
00048  * equidistant in linear space.  At this writing, gamma correction is not
00049  * implemented by jdcolor, so nothing is done here.
00050  */
00051 
00052 
00053 /* Declarations for ordered dithering.
00054  *
00055  * We use a standard 16x16 ordered dither array.  The basic concept of ordered
00056  * dithering is described in many references, for instance Dale Schumacher's
00057  * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991).
00058  * In place of Schumacher's comparisons against a "threshold" value, we add a
00059  * "dither" value to the input pixel and then round the result to the nearest
00060  * output value.  The dither value is equivalent to (0.5 - threshold) times
00061  * the distance between output values.  For ordered dithering, we assume that
00062  * the output colors are equally spaced; if not, results will probably be
00063  * worse, since the dither may be too much or too little at a given point.
00064  *
00065  * The normal calculation would be to form pixel value + dither, range-limit
00066  * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual.
00067  * We can skip the separate range-limiting step by extending the colorindex
00068  * table in both directions.
00069  */
00070 
00071 #define ODITHER_SIZE  16    /* dimension of dither matrix */
00072 /* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */
00073 #define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE)   /* # cells in matrix */
00074 #define ODITHER_MASK  (ODITHER_SIZE-1) /* mask for wrapping around counters */
00075 
00076 typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE];
00077 typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE];
00078 
00079 static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = {
00080   /* Bayer's order-4 dither array.  Generated by the code given in
00081    * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I.
00082    * The values in this array must range from 0 to ODITHER_CELLS-1.
00083    */
00084   {   0,192, 48,240, 12,204, 60,252,  3,195, 51,243, 15,207, 63,255 },
00085   { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
00086   {  32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
00087   { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
00088   {   8,200, 56,248,  4,196, 52,244, 11,203, 59,251,  7,199, 55,247 },
00089   { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
00090   {  40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
00091   { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
00092   {   2,194, 50,242, 14,206, 62,254,  1,193, 49,241, 13,205, 61,253 },
00093   { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
00094   {  34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
00095   { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
00096   {  10,202, 58,250,  6,198, 54,246,  9,201, 57,249,  5,197, 53,245 },
00097   { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
00098   {  42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
00099   { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
00100 };
00101 
00102 
00103 /* Declarations for Floyd-Steinberg dithering.
00104  *
00105  * Errors are accumulated into the array fserrors[], at a resolution of
00106  * 1/16th of a pixel count.  The error at a given pixel is propagated
00107  * to its not-yet-processed neighbors using the standard F-S fractions,
00108  *      ... (here)  7/16
00109  *      3/16    5/16    1/16
00110  * We work left-to-right on even rows, right-to-left on odd rows.
00111  *
00112  * We can get away with a single array (holding one row's worth of errors)
00113  * by using it to store the current row's errors at pixel columns not yet
00114  * processed, but the next row's errors at columns already processed.  We
00115  * need only a few extra variables to hold the errors immediately around the
00116  * current column.  (If we are lucky, those variables are in registers, but
00117  * even if not, they're probably cheaper to access than array elements are.)
00118  *
00119  * The fserrors[] array is indexed [component#][position].
00120  * We provide (#columns + 2) entries per component; the extra entry at each
00121  * end saves us from special-casing the first and last pixels.
00122  *
00123  * Note: on a wide image, we might not have enough room in a PC's near data
00124  * segment to hold the error array; so it is allocated with alloc_large.
00125  */
00126 
00127 #if BITS_IN_JSAMPLE == 8
00128 typedef INT16 FSERROR;      /* 16 bits should be enough */
00129 typedef int LOCFSERROR;     /* use 'int' for calculation temps */
00130 #else
00131 typedef INT32 FSERROR;      /* may need more than 16 bits */
00132 typedef INT32 LOCFSERROR;   /* be sure calculation temps are big enough */
00133 #endif
00134 
00135 typedef FSERROR FAR *FSERRPTR;  /* pointer to error array (in FAR storage!) */
00136 
00137 
00138 /* Private subobject */
00139 
00140 #define MAX_Q_COMPS 4       /* max components I can handle */
00141 
00142 typedef struct {
00143   struct jpeg_color_quantizer pub; /* public fields */
00144 
00145   /* Initially allocated colormap is saved here */
00146   JSAMPARRAY sv_colormap;   /* The color map as a 2-D pixel array */
00147   int sv_actual;        /* number of entries in use */
00148 
00149   JSAMPARRAY colorindex;    /* Precomputed mapping for speed */
00150   /* colorindex[i][j] = index of color closest to pixel value j in component i,
00151    * premultiplied as described above.  Since colormap indexes must fit into
00152    * JSAMPLEs, the entries of this array will too.
00153    */
00154   boolean is_padded;        /* is the colorindex padded for odither? */
00155 
00156   int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */
00157 
00158   /* Variables for ordered dithering */
00159   int row_index;        /* cur row's vertical index in dither matrix */
00160   ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */
00161 
00162   /* Variables for Floyd-Steinberg dithering */
00163   FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */
00164   boolean on_odd_row;       /* flag to remember which row we are on */
00165 } my_cquantizer;
00166 
00167 typedef my_cquantizer * my_cquantize_ptr;
00168 
00169 
00170 /*
00171  * Policy-making subroutines for create_colormap and create_colorindex.
00172  * These routines determine the colormap to be used.  The rest of the module
00173  * only assumes that the colormap is orthogonal.
00174  *
00175  *  * select_ncolors decides how to divvy up the available colors
00176  *    among the components.
00177  *  * output_value defines the set of representative values for a component.
00178  *  * largest_input_value defines the mapping from input values to
00179  *    representative values for a component.
00180  * Note that the latter two routines may impose different policies for
00181  * different components, though this is not currently done.
00182  */
00183 
00184 
00185 LOCAL(int)
00186 select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
00187 /* Determine allocation of desired colors to components, */
00188 /* and fill in Ncolors[] array to indicate choice. */
00189 /* Return value is total number of colors (product of Ncolors[] values). */
00190 {
00191   int nc = cinfo->out_color_components; /* number of color components */
00192   int max_colors = cinfo->desired_number_of_colors;
00193   int total_colors, iroot, i, j;
00194   boolean changed;
00195   long temp;
00196   static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE };
00197 
00198   /* We can allocate at least the nc'th root of max_colors per component. */
00199   /* Compute floor(nc'th root of max_colors). */
00200   iroot = 1;
00201   do {
00202     iroot++;
00203     temp = iroot;       /* set temp = iroot ** nc */
00204     for (i = 1; i < nc; i++)
00205       temp *= iroot;
00206   } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */
00207   iroot--;          /* now iroot = floor(root) */
00208 
00209   /* Must have at least 2 color values per component */
00210   if (iroot < 2)
00211     ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp);
00212 
00213   /* Initialize to iroot color values for each component */
00214   total_colors = 1;
00215   for (i = 0; i < nc; i++) {
00216     Ncolors[i] = iroot;
00217     total_colors *= iroot;
00218   }
00219   /* We may be able to increment the count for one or more components without
00220    * exceeding max_colors, though we know not all can be incremented.
00221    * Sometimes, the first component can be incremented more than once!
00222    * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.)
00223    * In RGB colorspace, try to increment G first, then R, then B.
00224    */
00225   do {
00226     changed = FALSE;
00227     for (i = 0; i < nc; i++) {
00228       j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i);
00229       /* calculate new total_colors if Ncolors[j] is incremented */
00230       temp = total_colors / Ncolors[j];
00231       temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */
00232       if (temp > (long) max_colors)
00233     break;          /* won't fit, done with this pass */
00234       Ncolors[j]++;     /* OK, apply the increment */
00235       total_colors = (int) temp;
00236       changed = TRUE;
00237     }
00238   } while (changed);
00239 
00240   return total_colors;
00241 }
00242 
00243 
00244 LOCAL(int)
00245 output_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
00246 /* Return j'th output value, where j will range from 0 to maxj */
00247 /* The output values must fall in 0..MAXJSAMPLE in increasing order */
00248 {
00249   /* We always provide values 0 and MAXJSAMPLE for each component;
00250    * any additional values are equally spaced between these limits.
00251    * (Forcing the upper and lower values to the limits ensures that
00252    * dithering can't produce a color outside the selected gamut.)
00253    */
00254   return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj);
00255 }
00256 
00257 
00258 LOCAL(int)
00259 largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
00260 /* Return largest input value that should map to j'th output value */
00261 /* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */
00262 {
00263   /* Breakpoints are halfway between values returned by output_value */
00264   return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj));
00265 }
00266 
00267 
00268 /*
00269  * Create the colormap.
00270  */
00271 
00272 LOCAL(void)
00273 create_colormap (j_decompress_ptr cinfo)
00274 {
00275   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00276   JSAMPARRAY colormap;      /* Created colormap */
00277   int total_colors;     /* Number of distinct output colors */
00278   int i,j,k, nci, blksize, blkdist, ptr, val;
00279 
00280   /* Select number of colors for each component */
00281   total_colors = select_ncolors(cinfo, cquantize->Ncolors);
00282 
00283   /* Report selected color counts */
00284   if (cinfo->out_color_components == 3)
00285     TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS,
00286          total_colors, cquantize->Ncolors[0],
00287          cquantize->Ncolors[1], cquantize->Ncolors[2]);
00288   else
00289     TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors);
00290 
00291   /* Allocate and fill in the colormap. */
00292   /* The colors are ordered in the map in standard row-major order, */
00293   /* i.e. rightmost (highest-indexed) color changes most rapidly. */
00294 
00295   colormap = (*cinfo->mem->alloc_sarray)
00296     ((j_common_ptr) cinfo, JPOOL_IMAGE,
00297      (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components);
00298 
00299   /* blksize is number of adjacent repeated entries for a component */
00300   /* blkdist is distance between groups of identical entries for a component */
00301   blkdist = total_colors;
00302 
00303   for (i = 0; i < cinfo->out_color_components; i++) {
00304     /* fill in colormap entries for i'th color component */
00305     nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
00306     blksize = blkdist / nci;
00307     for (j = 0; j < nci; j++) {
00308       /* Compute j'th output value (out of nci) for component */
00309       val = output_value(cinfo, i, j, nci-1);
00310       /* Fill in all colormap entries that have this value of this component */
00311       for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
00312     /* fill in blksize entries beginning at ptr */
00313     for (k = 0; k < blksize; k++)
00314       colormap[i][ptr+k] = (JSAMPLE) val;
00315       }
00316     }
00317     blkdist = blksize;      /* blksize of this color is blkdist of next */
00318   }
00319 
00320   /* Save the colormap in private storage,
00321    * where it will survive color quantization mode changes.
00322    */
00323   cquantize->sv_colormap = colormap;
00324   cquantize->sv_actual = total_colors;
00325 }
00326 
00327 
00328 /*
00329  * Create the color index table.
00330  */
00331 
00332 LOCAL(void)
00333 create_colorindex (j_decompress_ptr cinfo)
00334 {
00335   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00336   JSAMPROW indexptr;
00337   int i,j,k, nci, blksize, val, pad;
00338 
00339   /* For ordered dither, we pad the color index tables by MAXJSAMPLE in
00340    * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE).
00341    * This is not necessary in the other dithering modes.  However, we
00342    * flag whether it was done in case user changes dithering mode.
00343    */
00344   if (cinfo->dither_mode == JDITHER_ORDERED) {
00345     pad = MAXJSAMPLE*2;
00346     cquantize->is_padded = TRUE;
00347   } else {
00348     pad = 0;
00349     cquantize->is_padded = FALSE;
00350   }
00351 
00352   cquantize->colorindex = (*cinfo->mem->alloc_sarray)
00353     ((j_common_ptr) cinfo, JPOOL_IMAGE,
00354      (JDIMENSION) (MAXJSAMPLE+1 + pad),
00355      (JDIMENSION) cinfo->out_color_components);
00356 
00357   /* blksize is number of adjacent repeated entries for a component */
00358   blksize = cquantize->sv_actual;
00359 
00360   for (i = 0; i < cinfo->out_color_components; i++) {
00361     /* fill in colorindex entries for i'th color component */
00362     nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
00363     blksize = blksize / nci;
00364 
00365     /* adjust colorindex pointers to provide padding at negative indexes. */
00366     if (pad)
00367       cquantize->colorindex[i] += MAXJSAMPLE;
00368 
00369     /* in loop, val = index of current output value, */
00370     /* and k = largest j that maps to current val */
00371     indexptr = cquantize->colorindex[i];
00372     val = 0;
00373     k = largest_input_value(cinfo, i, 0, nci-1);
00374     for (j = 0; j <= MAXJSAMPLE; j++) {
00375       while (j > k)     /* advance val if past boundary */
00376     k = largest_input_value(cinfo, i, ++val, nci-1);
00377       /* premultiply so that no multiplication needed in main processing */
00378       indexptr[j] = (JSAMPLE) (val * blksize);
00379     }
00380     /* Pad at both ends if necessary */
00381     if (pad)
00382       for (j = 1; j <= MAXJSAMPLE; j++) {
00383     indexptr[-j] = indexptr[0];
00384     indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE];
00385       }
00386   }
00387 }
00388 
00389 
00390 /*
00391  * Create an ordered-dither array for a component having ncolors
00392  * distinct output values.
00393  */
00394 
00395 LOCAL(ODITHER_MATRIX_PTR)
00396 make_odither_array (j_decompress_ptr cinfo, int ncolors)
00397 {
00398   ODITHER_MATRIX_PTR odither;
00399   int j,k;
00400   INT32 num,den;
00401 
00402   odither = (ODITHER_MATRIX_PTR)
00403     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00404                 SIZEOF(ODITHER_MATRIX));
00405   /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1).
00406    * Hence the dither value for the matrix cell with fill order f
00407    * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1).
00408    * On 16-bit-int machine, be careful to avoid overflow.
00409    */
00410   den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1));
00411   for (j = 0; j < ODITHER_SIZE; j++) {
00412     for (k = 0; k < ODITHER_SIZE; k++) {
00413       num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k])))
00414         * MAXJSAMPLE;
00415       /* Ensure round towards zero despite C's lack of consistency
00416        * about rounding negative values in integer division...
00417        */
00418       odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den);
00419     }
00420   }
00421   return odither;
00422 }
00423 
00424 
00425 /*
00426  * Create the ordered-dither tables.
00427  * Components having the same number of representative colors may 
00428  * share a dither table.
00429  */
00430 
00431 LOCAL(void)
00432 create_odither_tables (j_decompress_ptr cinfo)
00433 {
00434   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00435   ODITHER_MATRIX_PTR odither;
00436   int i, j, nci;
00437 
00438   for (i = 0; i < cinfo->out_color_components; i++) {
00439     nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
00440     odither = NULL;     /* search for matching prior component */
00441     for (j = 0; j < i; j++) {
00442       if (nci == cquantize->Ncolors[j]) {
00443     odither = cquantize->odither[j];
00444     break;
00445       }
00446     }
00447     if (odither == NULL)    /* need a new table? */
00448       odither = make_odither_array(cinfo, nci);
00449     cquantize->odither[i] = odither;
00450   }
00451 }
00452 
00453 
00454 /*
00455  * Map some rows of pixels to the output colormapped representation.
00456  */
00457 
00458 METHODDEF(void)
00459 color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
00460         JSAMPARRAY output_buf, int num_rows)
00461 /* General case, no dithering */
00462 {
00463   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00464   JSAMPARRAY colorindex = cquantize->colorindex;
00465   register int pixcode, ci;
00466   register JSAMPROW ptrin, ptrout;
00467   int row;
00468   JDIMENSION col;
00469   JDIMENSION width = cinfo->output_width;
00470   register int nc = cinfo->out_color_components;
00471 
00472   for (row = 0; row < num_rows; row++) {
00473     ptrin = input_buf[row];
00474     ptrout = output_buf[row];
00475     for (col = width; col > 0; col--) {
00476       pixcode = 0;
00477       for (ci = 0; ci < nc; ci++) {
00478     pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
00479       }
00480       *ptrout++ = (JSAMPLE) pixcode;
00481     }
00482   }
00483 }
00484 
00485 
00486 METHODDEF(void)
00487 color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
00488          JSAMPARRAY output_buf, int num_rows)
00489 /* Fast path for out_color_components==3, no dithering */
00490 {
00491   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00492   register int pixcode;
00493   register JSAMPROW ptrin, ptrout;
00494   JSAMPROW colorindex0 = cquantize->colorindex[0];
00495   JSAMPROW colorindex1 = cquantize->colorindex[1];
00496   JSAMPROW colorindex2 = cquantize->colorindex[2];
00497   int row;
00498   JDIMENSION col;
00499   JDIMENSION width = cinfo->output_width;
00500 
00501   for (row = 0; row < num_rows; row++) {
00502     ptrin = input_buf[row];
00503     ptrout = output_buf[row];
00504     for (col = width; col > 0; col--) {
00505       pixcode  = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]);
00506       pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
00507       pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
00508       *ptrout++ = (JSAMPLE) pixcode;
00509     }
00510   }
00511 }
00512 
00513 
00514 METHODDEF(void)
00515 quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
00516              JSAMPARRAY output_buf, int num_rows)
00517 /* General case, with ordered dithering */
00518 {
00519   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00520   register JSAMPROW input_ptr;
00521   register JSAMPROW output_ptr;
00522   JSAMPROW colorindex_ci;
00523   int * dither;         /* points to active row of dither matrix */
00524   int row_index, col_index; /* current indexes into dither matrix */
00525   int nc = cinfo->out_color_components;
00526   int ci;
00527   int row;
00528   JDIMENSION col;
00529   JDIMENSION width = cinfo->output_width;
00530 
00531   for (row = 0; row < num_rows; row++) {
00532     /* Initialize output values to 0 so can process components separately */
00533     jzero_far((void FAR *) output_buf[row],
00534           (size_t) (width * SIZEOF(JSAMPLE)));
00535     row_index = cquantize->row_index;
00536     for (ci = 0; ci < nc; ci++) {
00537       input_ptr = input_buf[row] + ci;
00538       output_ptr = output_buf[row];
00539       colorindex_ci = cquantize->colorindex[ci];
00540       dither = cquantize->odither[ci][row_index];
00541       col_index = 0;
00542 
00543       for (col = width; col > 0; col--) {
00544     /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE,
00545      * select output value, accumulate into output code for this pixel.
00546      * Range-limiting need not be done explicitly, as we have extended
00547      * the colorindex table to produce the right answers for out-of-range
00548      * inputs.  The maximum dither is +- MAXJSAMPLE; this sets the
00549      * required amount of padding.
00550      */
00551     *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]];
00552     input_ptr += nc;
00553     output_ptr++;
00554     col_index = (col_index + 1) & ODITHER_MASK;
00555       }
00556     }
00557     /* Advance row index for next row */
00558     row_index = (row_index + 1) & ODITHER_MASK;
00559     cquantize->row_index = row_index;
00560   }
00561 }
00562 
00563 
00564 METHODDEF(void)
00565 quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
00566               JSAMPARRAY output_buf, int num_rows)
00567 /* Fast path for out_color_components==3, with ordered dithering */
00568 {
00569   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00570   register int pixcode;
00571   register JSAMPROW input_ptr;
00572   register JSAMPROW output_ptr;
00573   JSAMPROW colorindex0 = cquantize->colorindex[0];
00574   JSAMPROW colorindex1 = cquantize->colorindex[1];
00575   JSAMPROW colorindex2 = cquantize->colorindex[2];
00576   int * dither0;        /* points to active row of dither matrix */
00577   int * dither1;
00578   int * dither2;
00579   int row_index, col_index; /* current indexes into dither matrix */
00580   int row;
00581   JDIMENSION col;
00582   JDIMENSION width = cinfo->output_width;
00583 
00584   for (row = 0; row < num_rows; row++) {
00585     row_index = cquantize->row_index;
00586     input_ptr = input_buf[row];
00587     output_ptr = output_buf[row];
00588     dither0 = cquantize->odither[0][row_index];
00589     dither1 = cquantize->odither[1][row_index];
00590     dither2 = cquantize->odither[2][row_index];
00591     col_index = 0;
00592 
00593     for (col = width; col > 0; col--) {
00594       pixcode  = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) +
00595                     dither0[col_index]]);
00596       pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) +
00597                     dither1[col_index]]);
00598       pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) +
00599                     dither2[col_index]]);
00600       *output_ptr++ = (JSAMPLE) pixcode;
00601       col_index = (col_index + 1) & ODITHER_MASK;
00602     }
00603     row_index = (row_index + 1) & ODITHER_MASK;
00604     cquantize->row_index = row_index;
00605   }
00606 }
00607 
00608 
00609 METHODDEF(void)
00610 quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
00611             JSAMPARRAY output_buf, int num_rows)
00612 /* General case, with Floyd-Steinberg dithering */
00613 {
00614   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00615   register LOCFSERROR cur;  /* current error or pixel value */
00616   LOCFSERROR belowerr;      /* error for pixel below cur */
00617   LOCFSERROR bpreverr;      /* error for below/prev col */
00618   LOCFSERROR bnexterr;      /* error for below/next col */
00619   LOCFSERROR delta;
00620   register FSERRPTR errorptr;   /* => fserrors[] at column before current */
00621   register JSAMPROW input_ptr;
00622   register JSAMPROW output_ptr;
00623   JSAMPROW colorindex_ci;
00624   JSAMPROW colormap_ci;
00625   int pixcode;
00626   int nc = cinfo->out_color_components;
00627   int dir;          /* 1 for left-to-right, -1 for right-to-left */
00628   int dirnc;            /* dir * nc */
00629   int ci;
00630   int row;
00631   JDIMENSION col;
00632   JDIMENSION width = cinfo->output_width;
00633   JSAMPLE *range_limit = cinfo->sample_range_limit;
00634   SHIFT_TEMPS
00635 
00636   for (row = 0; row < num_rows; row++) {
00637     /* Initialize output values to 0 so can process components separately */
00638     jzero_far((void FAR *) output_buf[row],
00639           (size_t) (width * SIZEOF(JSAMPLE)));
00640     for (ci = 0; ci < nc; ci++) {
00641       input_ptr = input_buf[row] + ci;
00642       output_ptr = output_buf[row];
00643       if (cquantize->on_odd_row) {
00644     /* work right to left in this row */
00645     input_ptr += (width-1) * nc; /* so point to rightmost pixel */
00646     output_ptr += width-1;
00647     dir = -1;
00648     dirnc = -nc;
00649     errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */
00650       } else {
00651     /* work left to right in this row */
00652     dir = 1;
00653     dirnc = nc;
00654     errorptr = cquantize->fserrors[ci]; /* => entry before first column */
00655       }
00656       colorindex_ci = cquantize->colorindex[ci];
00657       colormap_ci = cquantize->sv_colormap[ci];
00658       /* Preset error values: no error propagated to first pixel from left */
00659       cur = 0;
00660       /* and no error propagated to row below yet */
00661       belowerr = bpreverr = 0;
00662 
00663       for (col = width; col > 0; col--) {
00664     /* cur holds the error propagated from the previous pixel on the
00665      * current line.  Add the error propagated from the previous line
00666      * to form the complete error correction term for this pixel, and
00667      * round the error term (which is expressed * 16) to an integer.
00668      * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
00669      * for either sign of the error value.
00670      * Note: errorptr points to *previous* column's array entry.
00671      */
00672     cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4);
00673     /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
00674      * The maximum error is +- MAXJSAMPLE; this sets the required size
00675      * of the range_limit array.
00676      */
00677     cur += GETJSAMPLE(*input_ptr);
00678     cur = GETJSAMPLE(range_limit[cur]);
00679     /* Select output value, accumulate into output code for this pixel */
00680     pixcode = GETJSAMPLE(colorindex_ci[cur]);
00681     *output_ptr += (JSAMPLE) pixcode;
00682     /* Compute actual representation error at this pixel */
00683     /* Note: we can do this even though we don't have the final */
00684     /* pixel code, because the colormap is orthogonal. */
00685     cur -= GETJSAMPLE(colormap_ci[pixcode]);
00686     /* Compute error fractions to be propagated to adjacent pixels.
00687      * Add these into the running sums, and simultaneously shift the
00688      * next-line error sums left by 1 column.
00689      */
00690     bnexterr = cur;
00691     delta = cur * 2;
00692     cur += delta;       /* form error * 3 */
00693     errorptr[0] = (FSERROR) (bpreverr + cur);
00694     cur += delta;       /* form error * 5 */
00695     bpreverr = belowerr + cur;
00696     belowerr = bnexterr;
00697     cur += delta;       /* form error * 7 */
00698     /* At this point cur contains the 7/16 error value to be propagated
00699      * to the next pixel on the current line, and all the errors for the
00700      * next line have been shifted over. We are therefore ready to move on.
00701      */
00702     input_ptr += dirnc; /* advance input ptr to next column */
00703     output_ptr += dir;  /* advance output ptr to next column */
00704     errorptr += dir;    /* advance errorptr to current column */
00705       }
00706       /* Post-loop cleanup: we must unload the final error value into the
00707        * final fserrors[] entry.  Note we need not unload belowerr because
00708        * it is for the dummy column before or after the actual array.
00709        */
00710       errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */
00711     }
00712     cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE);
00713   }
00714 }
00715 
00716 
00717 /*
00718  * Allocate workspace for Floyd-Steinberg errors.
00719  */
00720 
00721 LOCAL(void)
00722 alloc_fs_workspace (j_decompress_ptr cinfo)
00723 {
00724   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00725   size_t arraysize;
00726   int i;
00727 
00728   arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
00729   for (i = 0; i < cinfo->out_color_components; i++) {
00730     cquantize->fserrors[i] = (FSERRPTR)
00731       (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
00732   }
00733 }
00734 
00735 
00736 /*
00737  * Initialize for one-pass color quantization.
00738  */
00739 
00740 METHODDEF(void)
00741 start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
00742 {
00743   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00744   size_t arraysize;
00745   int i;
00746 
00747   /* Install my colormap. */
00748   cinfo->colormap = cquantize->sv_colormap;
00749   cinfo->actual_number_of_colors = cquantize->sv_actual;
00750 
00751   /* Initialize for desired dithering mode. */
00752   switch (cinfo->dither_mode) {
00753   case JDITHER_NONE:
00754     if (cinfo->out_color_components == 3)
00755       cquantize->pub.color_quantize = color_quantize3;
00756     else
00757       cquantize->pub.color_quantize = color_quantize;
00758     break;
00759   case JDITHER_ORDERED:
00760     if (cinfo->out_color_components == 3)
00761       cquantize->pub.color_quantize = quantize3_ord_dither;
00762     else
00763       cquantize->pub.color_quantize = quantize_ord_dither;
00764     cquantize->row_index = 0;   /* initialize state for ordered dither */
00765     /* If user changed to ordered dither from another mode,
00766      * we must recreate the color index table with padding.
00767      * This will cost extra space, but probably isn't very likely.
00768      */
00769     if (! cquantize->is_padded)
00770       create_colorindex(cinfo);
00771     /* Create ordered-dither tables if we didn't already. */
00772     if (cquantize->odither[0] == NULL)
00773       create_odither_tables(cinfo);
00774     break;
00775   case JDITHER_FS:
00776     cquantize->pub.color_quantize = quantize_fs_dither;
00777     cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */
00778     /* Allocate Floyd-Steinberg workspace if didn't already. */
00779     if (cquantize->fserrors[0] == NULL)
00780       alloc_fs_workspace(cinfo);
00781     /* Initialize the propagated errors to zero. */
00782     arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
00783     for (i = 0; i < cinfo->out_color_components; i++)
00784       jzero_far((void FAR *) cquantize->fserrors[i], arraysize);
00785     break;
00786   default:
00787     ERREXIT(cinfo, JERR_NOT_COMPILED);
00788     break;
00789   }
00790 }
00791 
00792 
00793 /*
00794  * Finish up at the end of the pass.
00795  */
00796 
00797 METHODDEF(void)
00798 finish_pass_1_quant (j_decompress_ptr cinfo)
00799 {
00800   /* no work in 1-pass case */
00801 }
00802 
00803 
00804 /*
00805  * Switch to a new external colormap between output passes.
00806  * Shouldn't get to this module!
00807  */
00808 
00809 METHODDEF(void)
00810 new_color_map_1_quant (j_decompress_ptr cinfo)
00811 {
00812   ERREXIT(cinfo, JERR_MODE_CHANGE);
00813 }
00814 
00815 
00816 /*
00817  * Module initialization routine for 1-pass color quantization.
00818  */
00819 
00820 GLOBAL(void)
00821 jinit_1pass_quantizer (j_decompress_ptr cinfo)
00822 {
00823   my_cquantize_ptr cquantize;
00824 
00825   cquantize = (my_cquantize_ptr)
00826     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00827                 SIZEOF(my_cquantizer));
00828   cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
00829   cquantize->pub.start_pass = start_pass_1_quant;
00830   cquantize->pub.finish_pass = finish_pass_1_quant;
00831   cquantize->pub.new_color_map = new_color_map_1_quant;
00832   cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */
00833   cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */
00834 
00835   /* Make sure my internal arrays won't overflow */
00836   if (cinfo->out_color_components > MAX_Q_COMPS)
00837     ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
00838   /* Make sure colormap indexes can be represented by JSAMPLEs */
00839   if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1))
00840     ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
00841 
00842   /* Create the colormap and color index table. */
00843   create_colormap(cinfo);
00844   create_colorindex(cinfo);
00845 
00846   /* Allocate Floyd-Steinberg workspace now if requested.
00847    * We do this now since it is FAR storage and may affect the memory
00848    * manager's space calculations.  If the user changes to FS dither
00849    * mode in a later pass, we will allocate the space then, and will
00850    * possibly overrun the max_memory_to_use setting.
00851    */
00852   if (cinfo->dither_mode == JDITHER_FS)
00853     alloc_fs_workspace(cinfo);
00854 }
00855 
00856 #endif /* QUANT_1PASS_SUPPORTED */

Generated on Sat May 26 2012 04:18:14 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.