The Independent JPEG Group's JPEG software v6

This commit is contained in:
Thomas G. Lane
1995-08-02 00:00:00 +00:00
committed by DRC
parent a8b67c4fbb
commit bc79e0680a
88 changed files with 9850 additions and 3723 deletions

139
jquant2.c
View File

@@ -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);
}
}