X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3f4fc7967b595ea8257696baff78e1866511223d..03e11df5470fd64d9d9a669d0b50b84c2d714736:/src/common/quantize.cpp diff --git a/src/common/quantize.cpp b/src/common/quantize.cpp index 5f579ba9ef..b96e92e6de 100644 --- a/src/common/quantize.cpp +++ b/src/common/quantize.cpp @@ -48,12 +48,22 @@ #include "wx/image.h" #include "wx/quantize.h" +#ifdef __WXMSW__ +#include +#endif + #include #include +#if defined(__VISAGECPP__) +#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 @@ -101,7 +111,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 @@ -141,6 +151,26 @@ typedef j_decompress *j_decompress_ptr; * you'll probably want to tweak the histogram sizes too. */ +#if defined(__VISAGECPP__) + +#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 +187,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. @@ -301,9 +332,9 @@ 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] @@ -348,7 +379,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 +399,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,11 +422,11 @@ 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++) { @@ -475,7 +506,7 @@ 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++) @@ -524,6 +555,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 +577,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,11 +628,11 @@ 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]; @@ -598,7 +645,7 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) } } } - + 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 +678,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 } @@ -867,17 +914,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 */ @@ -951,7 +998,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. */ @@ -1039,7 +1086,7 @@ 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]; @@ -1051,13 +1098,13 @@ pass2_fs_dither (j_decompress_ptr cinfo, dir = -1; dir3 = -3; errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ - cquantize->on_odd_row = false; /* flip for next time */ + cquantize->on_odd_row = FALSE; /* flip for next time */ } else { /* work left to right in this row */ dir = 1; dir3 = 3; errorptr = cquantize->fserrors; /* => entry before first real column */ - cquantize->on_odd_row = true; /* flip for next time */ + cquantize->on_odd_row = TRUE; /* flip for next time */ } /* Preset error values: no error propagated to first pixel from left */ cur0 = cur1 = cur2 = 0; @@ -1217,7 +1264,7 @@ finish_pass1 (j_decompress_ptr cinfo) cinfo->colormap = cquantize->sv_colormap; select_colors(cinfo, cquantize->desired); /* Force next pass to zero the color index table */ - cquantize->needs_zeroed = true; + cquantize->needs_zeroed = TRUE; } @@ -1243,7 +1290,7 @@ start_pass_2_quant (j_decompress_ptr cinfo, bool is_pre_scan) /* Set up method pointers */ cquantize->pub.color_quantize = prescan_quantize; cquantize->pub.finish_pass = finish_pass1; - cquantize->needs_zeroed = true; /* Always zero histogram */ + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ } else { /* Set up method pointers */ cquantize->pub.color_quantize = pass2_fs_dither; @@ -1263,7 +1310,7 @@ start_pass_2_quant (j_decompress_ptr cinfo, bool is_pre_scan) /* Make the error-limit table if we didn't already. */ if (cquantize->error_limiter == NULL) init_error_limit(cinfo); - cquantize->on_odd_row = false; + cquantize->on_odd_row = FALSE; } } @@ -1273,7 +1320,7 @@ start_pass_2_quant (j_decompress_ptr cinfo, bool is_pre_scan) memset((void *) histogram[i], 0, HIST_C1_ELEMS*HIST_C2_ELEMS * sizeof(histcell)); } - cquantize->needs_zeroed = false; + cquantize->needs_zeroed = FALSE; } } @@ -1288,7 +1335,7 @@ new_color_map_2_quant (j_decompress_ptr cinfo) my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; /* Reset the inverse color map */ - cquantize->needs_zeroed = true; + cquantize->needs_zeroed = TRUE; } @@ -1315,7 +1362,7 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo) for (i = 0; i < HIST_C0_ELEMS; i++) { cquantize->histogram[i] = (hist2d) malloc(HIST_C1_ELEMS*HIST_C2_ELEMS * sizeof(histcell)); } - cquantize->needs_zeroed = true; /* histogram is garbage now */ + cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ /* Allocate storage for the completed colormap, if required. * We do this now since it is storage and may affect @@ -1329,9 +1376,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. @@ -1404,11 +1451,11 @@ void wxQuantize::DoQuantize(unsigned w, unsigned h, unsigned char **in_rows, uns cquantize = (my_cquantize_ptr) dec.cquantize; - cquantize->pub.start_pass(&dec, true); + cquantize->pub.start_pass(&dec, TRUE); cquantize->pub.color_quantize(&dec, in_rows, out_rows, h); cquantize->pub.finish_pass(&dec); - cquantize->pub.start_pass(&dec, false); + cquantize->pub.start_pass(&dec, FALSE); cquantize->pub.color_quantize(&dec, in_rows, out_rows, h); cquantize->pub.finish_pass(&dec); @@ -1440,7 +1487,7 @@ void wxQuantize::DoQuantize(unsigned w, unsigned h, unsigned char **in_rows, uns 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(); @@ -1473,13 +1520,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) @@ -1558,7 +1605,27 @@ bool wxQuantize::Quantize(const wxImage& src, wxImage& dest, wxPalette** pPalett delete[] g; delete[] b; } - + 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)) + { + if (palette) + { + dest.SetPalette(* palette); + delete palette; + } + return TRUE; + } + else + return FALSE; +} +