#include "wx/image.h"
#include "wx/quantize.h"
+#ifdef __WXMSW__
+#include <windows.h>
+#endif
+
#include <stdlib.h>
#include <string.h>
+#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
* 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
* 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
#define C2_SCALE B_SCALE
#endif
+#endif
/*
* First we have the histogram data structure and routines for creating it.
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]
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;
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;
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++) {
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++)
/* 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; }
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.
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];
}
}
}
-
+
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);
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
}
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 */
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.
*/
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];
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;
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;
}
/* 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;
/* 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;
}
}
memset((void *) histogram[i], 0,
HIST_C1_ELEMS*HIST_C2_ELEMS * sizeof(histcell));
}
- cquantize->needs_zeroed = false;
+ cquantize->needs_zeroed = FALSE;
}
}
my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
/* Reset the inverse color map */
- cquantize->needs_zeroed = true;
+ cquantize->needs_zeroed = TRUE;
}
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
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.
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);
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();
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)
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;
+}
+