The Independent JPEG Group's JPEG software v6
diff --git a/jquant2.c b/jquant2.c
index 7984f58..2504398 100644
--- a/jquant2.c
+++ b/jquant2.c
@@ -1,7 +1,7 @@
/*
* jquant2.c
*
- * Copyright (C) 1991-1994, Thomas G. Lane.
+ * Copyright (C) 1991-1995, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
@@ -193,9 +193,15 @@
typedef struct {
struct jpeg_color_quantizer pub; /* public fields */
+ /* Space for the eventually created colormap is stashed here */
+ JSAMPARRAY sv_colormap; /* colormap allocated at init time */
+ int desired; /* desired # of colors = size of colormap */
+
/* Variables for accumulating image statistics */
hist3d histogram; /* pointer to the histogram */
+ boolean needs_zeroed; /* TRUE if next pass must zero histogram */
+
/* Variables for Floyd-Steinberg dithering */
FSERRPTR fserrors; /* accumulated errors */
boolean on_odd_row; /* flag to remember which row we are on */
@@ -530,17 +536,16 @@
LOCAL void
-select_colors (j_decompress_ptr cinfo)
+select_colors (j_decompress_ptr cinfo, int desired_colors)
/* Master routine for color selection */
{
boxptr boxlist;
int numboxes;
- int desired = cinfo->desired_number_of_colors;
int i;
/* Allocate workspace for box list */
boxlist = (boxptr) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, desired * SIZEOF(box));
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box));
/* Initialize one box containing whole space */
numboxes = 1;
boxlist[0].c0min = 0;
@@ -552,7 +557,7 @@
/* Shrink it to actually-used volume and set its statistics */
update_box(cinfo, & boxlist[0]);
/* Perform median-cut to produce final box list */
- numboxes = median_cut(cinfo, boxlist, numboxes, desired);
+ numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
/* Compute the representative color for each box, fill colormap */
for (i = 0; i < numboxes; i++)
compute_color(cinfo, & boxlist[i], i);
@@ -1137,8 +1142,13 @@
METHODDEF void
finish_pass1 (j_decompress_ptr cinfo)
{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
/* Select the representative colors and fill in cinfo->colormap */
- select_colors(cinfo);
+ cinfo->colormap = cquantize->sv_colormap;
+ select_colors(cinfo, cquantize->desired);
+ /* Force next pass to zero the color index table */
+ cquantize->needs_zeroed = TRUE;
}
@@ -1160,10 +1170,16 @@
hist3d histogram = cquantize->histogram;
int i;
+ /* Only F-S dithering or no dithering is supported. */
+ /* If user asks for ordered dither, give him F-S. */
+ if (cinfo->dither_mode != JDITHER_NONE)
+ cinfo->dither_mode = JDITHER_FS;
+
if (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 */
} else {
/* Set up method pointers */
if (cinfo->dither_mode == JDITHER_FS)
@@ -1171,16 +1187,56 @@
else
cquantize->pub.color_quantize = pass2_no_dither;
cquantize->pub.finish_pass = finish_pass2;
+
+ /* Make sure color count is acceptable */
+ i = cinfo->actual_number_of_colors;
+ if (i < 1)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1);
+ if (i > MAXNUMCOLORS)
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+
+ if (cinfo->dither_mode == JDITHER_FS) {
+ size_t arraysize = (size_t) ((cinfo->output_width + 2) *
+ (3 * SIZEOF(FSERROR)));
+ /* Allocate Floyd-Steinberg workspace if we didn't already. */
+ if (cquantize->fserrors == NULL)
+ cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ /* Initialize the propagated errors to zero. */
+ jzero_far((void FAR *) cquantize->fserrors, arraysize);
+ /* Make the error-limit table if we didn't already. */
+ if (cquantize->error_limiter == NULL)
+ init_error_limit(cinfo);
+ cquantize->on_odd_row = FALSE;
+ }
+
}
- /* Zero the histogram or inverse color map */
- for (i = 0; i < HIST_C0_ELEMS; i++) {
- jzero_far((void FAR *) histogram[i],
- HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+ /* Zero the histogram or inverse color map, if necessary */
+ if (cquantize->needs_zeroed) {
+ for (i = 0; i < HIST_C0_ELEMS; i++) {
+ jzero_far((void FAR *) histogram[i],
+ HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+ }
+ cquantize->needs_zeroed = FALSE;
}
}
/*
+ * Switch to a new external colormap between output passes.
+ */
+
+METHODDEF void
+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;
+}
+
+
+/*
* Module initialization routine for 2-pass color quantization.
*/
@@ -1195,26 +1251,14 @@
SIZEOF(my_cquantizer));
cinfo->cquantize = (struct 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->error_limiter = NULL;
/* Make sure jdmaster didn't give me a case I can't handle */
if (cinfo->out_color_components != 3)
ERREXIT(cinfo, JERR_NOTIMPL);
- /* Only F-S dithering or no dithering is supported. */
- /* If user asks for ordered dither, give him F-S. */
- if (cinfo->dither_mode != JDITHER_NONE)
- cinfo->dither_mode = JDITHER_FS;
-
- /* Make sure color count is acceptable */
- i = (cinfo->colormap != NULL) ? cinfo->actual_number_of_colors
- : cinfo->desired_number_of_colors;
- /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
- if (i < 8)
- ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
- /* Make sure colormap indexes can be represented by JSAMPLEs */
- if (i > MAXNUMCOLORS)
- ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
-
/* Allocate the histogram/inverse colormap storage */
cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small)
((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d));
@@ -1223,29 +1267,42 @@
((j_common_ptr) cinfo, JPOOL_IMAGE,
HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
}
+ cquantize->needs_zeroed = TRUE; /* histogram is garbage now */
- /* Allocate storage for the completed colormap,
- * unless it has been supplied by the application.
+ /* Allocate storage for the completed colormap, if required.
* We do this now since it is FAR storage and may affect
* the memory manager's space calculations.
*/
- if (cinfo->colormap == NULL) {
- cinfo->colormap = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) cinfo->desired_number_of_colors, (JDIMENSION) 3);
- }
+ if (cinfo->enable_2pass_quant) {
+ /* Make sure color count is acceptable */
+ int desired = cinfo->desired_number_of_colors;
+ /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
+ if (desired < 8)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
+ /* Make sure colormap indexes can be represented by JSAMPLEs */
+ if (desired > MAXNUMCOLORS)
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+ cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3);
+ cquantize->desired = desired;
+ } else
+ cquantize->sv_colormap = NULL;
- /* Allocate Floyd-Steinberg workspace if necessary. */
- /* This isn't needed until pass 2, but again it is FAR storage. */
+ /* Only F-S dithering or no dithering is supported. */
+ /* If user asks for ordered dither, give him F-S. */
+ if (cinfo->dither_mode != JDITHER_NONE)
+ cinfo->dither_mode = JDITHER_FS;
+
+ /* Allocate Floyd-Steinberg workspace if necessary.
+ * This isn't really needed until pass 2, but again it is FAR storage.
+ * Although we will cope with a later change in dither_mode,
+ * we do not promise to honor max_memory_to_use if dither_mode changes.
+ */
if (cinfo->dither_mode == JDITHER_FS) {
- size_t arraysize = (size_t) ((cinfo->output_width + 2) *
- (3 * SIZEOF(FSERROR)));
-
cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
- /* Initialize the propagated errors to zero. */
- jzero_far((void FAR *) cquantize->fserrors, arraysize);
- cquantize->on_odd_row = FALSE;
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))));
+ /* Might as well create the error-limiting table too. */
init_error_limit(cinfo);
}
}