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