The Independent JPEG Group's JPEG software v6
This commit is contained in:
139
jquant2.c
139
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 FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */
|
||||
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 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
|
||||
|
||||
|
||||
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 @@ select_colors (j_decompress_ptr cinfo)
|
||||
/* 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 @@ init_error_limit (j_decompress_ptr cinfo)
|
||||
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 @@ start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
|
||||
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,15 +1187,55 @@ start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
|
||||
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 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo)
|
||||
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 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo)
|
||||
((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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user