00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 #define JPEG_INTERNALS
00021 #include "jinclude.h"
00022 #include "jpeglib.h"
00023 
00024 #ifdef QUANT_2PASS_SUPPORTED
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 #define R_SCALE 2               
00074 #define G_SCALE 3               
00075 #define B_SCALE 1               
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 #if RGB_RED == 0
00085 #define C0_SCALE R_SCALE
00086 #endif
00087 #if RGB_BLUE == 0
00088 #define C0_SCALE B_SCALE
00089 #endif
00090 #if RGB_GREEN == 1
00091 #define C1_SCALE G_SCALE
00092 #endif
00093 #if RGB_RED == 2
00094 #define C2_SCALE R_SCALE
00095 #endif
00096 #if RGB_BLUE == 2
00097 #define C2_SCALE B_SCALE
00098 #endif
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 #define MAXNUMCOLORS  (MAXJSAMPLE+1) 
00128 
00129 
00130 
00131 
00132 #define HIST_C0_BITS  5         
00133 #define HIST_C1_BITS  6         
00134 #define HIST_C2_BITS  5         
00135 
00136 
00137 #define HIST_C0_ELEMS  (1<<HIST_C0_BITS)
00138 #define HIST_C1_ELEMS  (1<<HIST_C1_BITS)
00139 #define HIST_C2_ELEMS  (1<<HIST_C2_BITS)
00140 
00141 
00142 #define C0_SHIFT  (BITS_IN_JSAMPLE-HIST_C0_BITS)
00143 #define C1_SHIFT  (BITS_IN_JSAMPLE-HIST_C1_BITS)
00144 #define C2_SHIFT  (BITS_IN_JSAMPLE-HIST_C2_BITS)
00145 
00146 
00147 typedef UINT16 histcell;        
00148 
00149 typedef histcell FAR * histptr; 
00150 
00151 typedef histcell hist1d[HIST_C2_ELEMS]; 
00152 typedef hist1d FAR * hist2d;    
00153 typedef hist2d * hist3d;        
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 #if BITS_IN_JSAMPLE == 8
00181 typedef INT16 FSERROR;          
00182 typedef int LOCFSERROR;         
00183 #else
00184 typedef INT32 FSERROR;          
00185 typedef INT32 LOCFSERROR;       
00186 #endif
00187 
00188 typedef FSERROR FAR *FSERRPTR;  
00189 
00190 
00191 
00192 
00193 typedef struct {
00194   struct jpeg_color_quantizer pub; 
00195 
00196   
00197   JSAMPARRAY sv_colormap;       
00198   int desired;                  
00199 
00200   
00201   hist3d histogram;             
00202 
00203   boolean needs_zeroed;         
00204 
00205   
00206   FSERRPTR fserrors;            
00207   boolean on_odd_row;           
00208   int * error_limiter;          
00209 } my_cquantizer;
00210 
00211 typedef my_cquantizer * my_cquantize_ptr;
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 METHODDEF(void)
00224 prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
00225                   JSAMPARRAY output_buf, int num_rows)
00226 {
00227   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00228   register JSAMPROW ptr;
00229   register histptr histp;
00230   register hist3d histogram = cquantize->histogram;
00231   int row;
00232   JDIMENSION col;
00233   JDIMENSION width = cinfo->output_width;
00234 
00235   for (row = 0; row < num_rows; row++) {
00236     ptr = input_buf[row];
00237     for (col = width; col > 0; col--) {
00238       
00239       histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
00240                          [GETJSAMPLE(ptr[1]) >> C1_SHIFT]
00241                          [GETJSAMPLE(ptr[2]) >> C2_SHIFT];
00242       
00243       if (++(*histp) <= 0)
00244         (*histp)--;
00245       ptr += 3;
00246     }
00247   }
00248 }
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 typedef struct {
00259   
00260   int c0min, c0max;
00261   int c1min, c1max;
00262   int c2min, c2max;
00263   
00264   INT32 volume;
00265   
00266   long colorcount;
00267 } box;
00268 
00269 typedef box * boxptr;
00270 
00271 
00272 LOCAL(boxptr)
00273 find_biggest_color_pop (boxptr boxlist, int numboxes)
00274 
00275 
00276 {
00277   register boxptr boxp;
00278   register int i;
00279   register long maxc = 0;
00280   boxptr which = NULL;
00281   
00282   for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
00283     if (boxp->colorcount > maxc && boxp->volume > 0) {
00284       which = boxp;
00285       maxc = boxp->colorcount;
00286     }
00287   }
00288   return which;
00289 }
00290 
00291 
00292 LOCAL(boxptr)
00293 find_biggest_volume (boxptr boxlist, int numboxes)
00294 
00295 
00296 {
00297   register boxptr boxp;
00298   register int i;
00299   register INT32 maxv = 0;
00300   boxptr which = NULL;
00301   
00302   for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
00303     if (boxp->volume > maxv) {
00304       which = boxp;
00305       maxv = boxp->volume;
00306     }
00307   }
00308   return which;
00309 }
00310 
00311 
00312 LOCAL(void)
00313 update_box (j_decompress_ptr cinfo, boxptr boxp)
00314 
00315 
00316 {
00317   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00318   hist3d histogram = cquantize->histogram;
00319   histptr histp;
00320   int c0,c1,c2;
00321   int c0min,c0max,c1min,c1max,c2min,c2max;
00322   INT32 dist0,dist1,dist2;
00323   long ccount;
00324   
00325   c0min = boxp->c0min;  c0max = boxp->c0max;
00326   c1min = boxp->c1min;  c1max = boxp->c1max;
00327   c2min = boxp->c2min;  c2max = boxp->c2max;
00328   
00329   if (c0max > c0min)
00330     for (c0 = c0min; c0 <= c0max; c0++)
00331       for (c1 = c1min; c1 <= c1max; c1++) {
00332         histp = & histogram[c0][c1][c2min];
00333         for (c2 = c2min; c2 <= c2max; c2++)
00334           if (*histp++ != 0) {
00335             boxp->c0min = c0min = c0;
00336             goto have_c0min;
00337           }
00338       }
00339  have_c0min:
00340   if (c0max > c0min)
00341     for (c0 = c0max; c0 >= c0min; c0--)
00342       for (c1 = c1min; c1 <= c1max; c1++) {
00343         histp = & histogram[c0][c1][c2min];
00344         for (c2 = c2min; c2 <= c2max; c2++)
00345           if (*histp++ != 0) {
00346             boxp->c0max = c0max = c0;
00347             goto have_c0max;
00348           }
00349       }
00350  have_c0max:
00351   if (c1max > c1min)
00352     for (c1 = c1min; c1 <= c1max; c1++)
00353       for (c0 = c0min; c0 <= c0max; c0++) {
00354         histp = & histogram[c0][c1][c2min];
00355         for (c2 = c2min; c2 <= c2max; c2++)
00356           if (*histp++ != 0) {
00357             boxp->c1min = c1min = c1;
00358             goto have_c1min;
00359           }
00360       }
00361  have_c1min:
00362   if (c1max > c1min)
00363     for (c1 = c1max; c1 >= c1min; c1--)
00364       for (c0 = c0min; c0 <= c0max; c0++) {
00365         histp = & histogram[c0][c1][c2min];
00366         for (c2 = c2min; c2 <= c2max; c2++)
00367           if (*histp++ != 0) {
00368             boxp->c1max = c1max = c1;
00369             goto have_c1max;
00370           }
00371       }
00372  have_c1max:
00373   if (c2max > c2min)
00374     for (c2 = c2min; c2 <= c2max; c2++)
00375       for (c0 = c0min; c0 <= c0max; c0++) {
00376         histp = & histogram[c0][c1min][c2];
00377         for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
00378           if (*histp != 0) {
00379             boxp->c2min = c2min = c2;
00380             goto have_c2min;
00381           }
00382       }
00383  have_c2min:
00384   if (c2max > c2min)
00385     for (c2 = c2max; c2 >= c2min; c2--)
00386       for (c0 = c0min; c0 <= c0max; c0++) {
00387         histp = & histogram[c0][c1min][c2];
00388         for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
00389           if (*histp != 0) {
00390             boxp->c2max = c2max = c2;
00391             goto have_c2max;
00392           }
00393       }
00394  have_c2max:
00395 
00396   
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404   dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
00405   dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
00406   dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
00407   boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
00408   
00409   
00410   ccount = 0;
00411   for (c0 = c0min; c0 <= c0max; c0++)
00412     for (c1 = c1min; c1 <= c1max; c1++) {
00413       histp = & histogram[c0][c1][c2min];
00414       for (c2 = c2min; c2 <= c2max; c2++, histp++)
00415         if (*histp != 0) {
00416           ccount++;
00417         }
00418     }
00419   boxp->colorcount = ccount;
00420 }
00421 
00422 
00423 LOCAL(int)
00424 median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
00425             int desired_colors)
00426 
00427 {
00428   int n,lb;
00429   int c0,c1,c2,cmax;
00430   register boxptr b1,b2;
00431 
00432   while (numboxes < desired_colors) {
00433     
00434 
00435 
00436     if (numboxes*2 <= desired_colors) {
00437       b1 = find_biggest_color_pop(boxlist, numboxes);
00438     } else {
00439       b1 = find_biggest_volume(boxlist, numboxes);
00440     }
00441     if (b1 == NULL)             
00442       break;
00443     b2 = &boxlist[numboxes];    
00444     
00445     b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
00446     b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
00447     
00448 
00449 
00450 
00451     c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE;
00452     c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE;
00453     c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE;
00454     
00455 
00456 
00457 #if RGB_RED == 0
00458     cmax = c1; n = 1;
00459     if (c0 > cmax) { cmax = c0; n = 0; }
00460     if (c2 > cmax) { n = 2; }
00461 #else
00462     cmax = c1; n = 1;
00463     if (c2 > cmax) { cmax = c2; n = 2; }
00464     if (c0 > cmax) { n = 0; }
00465 #endif
00466     
00467 
00468 
00469 
00470 
00471 
00472     switch (n) {
00473     case 0:
00474       lb = (b1->c0max + b1->c0min) / 2;
00475       b1->c0max = lb;
00476       b2->c0min = lb+1;
00477       break;
00478     case 1:
00479       lb = (b1->c1max + b1->c1min) / 2;
00480       b1->c1max = lb;
00481       b2->c1min = lb+1;
00482       break;
00483     case 2:
00484       lb = (b1->c2max + b1->c2min) / 2;
00485       b1->c2max = lb;
00486       b2->c2min = lb+1;
00487       break;
00488     }
00489     
00490     update_box(cinfo, b1);
00491     update_box(cinfo, b2);
00492     numboxes++;
00493   }
00494   return numboxes;
00495 }
00496 
00497 
00498 LOCAL(void)
00499 compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
00500 
00501 {
00502   
00503   
00504   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00505   hist3d histogram = cquantize->histogram;
00506   histptr histp;
00507   int c0,c1,c2;
00508   int c0min,c0max,c1min,c1max,c2min,c2max;
00509   long count;
00510   long total = 0;
00511   long c0total = 0;
00512   long c1total = 0;
00513   long c2total = 0;
00514   
00515   c0min = boxp->c0min;  c0max = boxp->c0max;
00516   c1min = boxp->c1min;  c1max = boxp->c1max;
00517   c2min = boxp->c2min;  c2max = boxp->c2max;
00518   
00519   for (c0 = c0min; c0 <= c0max; c0++)
00520     for (c1 = c1min; c1 <= c1max; c1++) {
00521       histp = & histogram[c0][c1][c2min];
00522       for (c2 = c2min; c2 <= c2max; c2++) {
00523         if ((count = *histp++) != 0) {
00524           total += count;
00525           c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count;
00526           c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count;
00527           c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count;
00528         }
00529       }
00530     }
00531   
00532   cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
00533   cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
00534   cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
00535 }
00536 
00537 
00538 LOCAL(void)
00539 select_colors (j_decompress_ptr cinfo, int desired_colors)
00540 
00541 {
00542   boxptr boxlist;
00543   int numboxes;
00544   int i;
00545 
00546   
00547   boxlist = (boxptr) (*cinfo->mem->alloc_small)
00548     ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box));
00549   
00550   numboxes = 1;
00551   boxlist[0].c0min = 0;
00552   boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT;
00553   boxlist[0].c1min = 0;
00554   boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT;
00555   boxlist[0].c2min = 0;
00556   boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT;
00557   
00558   update_box(cinfo, & boxlist[0]);
00559   
00560   numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
00561   
00562   for (i = 0; i < numboxes; i++)
00563     compute_color(cinfo, & boxlist[i], i);
00564   cinfo->actual_number_of_colors = numboxes;
00565   TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes);
00566 }
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 
00575 
00576 
00577 
00578 
00579 
00580 
00581 
00582 
00583 
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 
00601 
00602 
00603 
00604 
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 
00622 
00623 
00624 #define BOX_C0_LOG  (HIST_C0_BITS-3)
00625 #define BOX_C1_LOG  (HIST_C1_BITS-3)
00626 #define BOX_C2_LOG  (HIST_C2_BITS-3)
00627 
00628 #define BOX_C0_ELEMS  (1<<BOX_C0_LOG) 
00629 #define BOX_C1_ELEMS  (1<<BOX_C1_LOG)
00630 #define BOX_C2_ELEMS  (1<<BOX_C2_LOG)
00631 
00632 #define BOX_C0_SHIFT  (C0_SHIFT + BOX_C0_LOG)
00633 #define BOX_C1_SHIFT  (C1_SHIFT + BOX_C1_LOG)
00634 #define BOX_C2_SHIFT  (C2_SHIFT + BOX_C2_LOG)
00635 
00636 
00637 
00638 
00639 
00640 
00641 
00642 
00643 
00644 
00645 LOCAL(int)
00646 find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
00647                     JSAMPLE colorlist[])
00648 
00649 
00650 
00651 
00652 
00653 
00654 
00655 
00656 {
00657   int numcolors = cinfo->actual_number_of_colors;
00658   int maxc0, maxc1, maxc2;
00659   int centerc0, centerc1, centerc2;
00660   int i, x, ncolors;
00661   INT32 minmaxdist, min_dist, max_dist, tdist;
00662   INT32 mindist[MAXNUMCOLORS];  
00663 
00664   
00665 
00666 
00667 
00668 
00669 
00670   maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));
00671   centerc0 = (minc0 + maxc0) >> 1;
00672   maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));
00673   centerc1 = (minc1 + maxc1) >> 1;
00674   maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));
00675   centerc2 = (minc2 + maxc2) >> 1;
00676 
00677   
00678 
00679 
00680 
00681 
00682 
00683 
00684 
00685   minmaxdist = 0x7FFFFFFFL;
00686 
00687   for (i = 0; i < numcolors; i++) {
00688     
00689     x = GETJSAMPLE(cinfo->colormap[0][i]);
00690     if (x < minc0) {
00691       tdist = (x - minc0) * C0_SCALE;
00692       min_dist = tdist*tdist;
00693       tdist = (x - maxc0) * C0_SCALE;
00694       max_dist = tdist*tdist;
00695     } else if (x > maxc0) {
00696       tdist = (x - maxc0) * C0_SCALE;
00697       min_dist = tdist*tdist;
00698       tdist = (x - minc0) * C0_SCALE;
00699       max_dist = tdist*tdist;
00700     } else {
00701       
00702       min_dist = 0;
00703       if (x <= centerc0) {
00704         tdist = (x - maxc0) * C0_SCALE;
00705         max_dist = tdist*tdist;
00706       } else {
00707         tdist = (x - minc0) * C0_SCALE;
00708         max_dist = tdist*tdist;
00709       }
00710     }
00711 
00712     x = GETJSAMPLE(cinfo->colormap[1][i]);
00713     if (x < minc1) {
00714       tdist = (x - minc1) * C1_SCALE;
00715       min_dist += tdist*tdist;
00716       tdist = (x - maxc1) * C1_SCALE;
00717       max_dist += tdist*tdist;
00718     } else if (x > maxc1) {
00719       tdist = (x - maxc1) * C1_SCALE;
00720       min_dist += tdist*tdist;
00721       tdist = (x - minc1) * C1_SCALE;
00722       max_dist += tdist*tdist;
00723     } else {
00724       
00725       if (x <= centerc1) {
00726         tdist = (x - maxc1) * C1_SCALE;
00727         max_dist += tdist*tdist;
00728       } else {
00729         tdist = (x - minc1) * C1_SCALE;
00730         max_dist += tdist*tdist;
00731       }
00732     }
00733 
00734     x = GETJSAMPLE(cinfo->colormap[2][i]);
00735     if (x < minc2) {
00736       tdist = (x - minc2) * C2_SCALE;
00737       min_dist += tdist*tdist;
00738       tdist = (x - maxc2) * C2_SCALE;
00739       max_dist += tdist*tdist;
00740     } else if (x > maxc2) {
00741       tdist = (x - maxc2) * C2_SCALE;
00742       min_dist += tdist*tdist;
00743       tdist = (x - minc2) * C2_SCALE;
00744       max_dist += tdist*tdist;
00745     } else {
00746       
00747       if (x <= centerc2) {
00748         tdist = (x - maxc2) * C2_SCALE;
00749         max_dist += tdist*tdist;
00750       } else {
00751         tdist = (x - minc2) * C2_SCALE;
00752         max_dist += tdist*tdist;
00753       }
00754     }
00755 
00756     mindist[i] = min_dist;      
00757     if (max_dist < minmaxdist)
00758       minmaxdist = max_dist;
00759   }
00760 
00761   
00762 
00763 
00764 
00765   ncolors = 0;
00766   for (i = 0; i < numcolors; i++) {
00767     if (mindist[i] <= minmaxdist)
00768       colorlist[ncolors++] = (JSAMPLE) i;
00769   }
00770   return ncolors;
00771 }
00772 
00773 
00774 LOCAL(void)
00775 find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
00776                   int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
00777 
00778 
00779 
00780 
00781 
00782 
00783 {
00784   int ic0, ic1, ic2;
00785   int i, icolor;
00786   register INT32 * bptr;        
00787   JSAMPLE * cptr;               
00788   INT32 dist0, dist1;           
00789   register INT32 dist2;         
00790   INT32 xx0, xx1;               
00791   register INT32 xx2;
00792   INT32 inc0, inc1, inc2;       
00793   
00794   INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
00795 
00796   
00797   bptr = bestdist;
00798   for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
00799     *bptr++ = 0x7FFFFFFFL;
00800   
00801   
00802 
00803 
00804 
00805   
00806   
00807 #define STEP_C0  ((1 << C0_SHIFT) * C0_SCALE)
00808 #define STEP_C1  ((1 << C1_SHIFT) * C1_SCALE)
00809 #define STEP_C2  ((1 << C2_SHIFT) * C2_SCALE)
00810   
00811   for (i = 0; i < numcolors; i++) {
00812     icolor = GETJSAMPLE(colorlist[i]);
00813     
00814     inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
00815     dist0 = inc0*inc0;
00816     inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
00817     dist0 += inc1*inc1;
00818     inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
00819     dist0 += inc2*inc2;
00820     
00821     inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
00822     inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
00823     inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;
00824     
00825     bptr = bestdist;
00826     cptr = bestcolor;
00827     xx0 = inc0;
00828     for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) {
00829       dist1 = dist0;
00830       xx1 = inc1;
00831       for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) {
00832         dist2 = dist1;
00833         xx2 = inc2;
00834         for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) {
00835           if (dist2 < *bptr) {
00836             *bptr = dist2;
00837             *cptr = (JSAMPLE) icolor;
00838           }
00839           dist2 += xx2;
00840           xx2 += 2 * STEP_C2 * STEP_C2;
00841           bptr++;
00842           cptr++;
00843         }
00844         dist1 += xx1;
00845         xx1 += 2 * STEP_C1 * STEP_C1;
00846       }
00847       dist0 += xx0;
00848       xx0 += 2 * STEP_C0 * STEP_C0;
00849     }
00850   }
00851 }
00852 
00853 
00854 LOCAL(void)
00855 fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
00856 
00857 
00858 
00859 {
00860   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00861   hist3d histogram = cquantize->histogram;
00862   int minc0, minc1, minc2;      
00863   int ic0, ic1, ic2;
00864   register JSAMPLE * cptr;      
00865   register histptr cachep;      
00866   
00867   JSAMPLE colorlist[MAXNUMCOLORS];
00868   int numcolors;                
00869   
00870   JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
00871 
00872   
00873   c0 >>= BOX_C0_LOG;
00874   c1 >>= BOX_C1_LOG;
00875   c2 >>= BOX_C2_LOG;
00876 
00877   
00878 
00879 
00880 
00881   minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
00882   minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
00883   minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
00884   
00885   
00886 
00887 
00888   numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist);
00889 
00890   
00891   find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist,
00892                    bestcolor);
00893 
00894   
00895   c0 <<= BOX_C0_LOG;            
00896   c1 <<= BOX_C1_LOG;
00897   c2 <<= BOX_C2_LOG;
00898   cptr = bestcolor;
00899   for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
00900     for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
00901       cachep = & histogram[c0+ic0][c1+ic1][c2];
00902       for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
00903         *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1);
00904       }
00905     }
00906   }
00907 }
00908 
00909 
00910 
00911 
00912 
00913 
00914 METHODDEF(void)
00915 pass2_no_dither (j_decompress_ptr cinfo,
00916                  JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
00917 
00918 {
00919   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00920   hist3d histogram = cquantize->histogram;
00921   register JSAMPROW inptr, outptr;
00922   register histptr cachep;
00923   register int c0, c1, c2;
00924   int row;
00925   JDIMENSION col;
00926   JDIMENSION width = cinfo->output_width;
00927 
00928   for (row = 0; row < num_rows; row++) {
00929     inptr = input_buf[row];
00930     outptr = output_buf[row];
00931     for (col = width; col > 0; col--) {
00932       
00933       c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
00934       c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
00935       c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
00936       cachep = & histogram[c0][c1][c2];
00937       
00938       
00939       if (*cachep == 0)
00940         fill_inverse_cmap(cinfo, c0,c1,c2);
00941       
00942       *outptr++ = (JSAMPLE) (*cachep - 1);
00943     }
00944   }
00945 }
00946 
00947 
00948 METHODDEF(void)
00949 pass2_fs_dither (j_decompress_ptr cinfo,
00950                  JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
00951 
00952 {
00953   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
00954   hist3d histogram = cquantize->histogram;
00955   register LOCFSERROR cur0, cur1, cur2; 
00956   LOCFSERROR belowerr0, belowerr1, belowerr2; 
00957   LOCFSERROR bpreverr0, bpreverr1, bpreverr2; 
00958   register FSERRPTR errorptr;   
00959   JSAMPROW inptr;               
00960   JSAMPROW outptr;              
00961   histptr cachep;
00962   int dir;                      
00963   int dir3;                     
00964   int row;
00965   JDIMENSION col;
00966   JDIMENSION width = cinfo->output_width;
00967   JSAMPLE *range_limit = cinfo->sample_range_limit;
00968   int *error_limit = cquantize->error_limiter;
00969   JSAMPROW colormap0 = cinfo->colormap[0];
00970   JSAMPROW colormap1 = cinfo->colormap[1];
00971   JSAMPROW colormap2 = cinfo->colormap[2];
00972   SHIFT_TEMPS
00973 
00974   for (row = 0; row < num_rows; row++) {
00975     inptr = input_buf[row];
00976     outptr = output_buf[row];
00977     if (cquantize->on_odd_row) {
00978       
00979       inptr += (width-1) * 3;   
00980       outptr += width-1;
00981       dir = -1;
00982       dir3 = -3;
00983       errorptr = cquantize->fserrors + (width+1)*3; 
00984       cquantize->on_odd_row = FALSE; 
00985     } else {
00986       
00987       dir = 1;
00988       dir3 = 3;
00989       errorptr = cquantize->fserrors; 
00990       cquantize->on_odd_row = TRUE; 
00991     }
00992     
00993     cur0 = cur1 = cur2 = 0;
00994     
00995     belowerr0 = belowerr1 = belowerr2 = 0;
00996     bpreverr0 = bpreverr1 = bpreverr2 = 0;
00997 
00998     for (col = width; col > 0; col--) {
00999       
01000 
01001 
01002 
01003 
01004 
01005 
01006 
01007       cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4);
01008       cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4);
01009       cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4);
01010       
01011 
01012 
01013       cur0 = error_limit[cur0];
01014       cur1 = error_limit[cur1];
01015       cur2 = error_limit[cur2];
01016       
01017 
01018 
01019 
01020       cur0 += GETJSAMPLE(inptr[0]);
01021       cur1 += GETJSAMPLE(inptr[1]);
01022       cur2 += GETJSAMPLE(inptr[2]);
01023       cur0 = GETJSAMPLE(range_limit[cur0]);
01024       cur1 = GETJSAMPLE(range_limit[cur1]);
01025       cur2 = GETJSAMPLE(range_limit[cur2]);
01026       
01027       cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT];
01028       
01029       
01030       if (*cachep == 0)
01031         fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT);
01032       
01033       { register int pixcode = *cachep - 1;
01034         *outptr = (JSAMPLE) pixcode;
01035         
01036         cur0 -= GETJSAMPLE(colormap0[pixcode]);
01037         cur1 -= GETJSAMPLE(colormap1[pixcode]);
01038         cur2 -= GETJSAMPLE(colormap2[pixcode]);
01039       }
01040       
01041 
01042 
01043 
01044       { register LOCFSERROR bnexterr, delta;
01045 
01046         bnexterr = cur0;        
01047         delta = cur0 * 2;
01048         cur0 += delta;          
01049         errorptr[0] = (FSERROR) (bpreverr0 + cur0);
01050         cur0 += delta;          
01051         bpreverr0 = belowerr0 + cur0;
01052         belowerr0 = bnexterr;
01053         cur0 += delta;          
01054         bnexterr = cur1;        
01055         delta = cur1 * 2;
01056         cur1 += delta;          
01057         errorptr[1] = (FSERROR) (bpreverr1 + cur1);
01058         cur1 += delta;          
01059         bpreverr1 = belowerr1 + cur1;
01060         belowerr1 = bnexterr;
01061         cur1 += delta;          
01062         bnexterr = cur2;        
01063         delta = cur2 * 2;
01064         cur2 += delta;          
01065         errorptr[2] = (FSERROR) (bpreverr2 + cur2);
01066         cur2 += delta;          
01067         bpreverr2 = belowerr2 + cur2;
01068         belowerr2 = bnexterr;
01069         cur2 += delta;          
01070       }
01071       
01072 
01073 
01074 
01075       inptr += dir3;            
01076       outptr += dir;
01077       errorptr += dir3;         
01078     }
01079     
01080 
01081 
01082 
01083     errorptr[0] = (FSERROR) bpreverr0; 
01084     errorptr[1] = (FSERROR) bpreverr1;
01085     errorptr[2] = (FSERROR) bpreverr2;
01086   }
01087 }
01088 
01089 
01090 
01091 
01092 
01093 
01094 
01095 
01096 
01097 
01098 
01099 
01100 
01101 
01102 
01103 
01104 
01105 
01106 
01107 LOCAL(void)
01108 init_error_limit (j_decompress_ptr cinfo)
01109 
01110 {
01111   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
01112   int * table;
01113   int in, out;
01114 
01115   table = (int *) (*cinfo->mem->alloc_small)
01116     ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int));
01117   table += MAXJSAMPLE;          
01118   cquantize->error_limiter = table;
01119 
01120 #define STEPSIZE ((MAXJSAMPLE+1)/16)
01121   
01122   out = 0;
01123   for (in = 0; in < STEPSIZE; in++, out++) {
01124     table[in] = out; table[-in] = -out;
01125   }
01126   
01127   for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) {
01128     table[in] = out; table[-in] = -out;
01129   }
01130   
01131   for (; in <= MAXJSAMPLE; in++) {
01132     table[in] = out; table[-in] = -out;
01133   }
01134 #undef STEPSIZE
01135 }
01136 
01137 
01138 
01139 
01140 
01141 
01142 METHODDEF(void)
01143 finish_pass1 (j_decompress_ptr cinfo)
01144 {
01145   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
01146 
01147   
01148   cinfo->colormap = cquantize->sv_colormap;
01149   select_colors(cinfo, cquantize->desired);
01150   
01151   cquantize->needs_zeroed = TRUE;
01152 }
01153 
01154 
01155 METHODDEF(void)
01156 finish_pass2 (j_decompress_ptr cinfo)
01157 {
01158   
01159 }
01160 
01161 
01162 
01163 
01164 
01165 
01166 METHODDEF(void)
01167 start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
01168 {
01169   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
01170   hist3d histogram = cquantize->histogram;
01171   int i;
01172 
01173   
01174   
01175   if (cinfo->dither_mode != JDITHER_NONE)
01176     cinfo->dither_mode = JDITHER_FS;
01177 
01178   if (is_pre_scan) {
01179     
01180     cquantize->pub.color_quantize = prescan_quantize;
01181     cquantize->pub.finish_pass = finish_pass1;
01182     cquantize->needs_zeroed = TRUE; 
01183   } else {
01184     
01185     if (cinfo->dither_mode == JDITHER_FS)
01186       cquantize->pub.color_quantize = pass2_fs_dither;
01187     else
01188       cquantize->pub.color_quantize = pass2_no_dither;
01189     cquantize->pub.finish_pass = finish_pass2;
01190 
01191     
01192     i = cinfo->actual_number_of_colors;
01193     if (i < 1)
01194       ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1);
01195     if (i > MAXNUMCOLORS)
01196       ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
01197 
01198     if (cinfo->dither_mode == JDITHER_FS) {
01199       size_t arraysize = (size_t) ((cinfo->output_width + 2) *
01200                                    (3 * SIZEOF(FSERROR)));
01201       
01202       if (cquantize->fserrors == NULL)
01203         cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
01204           ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
01205       
01206       jzero_far((void FAR *) cquantize->fserrors, arraysize);
01207       
01208       if (cquantize->error_limiter == NULL)
01209         init_error_limit(cinfo);
01210       cquantize->on_odd_row = FALSE;
01211     }
01212 
01213   }
01214   
01215   if (cquantize->needs_zeroed) {
01216     for (i = 0; i < HIST_C0_ELEMS; i++) {
01217       jzero_far((void FAR *) histogram[i],
01218                 HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
01219     }
01220     cquantize->needs_zeroed = FALSE;
01221   }
01222 }
01223 
01224 
01225 
01226 
01227 
01228 
01229 METHODDEF(void)
01230 new_color_map_2_quant (j_decompress_ptr cinfo)
01231 {
01232   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
01233 
01234   
01235   cquantize->needs_zeroed = TRUE;
01236 }
01237 
01238 
01239 
01240 
01241 
01242 
01243 GLOBAL(void)
01244 jinit_2pass_quantizer (j_decompress_ptr cinfo)
01245 {
01246   my_cquantize_ptr cquantize;
01247   int i;
01248 
01249   cquantize = (my_cquantize_ptr)
01250     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
01251                                 SIZEOF(my_cquantizer));
01252   cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
01253   cquantize->pub.start_pass = start_pass_2_quant;
01254   cquantize->pub.new_color_map = new_color_map_2_quant;
01255   cquantize->fserrors = NULL;   
01256   cquantize->error_limiter = NULL;
01257 
01258   
01259   if (cinfo->out_color_components != 3)
01260     ERREXIT(cinfo, JERR_NOTIMPL);
01261 
01262   
01263   cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small)
01264     ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d));
01265   for (i = 0; i < HIST_C0_ELEMS; i++) {
01266     cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large)
01267       ((j_common_ptr) cinfo, JPOOL_IMAGE,
01268        HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
01269   }
01270   cquantize->needs_zeroed = TRUE; 
01271 
01272   
01273 
01274 
01275 
01276   if (cinfo->enable_2pass_quant) {
01277     
01278     int desired = cinfo->desired_number_of_colors;
01279     
01280     if (desired < 8)
01281       ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
01282     
01283     if (desired > MAXNUMCOLORS)
01284       ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
01285     cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
01286       ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3);
01287     cquantize->desired = desired;
01288   } else
01289     cquantize->sv_colormap = NULL;
01290 
01291   
01292   
01293   if (cinfo->dither_mode != JDITHER_NONE)
01294     cinfo->dither_mode = JDITHER_FS;
01295 
01296   
01297 
01298 
01299 
01300 
01301   if (cinfo->dither_mode == JDITHER_FS) {
01302     cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
01303       ((j_common_ptr) cinfo, JPOOL_IMAGE,
01304        (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))));
01305     
01306     init_error_limit(cinfo);
01307   }
01308 }
01309 
01310 #endif