X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3f4fc7967b595ea8257696baff78e1866511223d..4f13428c4f852674c8f8fc99af26d9486bf907db:/src/common/quantize.cpp diff --git a/src/common/quantize.cpp b/src/common/quantize.cpp index 5f579ba9ef..cb30f64599 100644 --- a/src/common/quantize.cpp +++ b/src/common/quantize.cpp @@ -1,12 +1,12 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: quantize.cpp +// Name: src/common/quantize.cpp // Purpose: wxQuantize implementation // Author: Julian Smart // Modified by: // Created: 22/6/2000 // RCS-ID: $Id$ // Copyright: (c) Thomas G. Lane, Vaclav Slavik, Julian Smart -// Licence: wxWindows licence + JPEG library licence +// Licence: wxWindows licence + JPEG library licence ///////////////////////////////////////////////////////////////////////////// /* @@ -30,10 +30,6 @@ /* modified by Vaclav Slavik for use as jpeglib-independent module */ -#ifdef __GNUG__ -#pragma implementation "quantize.h" -#endif - // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" @@ -41,19 +37,31 @@ #pragma hdrstop #endif +#if wxUSE_IMAGE + +#include "wx/quantize.h" + #ifndef WX_PRECOMP -#include "wx/wx.h" + #include "wx/palette.h" + #include "wx/image.h" #endif -#include "wx/image.h" -#include "wx/quantize.h" +#ifdef __WXMSW__ + #include "wx/msw/private.h" +#endif #include #include +#if defined(__OS2__) +#define RGB_RED_OS2 0 +#define RGB_GREEN_OS2 1 +#define RGB_BLUE_OS2 2 +#else #define RGB_RED 0 #define RGB_GREEN 1 #define RGB_BLUE 2 +#endif #define RGB_PIXELSIZE 3 #define MAXJSAMPLE 255 @@ -65,7 +73,9 @@ typedef unsigned short UINT16; typedef signed short INT16; +#if !(defined(__WATCOMC__) && (defined(__WXMSW__) || defined(__WXMOTIF__))) typedef signed int INT32; +#endif typedef unsigned char JSAMPLE; typedef JSAMPLE *JSAMPROW; @@ -81,7 +91,23 @@ typedef struct { JSAMPLE *sample_range_limit, *srl_orig; } j_decompress; +#if defined(__WINDOWS__) && !defined(__WXMICROWIN__) + #define JMETHOD(type,methodname,arglist) type (__cdecl methodname) arglist +#else + #define JMETHOD(type,methodname,arglist) type (methodname) arglist +#endif + typedef j_decompress *j_decompress_ptr; +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, bool is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + /* @@ -101,7 +127,7 @@ typedef j_decompress *j_decompress_ptr; * color space, and repeatedly splits the "largest" remaining box until we * have as many boxes as desired colors. Then the mean color in each * remaining box becomes one of the possible output colors. - * + * * The second pass over the image maps each input pixel to the closest output * color (optionally after applying a Floyd-Steinberg dithering correction). * This mapping is logically trivial, but making it go fast enough requires @@ -130,9 +156,9 @@ typedef j_decompress *j_decompress_ptr; * probably need to change these scale factors. */ -#define R_SCALE 2 /* scale R distances by this much */ -#define G_SCALE 3 /* scale G distances by this much */ -#define B_SCALE 1 /* and B by this much */ +#define R_SCALE 2 /* scale R distances by this much */ +#define G_SCALE 3 /* scale G distances by this much */ +#define B_SCALE 1 /* and B by this much */ /* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B @@ -141,6 +167,26 @@ typedef j_decompress *j_decompress_ptr; * you'll probably want to tweak the histogram sizes too. */ +#if defined(__OS2__) + +#if RGB_RED_OS2 == 0 +#define C0_SCALE R_SCALE +#endif +#if RGB_BLUE_OS2 == 0 +#define C0_SCALE B_SCALE +#endif +#if RGB_GREEN_OS2 == 1 +#define C1_SCALE G_SCALE +#endif +#if RGB_RED_OS2 == 2 +#define C2_SCALE R_SCALE +#endif +#if RGB_BLUE_OS2 == 2 +#define C2_SCALE B_SCALE +#endif + +#else + #if RGB_RED == 0 #define C0_SCALE R_SCALE #endif @@ -157,6 +203,7 @@ typedef j_decompress *j_decompress_ptr; #define C2_SCALE B_SCALE #endif +#endif /* * First we have the histogram data structure and routines for creating it. @@ -189,9 +236,9 @@ typedef j_decompress *j_decompress_ptr; /* These will do the right thing for either R,G,B or B,G,R color order, * but you may not like the results for other color orders. */ -#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ -#define HIST_C1_BITS 6 /* bits of precision in G histogram */ -#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ +#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ /* Number of elements along histogram axes. */ #define HIST_C0_ELEMS (1<cquantize; register JSAMPROW ptr; @@ -301,13 +348,13 @@ prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (row = 0; row < num_rows; row++) { ptr = input_buf[row]; for (col = width; col > 0; col--) { - + { - + /* get pixel value and index into the histogram */ histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] - [GETJSAMPLE(ptr[1]) >> C1_SHIFT] - [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; + [GETJSAMPLE(ptr[1]) >> C1_SHIFT] + [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; /* increment, check for overflow and undo increment if so. */ if (++(*histp) <= 0) (*histp)--; @@ -348,7 +395,7 @@ find_biggest_color_pop (boxptr boxlist, int numboxes) register int i; register long maxc = 0; boxptr which = NULL; - + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->colorcount > maxc && boxp->volume > 0) { which = boxp; @@ -368,7 +415,7 @@ find_biggest_volume (boxptr boxlist, int numboxes) register int i; register INT32 maxv = 0; boxptr which = NULL; - + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->volume > maxv) { which = boxp; @@ -391,75 +438,75 @@ update_box (j_decompress_ptr cinfo, boxptr boxp) int c0min,c0max,c1min,c1max,c2min,c2max; INT32 dist0,dist1,dist2; long ccount; - + c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; - + if (c0max > c0min) for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c0min = c0min = c0; - goto have_c0min; - } + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } } have_c0min: if (c0max > c0min) for (c0 = c0max; c0 >= c0min; c0--) for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c0max = c0max = c0; - goto have_c0max; - } + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } } have_c0max: if (c1max > c1min) for (c1 = c1min; c1 <= c1max; c1++) for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c1min = c1min = c1; - goto have_c1min; - } + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } } have_c1min: if (c1max > c1min) for (c1 = c1max; c1 >= c1min; c1--) for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c1max = c1max = c1; - goto have_c1max; - } + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } } have_c1max: if (c2max > c2min) for (c2 = c2min; c2 <= c2max; c2++) for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1min][c2]; - for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) - if (*histp != 0) { - boxp->c2min = c2min = c2; - goto have_c2min; - } + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } } have_c2min: if (c2max > c2min) for (c2 = c2max; c2 >= c2min; c2--) for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1min][c2]; - for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) - if (*histp != 0) { - boxp->c2max = c2max = c2; - goto have_c2max; - } + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } } have_c2max: @@ -475,16 +522,16 @@ update_box (j_decompress_ptr cinfo, boxptr boxp) dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; - + /* Now scan remaining volume of box and compute population */ ccount = 0; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++, histp++) - if (*histp != 0) { - ccount++; - } + if (*histp != 0) { + ccount++; + } } boxp->colorcount = ccount; } @@ -492,7 +539,7 @@ update_box (j_decompress_ptr cinfo, boxptr boxp) int median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, - int desired_colors) + int desired_colors) /* Repeatedly select and split the largest box until we have enough boxes */ { int n,lb; @@ -503,14 +550,14 @@ median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, /* Select box to split. * Current algorithm: by population for first half, then by volume. */ - if (numboxes*2 <= desired_colors) { + if ((numboxes*2) <= desired_colors) { b1 = find_biggest_color_pop(boxlist, numboxes); } else { b1 = find_biggest_volume(boxlist, numboxes); } - if (b1 == NULL) /* no splittable boxes left! */ + if (b1 == NULL) /* no splittable boxes left! */ break; - b2 = &boxlist[numboxes]; /* where new box will go */ + b2 = &boxlist[numboxes]; /* where new box will go */ /* Copy the color bounds to the new box. */ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; @@ -524,6 +571,20 @@ median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, /* We want to break any ties in favor of green, then red, blue last. * This code does the right thing for R,G,B or B,G,R color orders only. */ +#if defined(__VISAGECPP__) + +#if RGB_RED_OS2 == 0 + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } +#else + cmax = c1; n = 1; + if (c2 > cmax) { cmax = c2; n = 2; } + if (c0 > cmax) { n = 0; } +#endif + +#else + #if RGB_RED == 0 cmax = c1; n = 1; if (c0 > cmax) { cmax = c0; n = 0; } @@ -532,6 +593,8 @@ median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, cmax = c1; n = 1; if (c2 > cmax) { cmax = c2; n = 2; } if (c0 > cmax) { n = 0; } +#endif + #endif /* Choose split point along selected axis, and update box bounds. * Current algorithm: split at halfway point. @@ -581,24 +644,24 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) long c0total = 0; long c1total = 0; long c2total = 0; - + c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; - + for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) { - if ((count = *histp++) != 0) { - total += count; - c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; - c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; - c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; - } + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } } } - + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); @@ -631,7 +694,7 @@ select_colors (j_decompress_ptr cinfo, int desired_colors) for (i = 0; i < numboxes; i++) compute_color(cinfo, & boxlist[i], i); cinfo->actual_number_of_colors = numboxes; - + free(boxlist); //FIXME?? I don't know if this is correct - VS } @@ -714,7 +777,7 @@ select_colors (j_decompress_ptr cinfo, int desired_colors) static int find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - JSAMPLE colorlist[]) + JSAMPLE colorlist[]) /* Locate the colormap entries close enough to an update box to be candidates * for the nearest entry to some cell(s) in the update box. The update box * is specified by the center coordinates of its first cell. The number of @@ -729,7 +792,7 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, int centerc0, centerc1, centerc2; int i, x, ncolors; INT32 minmaxdist, min_dist, max_dist, tdist; - INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ + INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ /* Compute true coordinates of update box's upper corner and center. * Actually we compute the coordinates of the center of the upper-corner @@ -771,11 +834,11 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, /* within cell range so no contribution to min_dist */ min_dist = 0; if (x <= centerc0) { - tdist = (x - maxc0) * C0_SCALE; - max_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; } else { - tdist = (x - minc0) * C0_SCALE; - max_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; } } @@ -793,11 +856,11 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, } else { /* within cell range so no contribution to min_dist */ if (x <= centerc1) { - tdist = (x - maxc1) * C1_SCALE; - max_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; } else { - tdist = (x - minc1) * C1_SCALE; - max_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; } } @@ -815,15 +878,15 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, } else { /* within cell range so no contribution to min_dist */ if (x <= centerc2) { - tdist = (x - maxc2) * C2_SCALE; - max_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; } else { - tdist = (x - minc2) * C2_SCALE; - max_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; } } - mindist[i] = min_dist; /* save away the results */ + mindist[i] = min_dist; /* save away the results */ if (max_dist < minmaxdist) minmaxdist = max_dist; } @@ -843,7 +906,7 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, static void find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) + int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) /* Find the closest colormap entry for each cell in the update box, * given the list of candidate colors prepared by find_nearby_colors. * Return the indexes of the closest entries in the bestcolor[] array. @@ -853,13 +916,13 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, { int ic0, ic1, ic2; int i, icolor; - register INT32 * bptr; /* pointer into bestdist[] array */ - JSAMPLE * cptr; /* pointer into bestcolor[] array */ - INT32 dist0, dist1; /* initial distance values */ - register INT32 dist2; /* current distance in inner loop */ - INT32 xx0, xx1; /* distance increments */ + register INT32 * bptr; /* pointer into bestdist[] array */ + JSAMPLE * cptr; /* pointer into bestcolor[] array */ + INT32 dist0, dist1; /* initial distance values */ + register INT32 dist2; /* current distance in inner loop */ + INT32 xx0, xx1; /* distance increments */ register INT32 xx2; - INT32 inc0, inc1, inc2; /* initial values for increments */ + INT32 inc0, inc1, inc2; /* initial values for increments */ /* This array holds the distance to the nearest-so-far color for each cell */ INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; @@ -867,17 +930,17 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, bptr = bestdist; for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) *bptr++ = 0x7FFFFFFFL; - + /* For each color selected by find_nearby_colors, * compute its distance to the center of each cell in the box. * If that's less than best-so-far, update best distance and color number. */ - + /* Nominal steps between cell centers ("x" in Thomas article) */ #define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) #define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) #define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) - + for (i = 0; i < numcolors; i++) { icolor = GETJSAMPLE(colorlist[i]); /* Compute (square of) distance from minc0/c1/c2 to this color */ @@ -899,20 +962,20 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, dist1 = dist0; xx1 = inc1; for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { - dist2 = dist1; - xx2 = inc2; - for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { - if (dist2 < *bptr) { - *bptr = dist2; - *cptr = (JSAMPLE) icolor; - } - dist2 += xx2; - xx2 += 2 * STEP_C2 * STEP_C2; - bptr++; - cptr++; - } - dist1 += xx1; - xx1 += 2 * STEP_C1 * STEP_C1; + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; } dist0 += xx0; xx0 += 2 * STEP_C0 * STEP_C0; @@ -929,13 +992,13 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; - int minc0, minc1, minc2; /* lower left corner of update box */ + int minc0, minc1, minc2; /* lower left corner of update box */ int ic0, ic1, ic2; - register JSAMPLE * cptr; /* pointer into bestcolor[] array */ - register histptr cachep; /* pointer into main cache array */ + register JSAMPLE * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ /* This array lists the candidate colormap indexes. */ JSAMPLE colorlist[MAXNUMCOLORS]; - int numcolors; /* number of candidate colors */ + int numcolors; /* number of candidate colors */ /* This array holds the actually closest colormap index for each cell. */ JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; @@ -951,7 +1014,7 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); - + /* Determine which colormap entries are close enough to be candidates * for the nearest entry to some cell in the update box. */ @@ -959,10 +1022,10 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) /* Determine the actually nearest colors. */ find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, - bestcolor); + bestcolor); /* Save the best color numbers (plus 1) in the main cache array */ - c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ c1 <<= BOX_C1_LOG; c2 <<= BOX_C2_LOG; cptr = bestcolor; @@ -970,7 +1033,7 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { cachep = & histogram[c0+ic0][c1+ic1][c2]; for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { - *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); + *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); } } } @@ -983,7 +1046,7 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) void pass2_no_dither (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; @@ -1007,7 +1070,7 @@ pass2_no_dither (j_decompress_ptr cinfo, /* If we have not seen this color before, find nearest colormap entry */ /* and update the cache */ if (*cachep == 0) - fill_inverse_cmap(cinfo, c0,c1,c2); + fill_inverse_cmap(cinfo, c0,c1,c2); /* Now emit the colormap index for this cell */ *outptr++ = (JSAMPLE) (*cachep - 1); } @@ -1017,20 +1080,20 @@ pass2_no_dither (j_decompress_ptr cinfo, void pass2_fs_dither (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; - register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ - register FSERRPTR errorptr; /* => fserrors[] at column before current */ - JSAMPROW inptr; /* => current input pixel */ - JSAMPROW outptr; /* => current output pixel */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW inptr; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ histptr cachep; - int dir; /* +1 or -1 depending on direction */ - int dir3; /* 3*dir, for advancing inptr & errorptr */ + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing inptr & errorptr */ int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; @@ -1039,14 +1102,14 @@ pass2_fs_dither (j_decompress_ptr cinfo, JSAMPROW colormap0 = cinfo->colormap[0]; JSAMPROW colormap1 = cinfo->colormap[1]; JSAMPROW colormap2 = cinfo->colormap[2]; - + for (row = 0; row < num_rows; row++) { inptr = input_buf[row]; outptr = output_buf[row]; if (cquantize->on_odd_row) { /* work right to left in this row */ - inptr += (width-1) * 3; /* so point to rightmost pixel */ + inptr += (width-1) * 3; /* so point to rightmost pixel */ outptr += width-1; dir = -1; dir3 = -3; @@ -1098,14 +1161,14 @@ pass2_fs_dither (j_decompress_ptr cinfo, /* If we have not seen this color before, find nearest colormap */ /* entry and update the cache */ if (*cachep == 0) - fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); + fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); /* Now emit the colormap index for this cell */ { register int pixcode = *cachep - 1; - *outptr = (JSAMPLE) pixcode; - /* Compute representation error for this pixel */ - cur0 -= GETJSAMPLE(colormap0[pixcode]); - cur1 -= GETJSAMPLE(colormap1[pixcode]); - cur2 -= GETJSAMPLE(colormap2[pixcode]); + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); } /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the @@ -1113,38 +1176,38 @@ pass2_fs_dither (j_decompress_ptr cinfo, */ { register LOCFSERROR bnexterr, delta; - bnexterr = cur0; /* Process component 0 */ - delta = cur0 * 2; - cur0 += delta; /* form error * 3 */ - errorptr[0] = (FSERROR) (bpreverr0 + cur0); - cur0 += delta; /* form error * 5 */ - bpreverr0 = belowerr0 + cur0; - belowerr0 = bnexterr; - cur0 += delta; /* form error * 7 */ - bnexterr = cur1; /* Process component 1 */ - delta = cur1 * 2; - cur1 += delta; /* form error * 3 */ - errorptr[1] = (FSERROR) (bpreverr1 + cur1); - cur1 += delta; /* form error * 5 */ - bpreverr1 = belowerr1 + cur1; - belowerr1 = bnexterr; - cur1 += delta; /* form error * 7 */ - bnexterr = cur2; /* Process component 2 */ - delta = cur2 * 2; - cur2 += delta; /* form error * 3 */ - errorptr[2] = (FSERROR) (bpreverr2 + cur2); - cur2 += delta; /* form error * 5 */ - bpreverr2 = belowerr2 + cur2; - belowerr2 = bnexterr; - cur2 += delta; /* form error * 7 */ + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ } /* At this point curN contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. */ - inptr += dir3; /* Advance pixel pointers to next column */ + inptr += dir3; /* Advance pixel pointers to next column */ outptr += dir; - errorptr += dir3; /* advance errorptr to current column */ + errorptr += dir3; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error values into the * final fserrors[] entry. Note we need not unload belowerrN because @@ -1183,7 +1246,7 @@ init_error_limit (j_decompress_ptr cinfo) int in, out; table = (int *) malloc((MAXJSAMPLE*2+1) * sizeof(int)); - table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ cquantize->error_limiter = table; #define STEPSIZE ((MAXJSAMPLE+1)/16) @@ -1222,7 +1285,7 @@ finish_pass1 (j_decompress_ptr cinfo) void -finish_pass2 (j_decompress_ptr cinfo) +finish_pass2 (j_decompress_ptr WXUNUSED(cinfo)) { /* no work */ } @@ -1237,7 +1300,6 @@ start_pass_2_quant (j_decompress_ptr cinfo, bool is_pre_scan) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; - int i; if (is_pre_scan) { /* Set up method pointers */ @@ -1249,29 +1311,26 @@ start_pass_2_quant (j_decompress_ptr cinfo, bool is_pre_scan) cquantize->pub.color_quantize = pass2_fs_dither; cquantize->pub.finish_pass = finish_pass2; - /* Make sure color count is acceptable */ - i = cinfo->actual_number_of_colors; - { size_t arraysize = (size_t) ((cinfo->output_width + 2) * - (3 * sizeof(FSERROR))); + (3 * sizeof(FSERROR))); /* Allocate Floyd-Steinberg workspace if we didn't already. */ if (cquantize->fserrors == NULL) - cquantize->fserrors = (INT16*) malloc(arraysize); + cquantize->fserrors = (INT16*) malloc(arraysize); /* Initialize the propagated errors to zero. */ memset((void *) cquantize->fserrors, 0, arraysize); /* Make the error-limit table if we didn't already. */ if (cquantize->error_limiter == NULL) - init_error_limit(cinfo); + init_error_limit(cinfo); cquantize->on_odd_row = false; } } /* Zero the histogram or inverse color map, if necessary */ if (cquantize->needs_zeroed) { - for (i = 0; i < HIST_C0_ELEMS; i++) { + for (int i = 0; i < HIST_C0_ELEMS; i++) { memset((void *) histogram[i], 0, - HIST_C1_ELEMS*HIST_C2_ELEMS * sizeof(histcell)); + HIST_C1_ELEMS*HIST_C2_ELEMS * sizeof(histcell)); } cquantize->needs_zeroed = false; } @@ -1303,10 +1362,10 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo) int i; cquantize = (my_cquantize_ptr) malloc(sizeof(my_cquantizer)); - cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cinfo->cquantize = (jpeg_color_quantizer *) cquantize; cquantize->pub.start_pass = start_pass_2_quant; cquantize->pub.new_color_map = new_color_map_2_quant; - cquantize->fserrors = NULL; /* flag optional arrays not allocated */ + cquantize->fserrors = NULL; /* flag optional arrays not allocated */ cquantize->error_limiter = NULL; @@ -1329,9 +1388,9 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo) cquantize->sv_colormap[0] = (JSAMPROW) malloc(sizeof(JSAMPLE) * desired); cquantize->sv_colormap[1] = (JSAMPROW) malloc(sizeof(JSAMPLE) * desired); cquantize->sv_colormap[2] = (JSAMPROW) malloc(sizeof(JSAMPLE) * desired); - + cquantize->desired = desired; - } + } /* Allocate Floyd-Steinberg workspace if necessary. * This isn't really needed until pass 2, but again it is storage. @@ -1364,22 +1423,22 @@ prepare_range_limit_table (j_decompress_ptr cinfo) table = (JSAMPLE *) malloc((5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * sizeof(JSAMPLE)); cinfo->srl_orig = table; - table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ cinfo->sample_range_limit = table; /* First segment of "simple" table: limit[x] = 0 for x < 0 */ memset(table - (MAXJSAMPLE+1), 0, (MAXJSAMPLE+1) * sizeof(JSAMPLE)); /* Main part of "simple" table: limit[x] = x */ for (i = 0; i <= MAXJSAMPLE; i++) table[i] = (JSAMPLE) i; - table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ /* End of simple table, rest of first half of post-IDCT table */ for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) table[i] = MAXJSAMPLE; /* Second half of post-IDCT table */ memset(table + (2 * (MAXJSAMPLE+1)), 0, - (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * sizeof(JSAMPLE)); + (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * sizeof(JSAMPLE)); memcpy(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), - cinfo->sample_range_limit, CENTERJSAMPLE * sizeof(JSAMPLE)); + cinfo->sample_range_limit, CENTERJSAMPLE * sizeof(JSAMPLE)); } @@ -1437,15 +1496,17 @@ void wxQuantize::DoQuantize(unsigned w, unsigned h, unsigned char **in_rows, uns // TODO: somehow make use of the Windows system colours, rather than ignoring them for the // purposes of quantization. -bool wxQuantize::Quantize(const wxImage& src, wxImage& dest, wxPalette** pPalette, int desiredNoColours, - unsigned char** eightBitData, int flags) +bool wxQuantize::Quantize(const wxImage& src, wxImage& dest, + wxPalette** pPalette, + int desiredNoColours, + unsigned char** eightBitData, + int flags) -{ +{ int i; - int w = src.GetWidth(); - int h = src.GetHeight(); int windowsSystemColourCount = 20; + int paletteShift = 0; // Shift the palette up by the number of Windows system colours, @@ -1460,8 +1521,9 @@ bool wxQuantize::Quantize(const wxImage& src, wxImage& dest, wxPalette** pPalett #endif // create rows info: + int h = src.GetHeight(); + int w = src.GetWidth(); unsigned char **rows = new unsigned char *[h]; - h = src.GetHeight(), w = src.GetWidth(); unsigned char *imgdt = src.GetData(); for (i = 0; i < h; i++) rows[i] = imgdt + 3/*RGB*/ * w * i; @@ -1473,13 +1535,13 @@ bool wxQuantize::Quantize(const wxImage& src, wxImage& dest, wxPalette** pPalett unsigned char **outrows = new unsigned char *[h]; for (i = 0; i < h; i++) outrows[i] = data8bit + w * i; - + //RGB->palette DoQuantize(w, h, rows, outrows, palette, desiredNoColours); - + delete[] rows; - delete[] outrows; - + delete[] outrows; + // palette->RGB(max.256) if (flags & wxQUANTIZE_FILL_DESTINATION_IMAGE) @@ -1505,7 +1567,7 @@ bool wxQuantize::Quantize(const wxImage& src, wxImage& dest, wxPalette** pPalett // We need to shift the palette entries up // to make room for the Windows system colours. for (i = 0; i < w * h; i++) - data8bit[i] = data8bit[i] + paletteShift; + data8bit[i] = (unsigned char)(data8bit[i] + paletteShift); } #endif *eightBitData = data8bit; @@ -1513,7 +1575,8 @@ bool wxQuantize::Quantize(const wxImage& src, wxImage& dest, wxPalette** pPalett else delete[] data8bit; - // Make a wxWindows palette +#if wxUSE_PALETTE + // Make a wxWidgets palette if (pPalette) { unsigned char* r = new unsigned char[256]; @@ -1558,7 +1621,34 @@ bool wxQuantize::Quantize(const wxImage& src, wxImage& dest, wxPalette** pPalett delete[] g; delete[] b; } - - return TRUE; +#endif // wxUSE_PALETTE + + return true; +} + +// This version sets a palette in the destination image so you don't +// have to manage it yourself. + +bool wxQuantize::Quantize(const wxImage& src, + wxImage& dest, + int desiredNoColours, + unsigned char** eightBitData, + int flags) +{ + wxPalette* palette = NULL; + if ( !Quantize(src, dest, & palette, desiredNoColours, eightBitData, flags) ) + return false; + +#if wxUSE_PALETTE + if (palette) + { + dest.SetPalette(* palette); + delete palette; + } +#endif // wxUSE_PALETTE + + return true; } +#endif + // wxUSE_IMAGE