Blame src/gd_topal.c

Packit ed3af9
/* TODO: oim and nim in the lower level functions;
Packit ed3af9
  correct use of stub (sigh). */
Packit ed3af9
Packit ed3af9
/* 2.0.12: a new adaptation from the same original, this time
Packit ed3af9
	by Barend Gehrels. My attempt to incorporate alpha channel
Packit ed3af9
	into the result worked poorly and degraded the quality of
Packit ed3af9
	palette conversion even when the source contained no
Packit ed3af9
	alpha channel data. This version does not attempt to produce
Packit ed3af9
	an output file with transparency in some of the palette
Packit ed3af9
	indexes, which, in practice, doesn't look so hot anyway. TBB */
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * gd_topal, adapted from jquant2.c
Packit ed3af9
 *
Packit ed3af9
 * Copyright (C) 1991-1996, Thomas G. Lane.
Packit ed3af9
 * This file is part of the Independent JPEG Group's software.
Packit ed3af9
 * For conditions of distribution and use, see the accompanying README file.
Packit ed3af9
 *
Packit ed3af9
 * This file contains 2-pass color quantization (color mapping) routines.
Packit ed3af9
 * These routines provide selection of a custom color map for an image,
Packit ed3af9
 * followed by mapping of the image to that color map, with optional
Packit ed3af9
 * Floyd-Steinberg dithering.
Packit ed3af9
 * It is also possible to use just the second pass to map to an arbitrary
Packit ed3af9
 * externally-given color map.
Packit ed3af9
 *
Packit ed3af9
 * Note: ordered dithering is not supported, since there isn't any fast
Packit ed3af9
 * way to compute intercolor distances; it's unclear that ordered dither's
Packit ed3af9
 * fundamental assumptions even hold with an irregularly spaced color map.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
/**
Packit ed3af9
 * File: Color Quantization
Packit ed3af9
 *
Packit ed3af9
 * Functions for truecolor to palette conversion
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * THOMAS BOUTELL & BAREND GEHRELS, february 2003
Packit ed3af9
 * adapted the code to work within gd rather than within libjpeg.
Packit ed3af9
 * If it is not working, it's not Thomas G. Lane's fault.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
#ifdef HAVE_CONFIG_H
Packit ed3af9
#include "config.h"
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#include <string.h>
Packit ed3af9
#include "gd.h"
Packit ed3af9
#include "gdhelpers.h"
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBIMAGEQUANT
Packit ed3af9
#include <libimagequant.h>
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
/* (Re)define some defines known by libjpeg */
Packit ed3af9
#define QUANT_2PASS_SUPPORTED
Packit ed3af9
Packit ed3af9
#define RGB_RED		0
Packit ed3af9
#define RGB_GREEN	1
Packit ed3af9
#define RGB_BLUE	2
Packit ed3af9
Packit ed3af9
#define JSAMPLE unsigned char
Packit ed3af9
#define MAXJSAMPLE (gdMaxColors-1)
Packit ed3af9
#define BITS_IN_JSAMPLE 8
Packit ed3af9
Packit ed3af9
#define JSAMPROW int*
Packit ed3af9
#define JDIMENSION int
Packit ed3af9
Packit ed3af9
#define METHODDEF(type) static type
Packit ed3af9
#define LOCAL(type)	static type
Packit ed3af9
Packit ed3af9
Packit ed3af9
/* We assume that right shift corresponds to signed division by 2 with
Packit ed3af9
 * rounding towards minus infinity.  This is correct for typical "arithmetic
Packit ed3af9
 * shift" instructions that shift in copies of the sign bit.  But some
Packit ed3af9
 * C compilers implement >> with an unsigned shift.  For these machines you
Packit ed3af9
 * must define RIGHT_SHIFT_IS_UNSIGNED.
Packit ed3af9
 * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
Packit ed3af9
 * It is only applied with constant shift counts.  SHIFT_TEMPS must be
Packit ed3af9
 * included in the variables of any routine using RIGHT_SHIFT.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
#ifdef RIGHT_SHIFT_IS_UNSIGNED
Packit ed3af9
#define SHIFT_TEMPS	INT32 shift_temp;
Packit ed3af9
#define RIGHT_SHIFT(x,shft)  \
Packit ed3af9
	((shift_temp = (x)) < 0 ? \
Packit ed3af9
	 (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
Packit ed3af9
	 (shift_temp >> (shft)))
Packit ed3af9
#else
Packit ed3af9
#define SHIFT_TEMPS
Packit ed3af9
#define RIGHT_SHIFT(x,shft)	((x) >> (shft))
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
Packit ed3af9
#define range_limit(x) { if(x<0) x=0; if (x>255) x=255; }
Packit ed3af9
Packit ed3af9
Packit ed3af9
#ifndef INT16
Packit ed3af9
#define INT16  short
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifndef UINT16
Packit ed3af9
#define UINT16 unsigned short
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifndef INT32
Packit ed3af9
#define INT32 int
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifndef FAR
Packit ed3af9
#define FAR
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
Packit ed3af9
Packit ed3af9
#ifndef boolean
Packit ed3af9
#define boolean int
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifndef TRUE
Packit ed3af9
#define TRUE 1
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifndef FALSE
Packit ed3af9
#define FALSE 0
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
Packit ed3af9
#define input_buf (oim->tpixels)
Packit ed3af9
#define output_buf (nim->pixels)
Packit ed3af9
Packit ed3af9
Packit ed3af9
#ifdef QUANT_2PASS_SUPPORTED
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * This module implements the well-known Heckbert paradigm for color
Packit ed3af9
 * quantization.  Most of the ideas used here can be traced back to
Packit ed3af9
 * Heckbert's seminal paper
Packit ed3af9
 *   Heckbert, Paul.  "Color Image Quantization for Frame Buffer Display",
Packit ed3af9
 *   Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304.
Packit ed3af9
 *
Packit ed3af9
 * In the first pass over the image, we accumulate a histogram showing the
Packit ed3af9
 * usage count of each possible color.  To keep the histogram to a reasonable
Packit ed3af9
 * size, we reduce the precision of the input; typical practice is to retain
Packit ed3af9
 * 5 or 6 bits per color, so that 8 or 4 different input values are counted
Packit ed3af9
 * in the same histogram cell.
Packit ed3af9
 *
Packit ed3af9
 * Next, the color-selection step begins with a box representing the whole
Packit ed3af9
 * color space, and repeatedly splits the "largest" remaining box until we
Packit ed3af9
 * have as many boxes as desired colors.  Then the mean color in each
Packit ed3af9
 * remaining box becomes one of the possible output colors.
Packit ed3af9
 *
Packit ed3af9
 * The second pass over the image maps each input pixel to the closest output
Packit ed3af9
 * color (optionally after applying a Floyd-Steinberg dithering correction).
Packit ed3af9
 * This mapping is logically trivial, but making it go fast enough requires
Packit ed3af9
 * considerable care.
Packit ed3af9
 *
Packit ed3af9
 * Heckbert-style quantizers vary a good deal in their policies for choosing
Packit ed3af9
 * the "largest" box and deciding where to cut it.  The particular policies
Packit ed3af9
 * used here have proved out well in experimental comparisons, but better ones
Packit ed3af9
 * may yet be found.
Packit ed3af9
 *
Packit ed3af9
 * In earlier versions of the IJG code, this module quantized in YCbCr color
Packit ed3af9
 * space, processing the raw upsampled data without a color conversion step.
Packit ed3af9
 * This allowed the color conversion math to be done only once per colormap
Packit ed3af9
 * entry, not once per pixel.  However, that optimization precluded other
Packit ed3af9
 * useful optimizations (such as merging color conversion with upsampling)
Packit ed3af9
 * and it also interfered with desired capabilities such as quantizing to an
Packit ed3af9
 * externally-supplied colormap.  We have therefore abandoned that approach.
Packit ed3af9
 * The present code works in the post-conversion color space, typically RGB.
Packit ed3af9
 *
Packit ed3af9
 * To improve the visual quality of the results, we actually work in scaled
Packit ed3af9
 * RGB space, giving G distances more weight than R, and R in turn more than
Packit ed3af9
 * B.  To do everything in integer math, we must use integer scale factors.
Packit ed3af9
 * The 2/3/1 scale factors used here correspond loosely to the relative
Packit ed3af9
 * weights of the colors in the NTSC grayscale equation.
Packit ed3af9
 * If you want to use this code to quantize a non-RGB color space, you'll
Packit ed3af9
 * probably need to change these scale factors.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
#define R_SCALE 2		/* scale R distances by this much */
Packit ed3af9
#define G_SCALE 3		/* scale G distances by this much */
Packit ed3af9
#define B_SCALE 1		/* and B by this much */
Packit ed3af9
Packit ed3af9
/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined
Packit ed3af9
 * in jmorecfg.h.  As the code stands, it will do the right thing for R,G,B
Packit ed3af9
 * and B,G,R orders.  If you define some other weird order in jmorecfg.h,
Packit ed3af9
 * you'll get compile errors until you extend this logic.  In that case
Packit ed3af9
 * you'll probably want to tweak the histogram sizes too.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
#if RGB_RED == 0
Packit ed3af9
#define C0_SCALE R_SCALE
Packit ed3af9
#endif
Packit ed3af9
#if RGB_BLUE == 0
Packit ed3af9
#define C0_SCALE B_SCALE
Packit ed3af9
#endif
Packit ed3af9
#if RGB_GREEN == 1
Packit ed3af9
#define C1_SCALE G_SCALE
Packit ed3af9
#endif
Packit ed3af9
#if RGB_RED == 2
Packit ed3af9
#define C2_SCALE R_SCALE
Packit ed3af9
#endif
Packit ed3af9
#if RGB_BLUE == 2
Packit ed3af9
#define C2_SCALE B_SCALE
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * First we have the histogram data structure and routines for creating it.
Packit ed3af9
 *
Packit ed3af9
 * The number of bits of precision can be adjusted by changing these symbols.
Packit ed3af9
 * We recommend keeping 6 bits for G and 5 each for R and B.
Packit ed3af9
 * If you have plenty of memory and cycles, 6 bits all around gives marginally
Packit ed3af9
 * better results; if you are short of memory, 5 bits all around will save
Packit ed3af9
 * some space but degrade the results.
Packit ed3af9
 * To maintain a fully accurate histogram, we'd need to allocate a "long"
Packit ed3af9
 * (preferably unsigned long) for each cell.  In practice this is overkill;
Packit ed3af9
 * we can get by with 16 bits per cell.  Few of the cell counts will overflow,
Packit ed3af9
 * and clamping those that do overflow to the maximum value will give close-
Packit ed3af9
 * enough results.  This reduces the recommended histogram size from 256Kb
Packit ed3af9
 * to 128Kb, which is a useful savings on PC-class machines.
Packit ed3af9
 * (In the second pass the histogram space is re-used for pixel mapping data;
Packit ed3af9
 * in that capacity, each cell must be able to store zero to the number of
Packit ed3af9
 * desired colors.  16 bits/cell is plenty for that too.)
Packit ed3af9
 * Since the JPEG code is intended to run in small memory model on 80x86
Packit ed3af9
 * machines, we can't just allocate the histogram in one chunk.  Instead
Packit ed3af9
 * of a true 3-D array, we use a row of pointers to 2-D arrays.  Each
Packit ed3af9
 * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and
Packit ed3af9
 * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries.  Note that
Packit ed3af9
 * on 80x86 machines, the pointer row is in near memory but the actual
Packit ed3af9
 * arrays are in far memory (same arrangement as we use for image arrays).
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
#define MAXNUMCOLORS  (MAXJSAMPLE+1)	/* maximum size of colormap */
Packit ed3af9
Packit ed3af9
/* These will do the right thing for either R,G,B or B,G,R color order,
Packit ed3af9
 * but you may not like the results for other color orders.
Packit ed3af9
 */
Packit ed3af9
#define HIST_C0_BITS  5		/* bits of precision in R/B histogram */
Packit ed3af9
#define HIST_C1_BITS  6		/* bits of precision in G histogram */
Packit ed3af9
#define HIST_C2_BITS  5		/* bits of precision in B/R histogram */
Packit ed3af9
Packit ed3af9
/* Number of elements along histogram axes. */
Packit ed3af9
#define HIST_C0_ELEMS  (1<
Packit ed3af9
#define HIST_C1_ELEMS  (1<
Packit ed3af9
#define HIST_C2_ELEMS  (1<
Packit ed3af9
Packit ed3af9
/* These are the amounts to shift an input value to get a histogram index. */
Packit ed3af9
#define C0_SHIFT  (BITS_IN_JSAMPLE-HIST_C0_BITS)
Packit ed3af9
#define C1_SHIFT  (BITS_IN_JSAMPLE-HIST_C1_BITS)
Packit ed3af9
#define C2_SHIFT  (BITS_IN_JSAMPLE-HIST_C2_BITS)
Packit ed3af9
Packit ed3af9
Packit ed3af9
typedef UINT16 histcell;	/* histogram cell; prefer an unsigned type */
Packit ed3af9
Packit ed3af9
typedef histcell FAR *histptr;	/* for pointers to histogram cells */
Packit ed3af9
Packit ed3af9
typedef histcell hist1d[HIST_C2_ELEMS];	/* typedefs for the array */
Packit ed3af9
typedef hist1d FAR *hist2d;	/* type for the 2nd-level pointers */
Packit ed3af9
typedef hist2d *hist3d;		/* type for top-level pointer */
Packit ed3af9
Packit ed3af9
Packit ed3af9
/* Declarations for Floyd-Steinberg dithering.
Packit ed3af9
 *
Packit ed3af9
 * Errors are accumulated into the array fserrors[], at a resolution of
Packit ed3af9
 * 1/16th of a pixel count.  The error at a given pixel is propagated
Packit ed3af9
 * to its not-yet-processed neighbors using the standard F-S fractions,
Packit ed3af9
 *		...	(here)	7/16
Packit ed3af9
 *		3/16	5/16	1/16
Packit ed3af9
 * We work left-to-right on even rows, right-to-left on odd rows.
Packit ed3af9
 *
Packit ed3af9
 * We can get away with a single array (holding one row's worth of errors)
Packit ed3af9
 * by using it to store the current row's errors at pixel columns not yet
Packit ed3af9
 * processed, but the next row's errors at columns already processed.  We
Packit ed3af9
 * need only a few extra variables to hold the errors immediately around the
Packit ed3af9
 * current column.  (If we are lucky, those variables are in registers, but
Packit ed3af9
 * even if not, they're probably cheaper to access than array elements are.)
Packit ed3af9
 *
Packit ed3af9
 * The fserrors[] array has (#columns + 2) entries; the extra entry at
Packit ed3af9
 * each end saves us from special-casing the first and last pixels.
Packit ed3af9
 * Each entry is three values long, one value for each color component.
Packit ed3af9
 *
Packit ed3af9
 * Note: on a wide image, we might not have enough room in a PC's near data
Packit ed3af9
 * segment to hold the error array; so it is allocated with alloc_large.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
#if BITS_IN_JSAMPLE == 8
Packit ed3af9
typedef INT16 FSERROR;		/* 16 bits should be enough */
Packit ed3af9
typedef int LOCFSERROR;		/* use 'int' for calculation temps */
Packit ed3af9
#else
Packit ed3af9
typedef INT32 FSERROR;		/* may need more than 16 bits */
Packit ed3af9
typedef INT32 LOCFSERROR;	/* be sure calculation temps are big enough */
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
typedef FSERROR FAR *FSERRPTR;	/* pointer to error array (in FAR storage!) */
Packit ed3af9
Packit ed3af9
Packit ed3af9
/* Private subobject */
Packit ed3af9
Packit ed3af9
typedef struct {
Packit ed3af9
	/* Variables for accumulating image statistics */
Packit ed3af9
	hist3d histogram;		/* pointer to the histogram */
Packit ed3af9
Packit ed3af9
Packit ed3af9
	/* Variables for Floyd-Steinberg dithering */
Packit ed3af9
	FSERRPTR fserrors;		/* accumulated errors */
Packit ed3af9
Packit ed3af9
	boolean on_odd_row;		/* flag to remember which row we are on */
Packit ed3af9
	int *error_limiter;		/* table for clamping the applied error */
Packit ed3af9
	int *error_limiter_storage;	/* gdMalloc'd storage for the above */
Packit ed3af9
}
Packit ed3af9
my_cquantizer;
Packit ed3af9
Packit ed3af9
typedef my_cquantizer *my_cquantize_ptr;
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * Prescan some rows of pixels.
Packit ed3af9
 * In this module the prescan simply updates the histogram, which has been
Packit ed3af9
 * initialized to zeroes by start_pass.
Packit ed3af9
 * An output_buf parameter is required by the method signature, but no data
Packit ed3af9
 * is actually output (in fact the buffer controller is probably passing a
Packit ed3af9
 * NULL pointer).
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
METHODDEF (void)
Packit ed3af9
prescan_quantize (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize)
Packit ed3af9
{
Packit ed3af9
	register JSAMPROW ptr;
Packit ed3af9
	register histptr histp;
Packit ed3af9
	register hist3d histogram = cquantize->histogram;
Packit ed3af9
	int row;
Packit ed3af9
	JDIMENSION col;
Packit ed3af9
	int width = oim->sx;
Packit ed3af9
	int num_rows = oim->sy;
Packit ed3af9
Packit ed3af9
	(void)nim;
Packit ed3af9
Packit ed3af9
	for (row = 0; row < num_rows; row++) {
Packit ed3af9
		ptr = input_buf[row];
Packit ed3af9
		for (col = width; col > 0; col--) {
Packit ed3af9
			int r = gdTrueColorGetRed (*ptr) >> C0_SHIFT;
Packit ed3af9
			int g = gdTrueColorGetGreen (*ptr) >> C1_SHIFT;
Packit ed3af9
			int b = gdTrueColorGetBlue (*ptr) >> C2_SHIFT;
Packit ed3af9
			/* 2.0.12: Steven Brown: support a single totally transparent
Packit ed3af9
			   color in the original. */
Packit ed3af9
			if ((oim->transparent >= 0) && (*ptr == oim->transparent)) {
Packit ed3af9
				ptr++;
Packit ed3af9
				continue;
Packit ed3af9
			}
Packit ed3af9
			/* get pixel value and index into the histogram */
Packit ed3af9
			histp = &histogram[r][g][b];
Packit ed3af9
			/* increment, check for overflow and undo increment if so. */
Packit ed3af9
			if (++(*histp) == 0)
Packit ed3af9
				(*histp)--;
Packit ed3af9
			ptr++;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * Next we have the really interesting routines: selection of a colormap
Packit ed3af9
 * given the completed histogram.
Packit ed3af9
 * These routines work with a list of "boxes", each representing a rectangular
Packit ed3af9
 * subset of the input color space (to histogram precision).
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
typedef struct {
Packit ed3af9
	/* The bounds of the box (inclusive); expressed as histogram indexes */
Packit ed3af9
	int c0min, c0max;
Packit ed3af9
	int c1min, c1max;
Packit ed3af9
	int c2min, c2max;
Packit ed3af9
	/* The volume (actually 2-norm) of the box */
Packit ed3af9
	INT32 volume;
Packit ed3af9
	/* The number of nonzero histogram cells within this box */
Packit ed3af9
	long colorcount;
Packit ed3af9
}
Packit ed3af9
box;
Packit ed3af9
Packit ed3af9
typedef box *boxptr;
Packit ed3af9
Packit ed3af9
Packit ed3af9
LOCAL (boxptr) find_biggest_color_pop (boxptr boxlist, int numboxes)
Packit ed3af9
/* Find the splittable box with the largest color population */
Packit ed3af9
/* Returns NULL if no splittable boxes remain */
Packit ed3af9
{
Packit ed3af9
	register boxptr boxp;
Packit ed3af9
	register int i;
Packit ed3af9
	register long maxc = 0;
Packit ed3af9
	boxptr which = NULL;
Packit ed3af9
Packit ed3af9
	for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
Packit ed3af9
		if (boxp->colorcount > maxc && boxp->volume > 0) {
Packit ed3af9
			which = boxp;
Packit ed3af9
			maxc = boxp->colorcount;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
	return which;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
LOCAL (boxptr) find_biggest_volume (boxptr boxlist, int numboxes)
Packit ed3af9
/* Find the splittable box with the largest (scaled) volume */
Packit ed3af9
/* Returns NULL if no splittable boxes remain */
Packit ed3af9
{
Packit ed3af9
	register boxptr boxp;
Packit ed3af9
	register int i;
Packit ed3af9
	register INT32 maxv = 0;
Packit ed3af9
	boxptr which = NULL;
Packit ed3af9
Packit ed3af9
	for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
Packit ed3af9
		if (boxp->volume > maxv) {
Packit ed3af9
			which = boxp;
Packit ed3af9
			maxv = boxp->volume;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
	return which;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
LOCAL (void)
Packit ed3af9
update_box (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize, boxptr boxp)
Packit ed3af9
{
Packit ed3af9
	hist3d histogram = cquantize->histogram;
Packit ed3af9
	histptr histp;
Packit ed3af9
	int c0, c1, c2;
Packit ed3af9
	int c0min, c0max, c1min, c1max, c2min, c2max;
Packit ed3af9
	INT32 dist0, dist1, dist2;
Packit ed3af9
	long ccount;
Packit ed3af9
	(void)oim;
Packit ed3af9
	(void)nim;
Packit ed3af9
Packit ed3af9
	c0min = boxp->c0min;
Packit ed3af9
	c0max = boxp->c0max;
Packit ed3af9
	c1min = boxp->c1min;
Packit ed3af9
	c1max = boxp->c1max;
Packit ed3af9
	c2min = boxp->c2min;
Packit ed3af9
	c2max = boxp->c2max;
Packit ed3af9
Packit ed3af9
	if (c0max > c0min)
Packit ed3af9
		for (c0 = c0min; c0 <= c0max; c0++)
Packit ed3af9
			for (c1 = c1min; c1 <= c1max; c1++) {
Packit ed3af9
				histp = &histogram[c0][c1][c2min];
Packit ed3af9
				for (c2 = c2min; c2 <= c2max; c2++)
Packit ed3af9
					if (*histp++ != 0) {
Packit ed3af9
						boxp->c0min = c0min = c0;
Packit ed3af9
						goto have_c0min;
Packit ed3af9
					}
Packit ed3af9
			}
Packit ed3af9
have_c0min:
Packit ed3af9
	if (c0max > c0min)
Packit ed3af9
		for (c0 = c0max; c0 >= c0min; c0--)
Packit ed3af9
			for (c1 = c1min; c1 <= c1max; c1++) {
Packit ed3af9
				histp = &histogram[c0][c1][c2min];
Packit ed3af9
				for (c2 = c2min; c2 <= c2max; c2++)
Packit ed3af9
					if (*histp++ != 0) {
Packit ed3af9
						boxp->c0max = c0max = c0;
Packit ed3af9
						goto have_c0max;
Packit ed3af9
					}
Packit ed3af9
			}
Packit ed3af9
have_c0max:
Packit ed3af9
	if (c1max > c1min)
Packit ed3af9
		for (c1 = c1min; c1 <= c1max; c1++)
Packit ed3af9
			for (c0 = c0min; c0 <= c0max; c0++) {
Packit ed3af9
				histp = &histogram[c0][c1][c2min];
Packit ed3af9
				for (c2 = c2min; c2 <= c2max; c2++)
Packit ed3af9
					if (*histp++ != 0) {
Packit ed3af9
						boxp->c1min = c1min = c1;
Packit ed3af9
						goto have_c1min;
Packit ed3af9
					}
Packit ed3af9
			}
Packit ed3af9
have_c1min:
Packit ed3af9
	if (c1max > c1min)
Packit ed3af9
		for (c1 = c1max; c1 >= c1min; c1--)
Packit ed3af9
			for (c0 = c0min; c0 <= c0max; c0++) {
Packit ed3af9
				histp = &histogram[c0][c1][c2min];
Packit ed3af9
				for (c2 = c2min; c2 <= c2max; c2++)
Packit ed3af9
					if (*histp++ != 0) {
Packit ed3af9
						boxp->c1max = c1max = c1;
Packit ed3af9
						goto have_c1max;
Packit ed3af9
					}
Packit ed3af9
			}
Packit ed3af9
have_c1max:
Packit ed3af9
	if (c2max > c2min)
Packit ed3af9
		for (c2 = c2min; c2 <= c2max; c2++)
Packit ed3af9
			for (c0 = c0min; c0 <= c0max; c0++) {
Packit ed3af9
				histp = &histogram[c0][c1min][c2];
Packit ed3af9
				for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
Packit ed3af9
					if (*histp != 0) {
Packit ed3af9
						boxp->c2min = c2min = c2;
Packit ed3af9
						goto have_c2min;
Packit ed3af9
					}
Packit ed3af9
			}
Packit ed3af9
have_c2min:
Packit ed3af9
	if (c2max > c2min)
Packit ed3af9
		for (c2 = c2max; c2 >= c2min; c2--)
Packit ed3af9
			for (c0 = c0min; c0 <= c0max; c0++) {
Packit ed3af9
				histp = &histogram[c0][c1min][c2];
Packit ed3af9
				for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
Packit ed3af9
					if (*histp != 0) {
Packit ed3af9
						boxp->c2max = c2max = c2;
Packit ed3af9
						goto have_c2max;
Packit ed3af9
					}
Packit ed3af9
			}
Packit ed3af9
have_c2max:
Packit ed3af9
Packit ed3af9
	/* Update box volume.
Packit ed3af9
	 * We use 2-norm rather than real volume here; this biases the method
Packit ed3af9
	 * against making long narrow boxes, and it has the side benefit that
Packit ed3af9
	 * a box is splittable iff norm > 0.
Packit ed3af9
	 * Since the differences are expressed in histogram-cell units,
Packit ed3af9
	 * we have to shift back to JSAMPLE units to get consistent distances;
Packit ed3af9
	 * after which, we scale according to the selected distance scale factors.
Packit ed3af9
	 */
Packit ed3af9
	dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
Packit ed3af9
	dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
Packit ed3af9
	dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
Packit ed3af9
	boxp->volume = dist0 * dist0 + dist1 * dist1 + dist2 * dist2;
Packit ed3af9
Packit ed3af9
	/* Now scan remaining volume of box and compute population */
Packit ed3af9
	ccount = 0;
Packit ed3af9
	for (c0 = c0min; c0 <= c0max; c0++)
Packit ed3af9
		for (c1 = c1min; c1 <= c1max; c1++) {
Packit ed3af9
			histp = &histogram[c0][c1][c2min];
Packit ed3af9
			for (c2 = c2min; c2 <= c2max; c2++, histp++)
Packit ed3af9
				if (*histp != 0) {
Packit ed3af9
					ccount++;
Packit ed3af9
				}
Packit ed3af9
		}
Packit ed3af9
	boxp->colorcount = ccount;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
LOCAL (int)
Packit ed3af9
median_cut (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize,
Packit ed3af9
	    boxptr boxlist, int numboxes, int desired_colors)
Packit ed3af9
/* Repeatedly select and split the largest box until we have enough boxes */
Packit ed3af9
{
Packit ed3af9
	int n, lb;
Packit ed3af9
	int c0, c1, c2, cmax;
Packit ed3af9
	register boxptr b1, b2;
Packit ed3af9
Packit ed3af9
	while (numboxes < desired_colors) {
Packit ed3af9
		/* Select box to split.
Packit ed3af9
		 * Current algorithm: by population for first half, then by volume.
Packit ed3af9
		 */
Packit ed3af9
		if (numboxes * 2 <= desired_colors) {
Packit ed3af9
			b1 = find_biggest_color_pop (boxlist, numboxes);
Packit ed3af9
		} else {
Packit ed3af9
			b1 = find_biggest_volume (boxlist, numboxes);
Packit ed3af9
		}
Packit ed3af9
		if (b1 == NULL)		/* no splittable boxes left! */
Packit ed3af9
			break;
Packit ed3af9
		b2 = &boxlist[numboxes];	/* where new box will go */
Packit ed3af9
		/* Copy the color bounds to the new box. */
Packit ed3af9
		b2->c0max = b1->c0max;
Packit ed3af9
		b2->c1max = b1->c1max;
Packit ed3af9
		b2->c2max = b1->c2max;
Packit ed3af9
		b2->c0min = b1->c0min;
Packit ed3af9
		b2->c1min = b1->c1min;
Packit ed3af9
		b2->c2min = b1->c2min;
Packit ed3af9
		/* Choose which axis to split the box on.
Packit ed3af9
		 * Current algorithm: longest scaled axis.
Packit ed3af9
		 * See notes in update_box about scaling distances.
Packit ed3af9
		 */
Packit ed3af9
		c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE;
Packit ed3af9
		c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE;
Packit ed3af9
		c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE;
Packit ed3af9
		/* We want to break any ties in favor of green, then red, blue last.
Packit ed3af9
		 * This code does the right thing for R,G,B or B,G,R color orders only.
Packit ed3af9
		 */
Packit ed3af9
#if RGB_RED == 0
Packit ed3af9
		cmax = c1;
Packit ed3af9
		n = 1;
Packit ed3af9
		if (c0 > cmax) {
Packit ed3af9
			cmax = c0;
Packit ed3af9
			n = 0;
Packit ed3af9
		}
Packit ed3af9
		if (c2 > cmax) {
Packit ed3af9
			n = 2;
Packit ed3af9
		}
Packit ed3af9
#else
Packit ed3af9
		cmax = c1;
Packit ed3af9
		n = 1;
Packit ed3af9
		if (c2 > cmax) {
Packit ed3af9
			cmax = c2;
Packit ed3af9
			n = 2;
Packit ed3af9
		}
Packit ed3af9
		if (c0 > cmax) {
Packit ed3af9
			n = 0;
Packit ed3af9
		}
Packit ed3af9
#endif
Packit ed3af9
		/* Choose split point along selected axis, and update box bounds.
Packit ed3af9
		 * Current algorithm: split at halfway point.
Packit ed3af9
		 * (Since the box has been shrunk to minimum volume,
Packit ed3af9
		 * any split will produce two nonempty subboxes.)
Packit ed3af9
		 * Note that lb value is max for lower box, so must be < old max.
Packit ed3af9
		 */
Packit ed3af9
		switch (n) {
Packit ed3af9
		case 0:
Packit ed3af9
			lb = (b1->c0max + b1->c0min) / 2;
Packit ed3af9
			b1->c0max = lb;
Packit ed3af9
			b2->c0min = lb + 1;
Packit ed3af9
			break;
Packit ed3af9
		case 1:
Packit ed3af9
			lb = (b1->c1max + b1->c1min) / 2;
Packit ed3af9
			b1->c1max = lb;
Packit ed3af9
			b2->c1min = lb + 1;
Packit ed3af9
			break;
Packit ed3af9
		case 2:
Packit ed3af9
			lb = (b1->c2max + b1->c2min) / 2;
Packit ed3af9
			b1->c2max = lb;
Packit ed3af9
			b2->c2min = lb + 1;
Packit ed3af9
			break;
Packit ed3af9
		}
Packit ed3af9
		/* Update stats for boxes */
Packit ed3af9
		update_box (oim, nim, cquantize, b1);
Packit ed3af9
		update_box (oim, nim, cquantize, b2);
Packit ed3af9
		numboxes++;
Packit ed3af9
	}
Packit ed3af9
	return numboxes;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
LOCAL (void)
Packit ed3af9
compute_color (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize,
Packit ed3af9
	       boxptr boxp, int icolor)
Packit ed3af9
{
Packit ed3af9
	hist3d histogram = cquantize->histogram;
Packit ed3af9
	histptr histp;
Packit ed3af9
	int c0, c1, c2;
Packit ed3af9
	int c0min, c0max, c1min, c1max, c2min, c2max;
Packit ed3af9
	long count = 0; /* 2.0.28: = 0 */
Packit ed3af9
	long total = 0;
Packit ed3af9
	long c0total = 0;
Packit ed3af9
	long c1total = 0;
Packit ed3af9
	long c2total = 0;
Packit ed3af9
	(void)oim;
Packit ed3af9
Packit ed3af9
	c0min = boxp->c0min;
Packit ed3af9
	c0max = boxp->c0max;
Packit ed3af9
	c1min = boxp->c1min;
Packit ed3af9
	c1max = boxp->c1max;
Packit ed3af9
	c2min = boxp->c2min;
Packit ed3af9
	c2max = boxp->c2max;
Packit ed3af9
Packit ed3af9
	for (c0 = c0min; c0 <= c0max; c0++)
Packit ed3af9
		for (c1 = c1min; c1 <= c1max; c1++) {
Packit ed3af9
			histp = &histogram[c0][c1][c2min];
Packit ed3af9
			for (c2 = c2min; c2 <= c2max; c2++) {
Packit ed3af9
				if ((count = *histp++) != 0) {
Packit ed3af9
					total += count;
Packit ed3af9
					c0total +=
Packit ed3af9
					    ((c0 << C0_SHIFT) + ((1 << C0_SHIFT) >> 1)) * count;
Packit ed3af9
					c1total +=
Packit ed3af9
					    ((c1 << C1_SHIFT) + ((1 << C1_SHIFT) >> 1)) * count;
Packit ed3af9
					c2total +=
Packit ed3af9
					    ((c2 << C2_SHIFT) + ((1 << C2_SHIFT) >> 1)) * count;
Packit ed3af9
				}
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
	/* 2.0.16: Paul den Dulk found an occasion where total can be 0 */
Packit ed3af9
	if (total) {
Packit ed3af9
		nim->red[icolor] = (int) ((c0total + (total >> 1)) / total);
Packit ed3af9
		nim->green[icolor] = (int) ((c1total + (total >> 1)) / total);
Packit ed3af9
		nim->blue[icolor] = (int) ((c2total + (total >> 1)) / total);
Packit ed3af9
	} else {
Packit ed3af9
		nim->red[icolor] = 255;
Packit ed3af9
		nim->green[icolor] = 255;
Packit ed3af9
		nim->blue[icolor] = 255;
Packit ed3af9
	}
Packit ed3af9
	nim->open[icolor] = 0;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
LOCAL (void)
Packit ed3af9
select_colors (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize, int desired_colors)
Packit ed3af9
/* Master routine for color selection */
Packit ed3af9
{
Packit ed3af9
	boxptr boxlist;
Packit ed3af9
	int numboxes;
Packit ed3af9
	int i;
Packit ed3af9
Packit ed3af9
	/* Allocate workspace for box list */
Packit ed3af9
	/* This can't happen because we clamp desired_colors at gdMaxColors,
Packit ed3af9
	  but anyway */
Packit ed3af9
	if (overflow2(desired_colors, sizeof (box))) {
Packit ed3af9
		return;
Packit ed3af9
	}
Packit ed3af9
	boxlist = (boxptr) gdMalloc (desired_colors * sizeof (box));
Packit ed3af9
	if (!boxlist) {
Packit ed3af9
		return;
Packit ed3af9
	}
Packit ed3af9
	/* Initialize one box containing whole space */
Packit ed3af9
	numboxes = 1;
Packit ed3af9
	boxlist[0].c0min = 0;
Packit ed3af9
	boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT;
Packit ed3af9
	boxlist[0].c1min = 0;
Packit ed3af9
	boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT;
Packit ed3af9
	boxlist[0].c2min = 0;
Packit ed3af9
	boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT;
Packit ed3af9
	/* Shrink it to actually-used volume and set its statistics */
Packit ed3af9
	update_box (oim, nim, cquantize, &boxlist[0]);
Packit ed3af9
	/* Perform median-cut to produce final box list */
Packit ed3af9
	numboxes = median_cut (oim, nim, cquantize, boxlist, numboxes, desired_colors);
Packit ed3af9
	/* Compute the representative color for each box, fill colormap */
Packit ed3af9
	for (i = 0; i < numboxes; i++)
Packit ed3af9
		compute_color (oim, nim, cquantize, &boxlist[i], i);
Packit ed3af9
	nim->colorsTotal = numboxes;
Packit ed3af9
Packit ed3af9
	/* If we had a pure transparency color, add it as the last palette entry.
Packit ed3af9
	 * Skip incrementing the color count so that the dither / matching phase
Packit ed3af9
	 * won't use it on pixels that shouldn't have been transparent.  We'll
Packit ed3af9
	 * increment it after all that finishes. */
Packit ed3af9
	if (oim->transparent >= 0) {
Packit ed3af9
		/* Save the transparent color. */
Packit ed3af9
		nim->red[nim->colorsTotal] = gdTrueColorGetRed (oim->transparent);
Packit ed3af9
		nim->green[nim->colorsTotal] = gdTrueColorGetGreen (oim->transparent);
Packit ed3af9
		nim->blue[nim->colorsTotal] = gdTrueColorGetBlue (oim->transparent);
Packit ed3af9
		nim->alpha[nim->colorsTotal] = gdAlphaTransparent;
Packit ed3af9
		nim->open[nim->colorsTotal] = 0;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	gdFree (boxlist);
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * These routines are concerned with the time-critical task of mapping input
Packit ed3af9
 * colors to the nearest color in the selected colormap.
Packit ed3af9
 *
Packit ed3af9
 * We re-use the histogram space as an "inverse color map", essentially a
Packit ed3af9
 * cache for the results of nearest-color searches.  All colors within a
Packit ed3af9
 * histogram cell will be mapped to the same colormap entry, namely the one
Packit ed3af9
 * closest to the cell's center.  This may not be quite the closest entry to
Packit ed3af9
 * the actual input color, but it's almost as good.  A zero in the cache
Packit ed3af9
 * indicates we haven't found the nearest color for that cell yet; the array
Packit ed3af9
 * is cleared to zeroes before starting the mapping pass.  When we find the
Packit ed3af9
 * nearest color for a cell, its colormap index plus one is recorded in the
Packit ed3af9
 * cache for future use.  The pass2 scanning routines call fill_inverse_cmap
Packit ed3af9
 * when they need to use an unfilled entry in the cache.
Packit ed3af9
 *
Packit ed3af9
 * Our method of efficiently finding nearest colors is based on the "locally
Packit ed3af9
 * sorted search" idea described by Heckbert and on the incremental distance
Packit ed3af9
 * calculation described by Spencer W. Thomas in chapter III.1 of Graphics
Packit ed3af9
 * Gems II (James Arvo, ed.  Academic Press, 1991).  Thomas points out that
Packit ed3af9
 * the distances from a given colormap entry to each cell of the histogram can
Packit ed3af9
 * be computed quickly using an incremental method: the differences between
Packit ed3af9
 * distances to adjacent cells themselves differ by a constant.  This allows a
Packit ed3af9
 * fairly fast implementation of the "brute force" approach of computing the
Packit ed3af9
 * distance from every colormap entry to every histogram cell.  Unfortunately,
Packit ed3af9
 * it needs a work array to hold the best-distance-so-far for each histogram
Packit ed3af9
 * cell (because the inner loop has to be over cells, not colormap entries).
Packit ed3af9
 * The work array elements have to be INT32s, so the work array would need
Packit ed3af9
 * 256Kb at our recommended precision.  This is not feasible in DOS machines.
Packit ed3af9
 *
Packit ed3af9
 * To get around these problems, we apply Thomas' method to compute the
Packit ed3af9
 * nearest colors for only the cells within a small subbox of the histogram.
Packit ed3af9
 * The work array need be only as big as the subbox, so the memory usage
Packit ed3af9
 * problem is solved.  Furthermore, we need not fill subboxes that are never
Packit ed3af9
 * referenced in pass2; many images use only part of the color gamut, so a
Packit ed3af9
 * fair amount of work is saved.  An additional advantage of this
Packit ed3af9
 * approach is that we can apply Heckbert's locality criterion to quickly
Packit ed3af9
 * eliminate colormap entries that are far away from the subbox; typically
Packit ed3af9
 * three-fourths of the colormap entries are rejected by Heckbert's criterion,
Packit ed3af9
 * and we need not compute their distances to individual cells in the subbox.
Packit ed3af9
 * The speed of this approach is heavily influenced by the subbox size: too
Packit ed3af9
 * small means too much overhead, too big loses because Heckbert's criterion
Packit ed3af9
 * can't eliminate as many colormap entries.  Empirically the best subbox
Packit ed3af9
 * size seems to be about 1/512th of the histogram (1/8th in each direction).
Packit ed3af9
 *
Packit ed3af9
 * Thomas' article also describes a refined method which is asymptotically
Packit ed3af9
 * faster than the brute-force method, but it is also far more complex and
Packit ed3af9
 * cannot efficiently be applied to small subboxes.  It is therefore not
Packit ed3af9
 * useful for programs intended to be portable to DOS machines.  On machines
Packit ed3af9
 * with plenty of memory, filling the whole histogram in one shot with Thomas'
Packit ed3af9
 * refined method might be faster than the present code --- but then again,
Packit ed3af9
 * it might not be any faster, and it's certainly more complicated.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
Packit ed3af9
/* log2(histogram cells in update box) for each axis; this can be adjusted */
Packit ed3af9
#define BOX_C0_LOG  (HIST_C0_BITS-3)
Packit ed3af9
#define BOX_C1_LOG  (HIST_C1_BITS-3)
Packit ed3af9
#define BOX_C2_LOG  (HIST_C2_BITS-3)
Packit ed3af9
Packit ed3af9
#define BOX_C0_ELEMS  (1<
Packit ed3af9
#define BOX_C1_ELEMS  (1<
Packit ed3af9
#define BOX_C2_ELEMS  (1<
Packit ed3af9
Packit ed3af9
#define BOX_C0_SHIFT  (C0_SHIFT + BOX_C0_LOG)
Packit ed3af9
#define BOX_C1_SHIFT  (C1_SHIFT + BOX_C1_LOG)
Packit ed3af9
#define BOX_C2_SHIFT  (C2_SHIFT + BOX_C2_LOG)
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * The next three routines implement inverse colormap filling.  They could
Packit ed3af9
 * all be folded into one big routine, but splitting them up this way saves
Packit ed3af9
 * some stack space (the mindist[] and bestdist[] arrays need not coexist)
Packit ed3af9
 * and may allow some compilers to produce better code by registerizing more
Packit ed3af9
 * inner-loop variables.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
LOCAL (int)
Packit ed3af9
find_nearby_colors (
Packit ed3af9
    gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize,
Packit ed3af9
    int minc0, int minc1, int minc2, JSAMPLE colorlist[])
Packit ed3af9
/* Locate the colormap entries close enough to an update box to be candidates
Packit ed3af9
 * for the nearest entry to some cell(s) in the update box.  The update box
Packit ed3af9
 * is specified by the center coordinates of its first cell.  The number of
Packit ed3af9
 * candidate colormap entries is returned, and their colormap indexes are
Packit ed3af9
 * placed in colorlist[].
Packit ed3af9
 * This routine uses Heckbert's "locally sorted search" criterion to select
Packit ed3af9
 * the colors that need further consideration.
Packit ed3af9
 */
Packit ed3af9
{
Packit ed3af9
	int numcolors = nim->colorsTotal;
Packit ed3af9
	int maxc0, maxc1, maxc2;
Packit ed3af9
	int centerc0, centerc1, centerc2;
Packit ed3af9
	int i, x, ncolors;
Packit ed3af9
	INT32 minmaxdist, min_dist, max_dist, tdist;
Packit ed3af9
	INT32 mindist[MAXNUMCOLORS];	/* min distance to colormap entry i */
Packit ed3af9
	(void)oim;
Packit ed3af9
	(void)cquantize;
Packit ed3af9
Packit ed3af9
	/* Compute true coordinates of update box's upper corner and center.
Packit ed3af9
	 * Actually we compute the coordinates of the center of the upper-corner
Packit ed3af9
	 * histogram cell, which are the upper bounds of the volume we care about.
Packit ed3af9
	 * Note that since ">>" rounds down, the "center" values may be closer to
Packit ed3af9
	 * min than to max; hence comparisons to them must be "<=", not "<".
Packit ed3af9
	 */
Packit ed3af9
	maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));
Packit ed3af9
	centerc0 = (minc0 + maxc0) >> 1;
Packit ed3af9
	maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));
Packit ed3af9
	centerc1 = (minc1 + maxc1) >> 1;
Packit ed3af9
	maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));
Packit ed3af9
	centerc2 = (minc2 + maxc2) >> 1;
Packit ed3af9
Packit ed3af9
	/* For each color in colormap, find:
Packit ed3af9
	 *  1. its minimum squared-distance to any point in the update box
Packit ed3af9
	 *     (zero if color is within update box);
Packit ed3af9
	 *  2. its maximum squared-distance to any point in the update box.
Packit ed3af9
	 * Both of these can be found by considering only the corners of the box.
Packit ed3af9
	 * We save the minimum distance for each color in mindist[];
Packit ed3af9
	 * only the smallest maximum distance is of interest.
Packit ed3af9
	 */
Packit ed3af9
	minmaxdist = 0x7FFFFFFFL;
Packit ed3af9
Packit ed3af9
	for (i = 0; i < numcolors; i++) {
Packit ed3af9
		/* We compute the squared-c0-distance term, then add in the other two. */
Packit ed3af9
		x = nim->red[i];
Packit ed3af9
		if (x < minc0) {
Packit ed3af9
			tdist = (x - minc0) * C0_SCALE;
Packit ed3af9
			min_dist = tdist * tdist;
Packit ed3af9
			tdist = (x - maxc0) * C0_SCALE;
Packit ed3af9
			max_dist = tdist * tdist;
Packit ed3af9
		} else if (x > maxc0) {
Packit ed3af9
			tdist = (x - maxc0) * C0_SCALE;
Packit ed3af9
			min_dist = tdist * tdist;
Packit ed3af9
			tdist = (x - minc0) * C0_SCALE;
Packit ed3af9
			max_dist = tdist * tdist;
Packit ed3af9
		} else {
Packit ed3af9
			/* within cell range so no contribution to min_dist */
Packit ed3af9
			min_dist = 0;
Packit ed3af9
			if (x <= centerc0) {
Packit ed3af9
				tdist = (x - maxc0) * C0_SCALE;
Packit ed3af9
				max_dist = tdist * tdist;
Packit ed3af9
			} else {
Packit ed3af9
				tdist = (x - minc0) * C0_SCALE;
Packit ed3af9
				max_dist = tdist * tdist;
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		x = nim->green[i];
Packit ed3af9
		if (x < minc1) {
Packit ed3af9
			tdist = (x - minc1) * C1_SCALE;
Packit ed3af9
			min_dist += tdist * tdist;
Packit ed3af9
			tdist = (x - maxc1) * C1_SCALE;
Packit ed3af9
			max_dist += tdist * tdist;
Packit ed3af9
		} else if (x > maxc1) {
Packit ed3af9
			tdist = (x - maxc1) * C1_SCALE;
Packit ed3af9
			min_dist += tdist * tdist;
Packit ed3af9
			tdist = (x - minc1) * C1_SCALE;
Packit ed3af9
			max_dist += tdist * tdist;
Packit ed3af9
		} else {
Packit ed3af9
			/* within cell range so no contribution to min_dist */
Packit ed3af9
			if (x <= centerc1) {
Packit ed3af9
				tdist = (x - maxc1) * C1_SCALE;
Packit ed3af9
				max_dist += tdist * tdist;
Packit ed3af9
			} else {
Packit ed3af9
				tdist = (x - minc1) * C1_SCALE;
Packit ed3af9
				max_dist += tdist * tdist;
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		x = nim->blue[i];
Packit ed3af9
		if (x < minc2) {
Packit ed3af9
			tdist = (x - minc2) * C2_SCALE;
Packit ed3af9
			min_dist += tdist * tdist;
Packit ed3af9
			tdist = (x - maxc2) * C2_SCALE;
Packit ed3af9
			max_dist += tdist * tdist;
Packit ed3af9
		} else if (x > maxc2) {
Packit ed3af9
			tdist = (x - maxc2) * C2_SCALE;
Packit ed3af9
			min_dist += tdist * tdist;
Packit ed3af9
			tdist = (x - minc2) * C2_SCALE;
Packit ed3af9
			max_dist += tdist * tdist;
Packit ed3af9
		} else {
Packit ed3af9
			/* within cell range so no contribution to min_dist */
Packit ed3af9
			if (x <= centerc2) {
Packit ed3af9
				tdist = (x - maxc2) * C2_SCALE;
Packit ed3af9
				max_dist += tdist * tdist;
Packit ed3af9
			} else {
Packit ed3af9
				tdist = (x - minc2) * C2_SCALE;
Packit ed3af9
				max_dist += tdist * tdist;
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		mindist[i] = min_dist;	/* save away the results */
Packit ed3af9
		if (max_dist < minmaxdist)
Packit ed3af9
			minmaxdist = max_dist;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* Now we know that no cell in the update box is more than minmaxdist
Packit ed3af9
	 * away from some colormap entry.  Therefore, only colors that are
Packit ed3af9
	 * within minmaxdist of some part of the box need be considered.
Packit ed3af9
	 */
Packit ed3af9
	ncolors = 0;
Packit ed3af9
	for (i = 0; i < numcolors; i++) {
Packit ed3af9
		if (mindist[i] <= minmaxdist)
Packit ed3af9
			colorlist[ncolors++] = (JSAMPLE) i;
Packit ed3af9
	}
Packit ed3af9
	return ncolors;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
LOCAL (void) find_best_colors (
Packit ed3af9
    gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize,
Packit ed3af9
    int minc0, int minc1, int minc2,
Packit ed3af9
    int numcolors, JSAMPLE colorlist[],
Packit ed3af9
    JSAMPLE bestcolor[])
Packit ed3af9
/* Find the closest colormap entry for each cell in the update box,
Packit ed3af9
 * given the list of candidate colors prepared by find_nearby_colors.
Packit ed3af9
 * Return the indexes of the closest entries in the bestcolor[] array.
Packit ed3af9
 * This routine uses Thomas' incremental distance calculation method to
Packit ed3af9
 * find the distance from a colormap entry to successive cells in the box.
Packit ed3af9
 */
Packit ed3af9
{
Packit ed3af9
	int ic0, ic1, ic2;
Packit ed3af9
	int i, icolor;
Packit ed3af9
	register INT32 *bptr;		/* pointer into bestdist[] array */
Packit ed3af9
	JSAMPLE *cptr;		/* pointer into bestcolor[] array */
Packit ed3af9
	INT32 dist0, dist1;		/* initial distance values */
Packit ed3af9
	register INT32 dist2;		/* current distance in inner loop */
Packit ed3af9
	INT32 xx0, xx1;		/* distance increments */
Packit ed3af9
	register INT32 xx2;
Packit ed3af9
	INT32 inc0, inc1, inc2;	/* initial values for increments */
Packit ed3af9
	/* This array holds the distance to the nearest-so-far color for each cell */
Packit ed3af9
	INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
Packit ed3af9
	(void)oim;
Packit ed3af9
	(void)cquantize;
Packit ed3af9
Packit ed3af9
	/* Initialize best-distance for each cell of the update box */
Packit ed3af9
	bptr = bestdist;
Packit ed3af9
	for (i = BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS - 1; i >= 0; i--)
Packit ed3af9
		*bptr++ = 0x7FFFFFFFL;
Packit ed3af9
Packit ed3af9
	/* For each color selected by find_nearby_colors,
Packit ed3af9
	 * compute its distance to the center of each cell in the box.
Packit ed3af9
	 * If that's less than best-so-far, update best distance and color number.
Packit ed3af9
	 */
Packit ed3af9
Packit ed3af9
	/* Nominal steps between cell centers ("x" in Thomas article) */
Packit ed3af9
#define STEP_C0  ((1 << C0_SHIFT) * C0_SCALE)
Packit ed3af9
#define STEP_C1  ((1 << C1_SHIFT) * C1_SCALE)
Packit ed3af9
#define STEP_C2  ((1 << C2_SHIFT) * C2_SCALE)
Packit ed3af9
Packit ed3af9
	for (i = 0; i < numcolors; i++) {
Packit ed3af9
		int r, g, b;
Packit ed3af9
		icolor = colorlist[i];
Packit ed3af9
		r = nim->red[icolor];
Packit ed3af9
		g = nim->green[icolor];
Packit ed3af9
		b = nim->blue[icolor];
Packit ed3af9
Packit ed3af9
		/* Compute (square of) distance from minc0/c1/c2 to this color */
Packit ed3af9
		inc0 = (minc0 - r) * C0_SCALE;
Packit ed3af9
		dist0 = inc0 * inc0;
Packit ed3af9
		inc1 = (minc1 - g) * C1_SCALE;
Packit ed3af9
		dist0 += inc1 * inc1;
Packit ed3af9
		inc2 = (minc2 - b) * C2_SCALE;
Packit ed3af9
		dist0 += inc2 * inc2;
Packit ed3af9
		/* Form the initial difference increments */
Packit ed3af9
		inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
Packit ed3af9
		inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
Packit ed3af9
		inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;
Packit ed3af9
		/* Now loop over all cells in box, updating distance per Thomas method */
Packit ed3af9
		bptr = bestdist;
Packit ed3af9
		cptr = bestcolor;
Packit ed3af9
		xx0 = inc0;
Packit ed3af9
		for (ic0 = BOX_C0_ELEMS - 1; ic0 >= 0; ic0--) {
Packit ed3af9
			dist1 = dist0;
Packit ed3af9
			xx1 = inc1;
Packit ed3af9
			for (ic1 = BOX_C1_ELEMS - 1; ic1 >= 0; ic1--) {
Packit ed3af9
				dist2 = dist1;
Packit ed3af9
				xx2 = inc2;
Packit ed3af9
				for (ic2 = BOX_C2_ELEMS - 1; ic2 >= 0; ic2--) {
Packit ed3af9
					if (dist2 < *bptr) {
Packit ed3af9
						*bptr = dist2;
Packit ed3af9
						*cptr = (JSAMPLE) icolor;
Packit ed3af9
					}
Packit ed3af9
					dist2 += xx2;
Packit ed3af9
					xx2 += 2 * STEP_C2 * STEP_C2;
Packit ed3af9
					bptr++;
Packit ed3af9
					cptr++;
Packit ed3af9
				}
Packit ed3af9
				dist1 += xx1;
Packit ed3af9
				xx1 += 2 * STEP_C1 * STEP_C1;
Packit ed3af9
			}
Packit ed3af9
			dist0 += xx0;
Packit ed3af9
			xx0 += 2 * STEP_C0 * STEP_C0;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
LOCAL (void)
Packit ed3af9
fill_inverse_cmap (
Packit ed3af9
    gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize,
Packit ed3af9
    int c0, int c1, int c2)
Packit ed3af9
/* Fill the inverse-colormap entries in the update box that contains */
Packit ed3af9
/* histogram cell c0/c1/c2.  (Only that one cell MUST be filled, but */
Packit ed3af9
/* we can fill as many others as we wish.) */
Packit ed3af9
{
Packit ed3af9
	hist3d histogram = cquantize->histogram;
Packit ed3af9
	int minc0, minc1, minc2;	/* lower left corner of update box */
Packit ed3af9
	int ic0, ic1, ic2;
Packit ed3af9
	register JSAMPLE *cptr;	/* pointer into bestcolor[] array */
Packit ed3af9
	register histptr cachep;	/* pointer into main cache array */
Packit ed3af9
	/* This array lists the candidate colormap indexes. */
Packit ed3af9
	JSAMPLE colorlist[MAXNUMCOLORS];
Packit ed3af9
	int numcolors;		/* number of candidate colors */
Packit ed3af9
	/* This array holds the actually closest colormap index for each cell. */
Packit ed3af9
	JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
Packit ed3af9
Packit ed3af9
	/* Convert cell coordinates to update box ID */
Packit ed3af9
	c0 >>= BOX_C0_LOG;
Packit ed3af9
	c1 >>= BOX_C1_LOG;
Packit ed3af9
	c2 >>= BOX_C2_LOG;
Packit ed3af9
Packit ed3af9
	/* Compute true coordinates of update box's origin corner.
Packit ed3af9
	 * Actually we compute the coordinates of the center of the corner
Packit ed3af9
	 * histogram cell, which are the lower bounds of the volume we care about.
Packit ed3af9
	 */
Packit ed3af9
	minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
Packit ed3af9
	minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
Packit ed3af9
	minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
Packit ed3af9
Packit ed3af9
	/* Determine which colormap entries are close enough to be candidates
Packit ed3af9
	 * for the nearest entry to some cell in the update box.
Packit ed3af9
	 */
Packit ed3af9
	numcolors =
Packit ed3af9
	    find_nearby_colors (oim, nim, cquantize, minc0, minc1, minc2, colorlist);
Packit ed3af9
	find_best_colors (oim, nim, cquantize, minc0, minc1, minc2, numcolors,
Packit ed3af9
			  colorlist, bestcolor);
Packit ed3af9
Packit ed3af9
	/* Save the best color numbers (plus 1) in the main cache array */
Packit ed3af9
	c0 <<= BOX_C0_LOG;		/* convert ID back to base cell indexes */
Packit ed3af9
	c1 <<= BOX_C1_LOG;
Packit ed3af9
	c2 <<= BOX_C2_LOG;
Packit ed3af9
	cptr = bestcolor;
Packit ed3af9
	for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
Packit ed3af9
		for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
Packit ed3af9
			cachep = &histogram[c0 + ic0][c1 + ic1][c2];
Packit ed3af9
			for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
Packit ed3af9
				*cachep++ = (histcell) ((*cptr++) + 1);
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * Map some rows of pixels to the output colormapped representation.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
METHODDEF (void)
Packit ed3af9
pass2_no_dither (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize)
Packit ed3af9
{
Packit ed3af9
	register int *inptr;
Packit ed3af9
	register unsigned char *outptr;
Packit ed3af9
	int width = oim->sx;
Packit ed3af9
	int num_rows = oim->sy;
Packit ed3af9
	hist3d histogram = cquantize->histogram;
Packit ed3af9
	register int c0, c1, c2;
Packit ed3af9
	int row;
Packit ed3af9
	JDIMENSION col;
Packit ed3af9
	register histptr cachep;
Packit ed3af9
Packit ed3af9
Packit ed3af9
	for (row = 0; row < num_rows; row++) {
Packit ed3af9
		inptr = input_buf[row];
Packit ed3af9
		outptr = output_buf[row];
Packit ed3af9
		for (col = width; col > 0; col--) {
Packit ed3af9
			/* get pixel value and index into the cache */
Packit ed3af9
			int r, g, b;
Packit ed3af9
			r = gdTrueColorGetRed (*inptr);
Packit ed3af9
			g = gdTrueColorGetGreen (*inptr);
Packit ed3af9
			/*
Packit ed3af9
			   2.0.24: inptr must not be incremented until after
Packit ed3af9
			   transparency check, if any. Thanks to "Super Pikeman."
Packit ed3af9
			 */
Packit ed3af9
			b = gdTrueColorGetBlue (*inptr);
Packit ed3af9
Packit ed3af9
			/* If the pixel is transparent, we assign it the palette index that
Packit ed3af9
			 * will later be added at the end of the palette as the transparent
Packit ed3af9
			 * index. */
Packit ed3af9
			if ((oim->transparent >= 0) && (oim->transparent == *inptr)) {
Packit ed3af9
				*outptr++ = nim->colorsTotal;
Packit ed3af9
				inptr++;
Packit ed3af9
				continue;
Packit ed3af9
			}
Packit ed3af9
			inptr++;
Packit ed3af9
			c0 = r >> C0_SHIFT;
Packit ed3af9
			c1 = g >> C1_SHIFT;
Packit ed3af9
			c2 = b >> C2_SHIFT;
Packit ed3af9
			cachep = &histogram[c0][c1][c2];
Packit ed3af9
			/* If we have not seen this color before, find nearest colormap entry */
Packit ed3af9
			/* and update the cache */
Packit ed3af9
			if (*cachep == 0)
Packit ed3af9
				fill_inverse_cmap (oim, nim, cquantize, c0, c1, c2);
Packit ed3af9
			/* Now emit the colormap index for this cell */
Packit ed3af9
			*outptr++ = (*cachep - 1);
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
METHODDEF (void)
Packit ed3af9
pass2_fs_dither (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize)
Packit ed3af9
{
Packit ed3af9
	hist3d histogram = cquantize->histogram;
Packit ed3af9
	register LOCFSERROR cur0, cur1, cur2;	/* current error or pixel value */
Packit ed3af9
	LOCFSERROR belowerr0, belowerr1, belowerr2;	/* error for pixel below cur */
Packit ed3af9
	LOCFSERROR bpreverr0, bpreverr1, bpreverr2;	/* error for below/prev col */
Packit ed3af9
	register FSERRPTR errorptr;	/* => fserrors[] at column before current */
Packit ed3af9
	histptr cachep;
Packit ed3af9
	int dir;			/* +1 or -1 depending on direction */
Packit ed3af9
	int dir3;			/* 3*dir, for advancing inptr & errorptr */
Packit ed3af9
	int row;
Packit ed3af9
	JDIMENSION col;
Packit ed3af9
	int *inptr;			/* => current input pixel */
Packit ed3af9
	unsigned char *outptr;	/* => current output pixel */
Packit ed3af9
	int width = oim->sx;
Packit ed3af9
	int num_rows = oim->sy;
Packit ed3af9
	int *colormap0 = nim->red;
Packit ed3af9
	int *colormap1 = nim->green;
Packit ed3af9
	int *colormap2 = nim->blue;
Packit ed3af9
	int *error_limit = cquantize->error_limiter;
Packit ed3af9
Packit ed3af9
Packit ed3af9
	SHIFT_TEMPS for (row = 0; row < num_rows; row++) {
Packit ed3af9
		inptr = input_buf[row];
Packit ed3af9
		outptr = output_buf[row];
Packit ed3af9
		if (cquantize->on_odd_row) {
Packit ed3af9
			/* work right to left in this row */
Packit ed3af9
			inptr += (width - 1) * 3;	/* so point to rightmost pixel */
Packit ed3af9
			outptr += width - 1;
Packit ed3af9
			dir = -1;
Packit ed3af9
			dir3 = -3;
Packit ed3af9
			errorptr = cquantize->fserrors + (width + 1) * 3;	/* => entry after last column */
Packit ed3af9
		} else {
Packit ed3af9
			/* work left to right in this row */
Packit ed3af9
			dir = 1;
Packit ed3af9
			dir3 = 3;
Packit ed3af9
			errorptr = cquantize->fserrors;	/* => entry before first real column */
Packit ed3af9
		}
Packit ed3af9
		/* Preset error values: no error propagated to first pixel from left */
Packit ed3af9
		cur0 = cur1 = cur2 = 0;
Packit ed3af9
		/* and no error propagated to row below yet */
Packit ed3af9
		belowerr0 = belowerr1 = belowerr2 = 0;
Packit ed3af9
		bpreverr0 = bpreverr1 = bpreverr2 = 0;
Packit ed3af9
Packit ed3af9
		for (col = width; col > 0; col--) {
Packit ed3af9
Packit ed3af9
			/* If this pixel is transparent, we want to assign it to the special
Packit ed3af9
			 * transparency color index past the end of the palette rather than
Packit ed3af9
			 * go through matching / dithering. */
Packit ed3af9
			if ((oim->transparent >= 0) && (*inptr == oim->transparent)) {
Packit ed3af9
				*outptr = nim->colorsTotal;
Packit ed3af9
				errorptr[0] = 0;
Packit ed3af9
				errorptr[1] = 0;
Packit ed3af9
				errorptr[2] = 0;
Packit ed3af9
				errorptr[3] = 0;
Packit ed3af9
				inptr += dir;
Packit ed3af9
				outptr += dir;
Packit ed3af9
				errorptr += dir3;
Packit ed3af9
				continue;
Packit ed3af9
			}
Packit ed3af9
			/* curN holds the error propagated from the previous pixel on the
Packit ed3af9
			 * current line.  Add the error propagated from the previous line
Packit ed3af9
			 * to form the complete error correction term for this pixel, and
Packit ed3af9
			 * round the error term (which is expressed * 16) to an integer.
Packit ed3af9
			 * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
Packit ed3af9
			 * for either sign of the error value.
Packit ed3af9
			 * Note: errorptr points to *previous* column's array entry.
Packit ed3af9
			 */
Packit ed3af9
			cur0 = RIGHT_SHIFT (cur0 + errorptr[dir3 + 0] + 8, 4);
Packit ed3af9
			cur1 = RIGHT_SHIFT (cur1 + errorptr[dir3 + 1] + 8, 4);
Packit ed3af9
			cur2 = RIGHT_SHIFT (cur2 + errorptr[dir3 + 2] + 8, 4);
Packit ed3af9
			/* Limit the error using transfer function set by init_error_limit.
Packit ed3af9
			 * See comments with init_error_limit for rationale.
Packit ed3af9
			 */
Packit ed3af9
			cur0 = error_limit[cur0];
Packit ed3af9
			cur1 = error_limit[cur1];
Packit ed3af9
			cur2 = error_limit[cur2];
Packit ed3af9
			/* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
Packit ed3af9
			 * The maximum error is +- MAXJSAMPLE (or less with error limiting);
Packit ed3af9
			 * this sets the required size of the range_limit array.
Packit ed3af9
			 */
Packit ed3af9
			cur0 += gdTrueColorGetRed (*inptr);
Packit ed3af9
			cur1 += gdTrueColorGetGreen (*inptr);
Packit ed3af9
			cur2 += gdTrueColorGetBlue (*inptr);
Packit ed3af9
			range_limit (cur0);
Packit ed3af9
			range_limit (cur1);
Packit ed3af9
			range_limit (cur2);
Packit ed3af9
Packit ed3af9
			/* Index into the cache with adjusted pixel value */
Packit ed3af9
			cachep =
Packit ed3af9
			    &histogram[cur0 >> C0_SHIFT][cur1 >> C1_SHIFT][cur2 >> C2_SHIFT];
Packit ed3af9
			/* If we have not seen this color before, find nearest colormap */
Packit ed3af9
			/* entry and update the cache */
Packit ed3af9
			if (*cachep == 0)
Packit ed3af9
				fill_inverse_cmap (oim, nim, cquantize, cur0 >> C0_SHIFT,
Packit ed3af9
						   cur1 >> C1_SHIFT, cur2 >> C2_SHIFT);
Packit ed3af9
			/* Now emit the colormap index for this cell */
Packit ed3af9
			{
Packit ed3af9
				register int pixcode = *cachep - 1;
Packit ed3af9
				*outptr = (JSAMPLE) pixcode;
Packit ed3af9
				/* Compute representation error for this pixel */
Packit ed3af9
#define GETJSAMPLE
Packit ed3af9
				cur0 -= GETJSAMPLE (colormap0[pixcode]);
Packit ed3af9
				cur1 -= GETJSAMPLE (colormap1[pixcode]);
Packit ed3af9
				cur2 -= GETJSAMPLE (colormap2[pixcode]);
Packit ed3af9
#undef GETJSAMPLE
Packit ed3af9
			}
Packit ed3af9
			/* Compute error fractions to be propagated to adjacent pixels.
Packit ed3af9
			 * Add these into the running sums, and simultaneously shift the
Packit ed3af9
			 * next-line error sums left by 1 column.
Packit ed3af9
			 */
Packit ed3af9
			{
Packit ed3af9
				register LOCFSERROR bnexterr, delta;
Packit ed3af9
Packit ed3af9
				bnexterr = cur0;	/* Process component 0 */
Packit ed3af9
				delta = cur0 * 2;
Packit ed3af9
				cur0 += delta;	/* form error * 3 */
Packit ed3af9
				errorptr[0] = (FSERROR) (bpreverr0 + cur0);
Packit ed3af9
				cur0 += delta;	/* form error * 5 */
Packit ed3af9
				bpreverr0 = belowerr0 + cur0;
Packit ed3af9
				belowerr0 = bnexterr;
Packit ed3af9
				cur0 += delta;	/* form error * 7 */
Packit ed3af9
				bnexterr = cur1;	/* Process component 1 */
Packit ed3af9
				delta = cur1 * 2;
Packit ed3af9
				cur1 += delta;	/* form error * 3 */
Packit ed3af9
				errorptr[1] = (FSERROR) (bpreverr1 + cur1);
Packit ed3af9
				cur1 += delta;	/* form error * 5 */
Packit ed3af9
				bpreverr1 = belowerr1 + cur1;
Packit ed3af9
				belowerr1 = bnexterr;
Packit ed3af9
				cur1 += delta;	/* form error * 7 */
Packit ed3af9
				bnexterr = cur2;	/* Process component 2 */
Packit ed3af9
				delta = cur2 * 2;
Packit ed3af9
				cur2 += delta;	/* form error * 3 */
Packit ed3af9
				errorptr[2] = (FSERROR) (bpreverr2 + cur2);
Packit ed3af9
				cur2 += delta;	/* form error * 5 */
Packit ed3af9
				bpreverr2 = belowerr2 + cur2;
Packit ed3af9
				belowerr2 = bnexterr;
Packit ed3af9
				cur2 += delta;	/* form error * 7 */
Packit ed3af9
			}
Packit ed3af9
			/* At this point curN contains the 7/16 error value to be propagated
Packit ed3af9
			 * to the next pixel on the current line, and all the errors for the
Packit ed3af9
			 * next line have been shifted over.  We are therefore ready to move on.
Packit ed3af9
			 */
Packit ed3af9
			inptr += dir;		/* Advance pixel pointers to next column */
Packit ed3af9
			outptr += dir;
Packit ed3af9
			errorptr += dir3;	/* advance errorptr to current column */
Packit ed3af9
		}
Packit ed3af9
		/* Post-loop cleanup: we must unload the final error values into the
Packit ed3af9
		 * final fserrors[] entry.  Note we need not unload belowerrN because
Packit ed3af9
		 * it is for the dummy column before or after the actual array.
Packit ed3af9
		 */
Packit ed3af9
		errorptr[0] = (FSERROR) bpreverr0;	/* unload prev errs into array */
Packit ed3af9
		errorptr[1] = (FSERROR) bpreverr1;
Packit ed3af9
		errorptr[2] = (FSERROR) bpreverr2;
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * Initialize the error-limiting transfer function (lookup table).
Packit ed3af9
 * The raw F-S error computation can potentially compute error values of up to
Packit ed3af9
 * +- MAXJSAMPLE.  But we want the maximum correction applied to a pixel to be
Packit ed3af9
 * much less, otherwise obviously wrong pixels will be created.  (Typical
Packit ed3af9
 * effects include weird fringes at color-area boundaries, isolated bright
Packit ed3af9
 * pixels in a dark area, etc.)  The standard advice for avoiding this problem
Packit ed3af9
 * is to ensure that the "corners" of the color cube are allocated as output
Packit ed3af9
 * colors; then repeated errors in the same direction cannot cause cascading
Packit ed3af9
 * error buildup.  However, that only prevents the error from getting
Packit ed3af9
 * completely out of hand; Aaron Giles reports that error limiting improves
Packit ed3af9
 * the results even with corner colors allocated.
Packit ed3af9
 * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty
Packit ed3af9
 * well, but the smoother transfer function used below is even better.  Thanks
Packit ed3af9
 * to Aaron Giles for this idea.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
LOCAL (void)
Packit ed3af9
init_error_limit (gdImagePtr oim, gdImagePtr nim, my_cquantize_ptr cquantize)
Packit ed3af9
/* Allocate and fill in the error_limiter table */
Packit ed3af9
{
Packit ed3af9
	int *table;
Packit ed3af9
	int in, out;
Packit ed3af9
	(void)oim;
Packit ed3af9
	(void)nim;
Packit ed3af9
Packit ed3af9
	cquantize->error_limiter_storage =
Packit ed3af9
	    (int *) gdMalloc ((MAXJSAMPLE * 2 + 1) * sizeof (int));
Packit ed3af9
	if (!cquantize->error_limiter_storage) {
Packit ed3af9
		return;
Packit ed3af9
	}
Packit ed3af9
	table = cquantize->error_limiter_storage;
Packit ed3af9
Packit ed3af9
	table += MAXJSAMPLE;		/* so can index -MAXJSAMPLE .. +MAXJSAMPLE */
Packit ed3af9
	cquantize->error_limiter = table;
Packit ed3af9
Packit ed3af9
#define STEPSIZE ((MAXJSAMPLE+1)/16)
Packit ed3af9
	/* Map errors 1:1 up to +- MAXJSAMPLE/16 */
Packit ed3af9
	out = 0;
Packit ed3af9
	for (in = 0; in < STEPSIZE; in++, out++) {
Packit ed3af9
		table[in] = out;
Packit ed3af9
		table[-in] = -out;
Packit ed3af9
	}
Packit ed3af9
	/* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */
Packit ed3af9
	for (; in < STEPSIZE * 3; in++, out += (in & 1) ? 0 : 1) {
Packit ed3af9
		table[in] = out;
Packit ed3af9
		table[-in] = -out;
Packit ed3af9
	}
Packit ed3af9
	/* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */
Packit ed3af9
	for (; in <= MAXJSAMPLE; in++) {
Packit ed3af9
		table[in] = out;
Packit ed3af9
		table[-in] = -out;
Packit ed3af9
	}
Packit ed3af9
#undef STEPSIZE
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * Finish up at the end of each pass.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
static void
Packit ed3af9
zeroHistogram (hist3d histogram)
Packit ed3af9
{
Packit ed3af9
	int i;
Packit ed3af9
	/* Zero the histogram or inverse color map */
Packit ed3af9
	for (i = 0; i < HIST_C0_ELEMS; i++) {
Packit ed3af9
		memset (histogram[i],
Packit ed3af9
		        0, HIST_C1_ELEMS * HIST_C2_ELEMS * sizeof (histcell));
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
/**
Packit ed3af9
 * Function: gdImageTrueColorToPaletteSetMethod
Packit ed3af9
 *
Packit ed3af9
 * Selects the quantization method
Packit ed3af9
 *
Packit ed3af9
 * That quantization method is used for all subsequent
Packit ed3af9
 * <gdImageTrueColorToPalette> and <gdImageCreatePaletteFromTrueColor> calls.
Packit ed3af9
 *
Packit ed3af9
 * Parameters:
Packit ed3af9
 *   im     - The image.
Packit ed3af9
 *   method - The quantization method, see <gdPaletteQuantizationMethod>.
Packit ed3af9
 *   speed  - The quantization speed between 1 (highest quality) and
Packit ed3af9
 *            10 (fastest). 0 selects a method-specific default (recommended).
Packit ed3af9
 *   
Packit ed3af9
 * Returns:
Packit ed3af9
 *   Zero if the given method is invalid or not available; non-zero otherwise.
Packit ed3af9
 *
Packit ed3af9
 * See also:
Packit ed3af9
 *   - <gdImageTrueColorToPaletteSetQuality>
Packit ed3af9
 */
Packit ed3af9
BGD_DECLARE(int) gdImageTrueColorToPaletteSetMethod (gdImagePtr im, int method, int speed)
Packit ed3af9
{
Packit ed3af9
#ifndef HAVE_LIBIMAGEQUANT
Packit ed3af9
	if (method == GD_QUANT_LIQ) {
Packit ed3af9
		return FALSE;
Packit ed3af9
	}
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
	if (method >= GD_QUANT_DEFAULT && method <= GD_QUANT_LIQ) {
Packit ed3af9
		im->paletteQuantizationMethod = method;
Packit ed3af9
Packit ed3af9
		if (speed < 0 || speed > 10) {
Packit ed3af9
			speed = 0;
Packit ed3af9
		}
Packit ed3af9
		im->paletteQuantizationSpeed = speed;
Packit ed3af9
	}
Packit ed3af9
	return TRUE;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/**
Packit ed3af9
 * Function: gdImageTrueColorToPaletteSetQuality
Packit ed3af9
 *
Packit ed3af9
 * Chooses a quality range for quantization
Packit ed3af9
 *
Packit ed3af9
 * That quality range is used in all subsequent calls to
Packit ed3af9
 * <gdImageTrueColorToPalette> and <gdImageCreatePaletteFromTrueColor>
Packit ed3af9
 * if the quantization method is <GD_QUANT_LIQ>.
Packit ed3af9
 *
Packit ed3af9
 * Parameters:
Packit ed3af9
 *   im          - The image.
Packit ed3af9
 *   min_quality - The minimum quality in range 1-100 (1 = ugly, 100 = perfect).
Packit ed3af9
 *                 If the palette cannot represent the image with at least
Packit ed3af9
 *                 min_quality, then no conversion is done.
Packit ed3af9
 *   max_quality - The maximum quality in range 1-100 (1 = ugly, 100 = perfect),
Packit ed3af9
 *                 which must be higher than the min_quality. If the palette can
Packit ed3af9
 *                 represent the image with a quality better than max_quality,
Packit ed3af9
 *                 then fewer colors than requested will be used.
Packit ed3af9
 */
Packit ed3af9
BGD_DECLARE(void) gdImageTrueColorToPaletteSetQuality (gdImagePtr im, int min_quality, int max_quality)
Packit ed3af9
{
Packit ed3af9
	if (min_quality >= 0 && min_quality <= 100 &&
Packit ed3af9
	        max_quality >= 0 && max_quality <= 100 && min_quality <= max_quality) {
Packit ed3af9
		im->paletteQuantizationMinQuality = min_quality;
Packit ed3af9
		im->paletteQuantizationMaxQuality = max_quality;
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
static int gdImageTrueColorToPaletteBody (gdImagePtr oim, int dither, int colorsWanted, gdImagePtr *cimP);
Packit ed3af9
Packit ed3af9
/**
Packit ed3af9
 * Function: gdImageCreatePaletteFromTrueColor
Packit ed3af9
 *
Packit ed3af9
 * Creates a new palette image from a truecolor image
Packit ed3af9
 *
Packit ed3af9
 * Parameters:
Packit ed3af9
 *   im           - The image.
Packit ed3af9
 *   dither       - Whether dithering should be applied.
Packit ed3af9
 *   colorsWanted - The number of desired palette entries.
Packit ed3af9
 *
Packit ed3af9
 * Returns:
Packit ed3af9
 *   A newly create palette image; NULL on failure.
Packit ed3af9
 *   
Packit ed3af9
 * See also:
Packit ed3af9
 *   - <gdImageCreatePaletteFromTrueColor>
Packit ed3af9
 *   - <gdImageTrueColorToPaletteSetMethod>
Packit ed3af9
 *   - <gdImageNeuQuant>
Packit ed3af9
 */
Packit ed3af9
BGD_DECLARE(gdImagePtr) gdImageCreatePaletteFromTrueColor (gdImagePtr im, int dither, int colorsWanted)
Packit ed3af9
{
Packit ed3af9
	gdImagePtr nim;
Packit ed3af9
	if (TRUE == gdImageTrueColorToPaletteBody(im, dither, colorsWanted, &nim)) {
Packit ed3af9
		return nim;
Packit ed3af9
	}
Packit ed3af9
	return NULL;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/**
Packit ed3af9
 * Function: gdImageTrueColorToPalette
Packit ed3af9
 *
Packit ed3af9
 * Converts a truecolor image to a palette image
Packit ed3af9
 *
Packit ed3af9
 * Parameters:
Packit ed3af9
 *   im           - The image.
Packit ed3af9
 *   dither       - Whether dithering should be applied.
Packit ed3af9
 *   colorsWanted - The number of desired palette entries.
Packit ed3af9
 *
Packit ed3af9
 * Returns:
Packit ed3af9
 *   Non-zero if the conversion succeeded, zero otherwise.
Packit ed3af9
 *
Packit ed3af9
 * See also:
Packit ed3af9
 *   - <gdImageCreatePaletteFromTrueColor>
Packit ed3af9
 *   - <gdImageTrueColorToPaletteSetMethod>
Packit ed3af9
 *   - <gdImagePaletteToTrueColor>
Packit ed3af9
 */
Packit ed3af9
BGD_DECLARE(int) gdImageTrueColorToPalette (gdImagePtr im, int dither, int colorsWanted)
Packit ed3af9
{
Packit ed3af9
	return gdImageTrueColorToPaletteBody(im, dither, colorsWanted, 0);
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBIMAGEQUANT
Packit ed3af9
/**
Packit ed3af9
  LIQ library needs pixels in RGBA order with alpha 0-255 (opaque 255).
Packit ed3af9
  This callback is run whenever source rows need to be converted from GD's format.
Packit ed3af9
*/
Packit ed3af9
static void convert_gdpixel_to_rgba(liq_color output_row[], int y, int width, void *userinfo)
Packit ed3af9
{
Packit ed3af9
	gdImagePtr oim = userinfo;
Packit ed3af9
	int x;
Packit ed3af9
	for(x = 0; x < width; x++) {
Packit ed3af9
		output_row[x].r = gdTrueColorGetRed(input_buf[y][x]) * 255/gdRedMax;
Packit ed3af9
		output_row[x].g = gdTrueColorGetGreen(input_buf[y][x]) * 255/gdGreenMax;
Packit ed3af9
		output_row[x].b = gdTrueColorGetBlue(input_buf[y][x]) * 255/gdBlueMax;
Packit ed3af9
		int alpha = gdTrueColorGetAlpha(input_buf[y][x]);
Packit ed3af9
		if (gdAlphaOpaque < gdAlphaTransparent) {
Packit ed3af9
			alpha = gdAlphaTransparent - alpha;
Packit ed3af9
		}
Packit ed3af9
		output_row[x].a = alpha * 255/gdAlphaMax;
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
static void free_truecolor_image_data(gdImagePtr oim)
Packit ed3af9
{
Packit ed3af9
	int i;
Packit ed3af9
	oim->trueColor = 0;
Packit ed3af9
	/* Junk the truecolor pixels */
Packit ed3af9
	for (i = 0; i < oim->sy; i++) {
Packit ed3af9
		gdFree (oim->tpixels[i]);
Packit ed3af9
	}
Packit ed3af9
	gdFree (oim->tpixels);
Packit ed3af9
	oim->tpixels = 0;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
 * Module initialization routine for 2-pass color quantization.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
static int gdImageTrueColorToPaletteBody (gdImagePtr oim, int dither, int colorsWanted, gdImagePtr *cimP)
Packit ed3af9
{
Packit ed3af9
	my_cquantize_ptr cquantize = NULL;
Packit ed3af9
	int i, conversionSucceeded=0;
Packit ed3af9
Packit ed3af9
	/* Allocate the JPEG palette-storage */
Packit ed3af9
	size_t arraysize;
Packit ed3af9
	int maxColors = gdMaxColors;
Packit ed3af9
	gdImagePtr nim;
Packit ed3af9
Packit ed3af9
	if (cimP) {
Packit ed3af9
		nim = gdImageCreate(oim->sx, oim->sy);
Packit ed3af9
		*cimP = nim;
Packit ed3af9
		if (!nim) {
Packit ed3af9
			return FALSE;
Packit ed3af9
		}
Packit ed3af9
	} else {
Packit ed3af9
		nim = oim;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (!oim->trueColor) {
Packit ed3af9
		/* (Almost) nothing to do! */
Packit ed3af9
		if (cimP) {
Packit ed3af9
			gdImageCopy(nim, oim, 0, 0, 0, 0, oim->sx, oim->sy);
Packit ed3af9
			*cimP = nim;
Packit ed3af9
		}
Packit ed3af9
		return TRUE;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* If we have a transparent color (the alphaless mode of transparency), we
Packit ed3af9
	 * must reserve a palette entry for it at the end of the palette. */
Packit ed3af9
	if (oim->transparent >= 0) {
Packit ed3af9
		maxColors--;
Packit ed3af9
	}
Packit ed3af9
	if (colorsWanted > maxColors) {
Packit ed3af9
		colorsWanted = maxColors;
Packit ed3af9
	}
Packit ed3af9
	if (!cimP) {
Packit ed3af9
		nim->pixels = gdCalloc (sizeof (unsigned char *), oim->sy);
Packit ed3af9
		if (!nim->pixels) {
Packit ed3af9
			/* No can do */
Packit ed3af9
			goto outOfMemory;
Packit ed3af9
		}
Packit ed3af9
		for (i = 0; (i < nim->sy); i++) {
Packit ed3af9
			nim->pixels[i] = (unsigned char *) gdCalloc (sizeof (unsigned char), oim->sx);
Packit ed3af9
			if (!nim->pixels[i]) {
Packit ed3af9
				goto outOfMemory;
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
Packit ed3af9
	if (oim->paletteQuantizationMethod == GD_QUANT_NEUQUANT) {
Packit ed3af9
		if (cimP) { /* NeuQuant alwasy creates a copy, so the new blank image can't be used */
Packit ed3af9
			gdImageDestroy(nim);
Packit ed3af9
		}
Packit ed3af9
		nim = gdImageNeuQuant(oim, colorsWanted, oim->paletteQuantizationSpeed ? oim->paletteQuantizationSpeed : 2);
Packit ed3af9
		if (cimP) {
Packit ed3af9
			*cimP = nim;
Packit ed3af9
		} 
Packit ed3af9
		if (!nim) {
Packit ed3af9
			return FALSE;
Packit ed3af9
		} else {
Packit ed3af9
			free_truecolor_image_data(oim);
Packit ed3af9
			gdImageCopy(oim, nim, 0, 0, 0, 0, oim->sx, oim->sy);
Packit ed3af9
			gdImageDestroy(nim);
Packit ed3af9
		}
Packit ed3af9
		return TRUE;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBIMAGEQUANT
Packit ed3af9
	if (oim->paletteQuantizationMethod == GD_QUANT_DEFAULT ||
Packit ed3af9
	        oim->paletteQuantizationMethod == GD_QUANT_LIQ) {
Packit ed3af9
		liq_attr *attr = liq_attr_create_with_allocator(gdMalloc, gdFree);
Packit ed3af9
		liq_image *image;
Packit ed3af9
		liq_result *remap;
Packit ed3af9
		int remapped_ok = 0;
Packit ed3af9
Packit ed3af9
		liq_set_max_colors(attr, colorsWanted);
Packit ed3af9
Packit ed3af9
		/* by default make it fast to match speed of previous implementation */
Packit ed3af9
		liq_set_speed(attr, oim->paletteQuantizationSpeed ? oim->paletteQuantizationSpeed : 9);
Packit ed3af9
		if (oim->paletteQuantizationMaxQuality) {
Packit ed3af9
			liq_set_quality(attr, oim->paletteQuantizationMinQuality, oim->paletteQuantizationMaxQuality);
Packit ed3af9
		}
Packit ed3af9
		image = liq_image_create_custom(attr, convert_gdpixel_to_rgba, oim, oim->sx, oim->sy, 0);
Packit ed3af9
		remap = liq_quantize_image(attr, image);
Packit ed3af9
		if (!remap) { /* minimum quality not met, leave image unmodified */
Packit ed3af9
			liq_image_destroy(image);
Packit ed3af9
			liq_attr_destroy(attr);
Packit ed3af9
			goto outOfMemory;
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		liq_set_dithering_level(remap, dither ? 1 : 0);
Packit ed3af9
		if (LIQ_OK == liq_write_remapped_image_rows(remap, image, output_buf)) {
Packit ed3af9
			remapped_ok = 1;
Packit ed3af9
			const liq_palette *pal = liq_get_palette(remap);
Packit ed3af9
			nim->transparent = -1;
Packit ed3af9
			unsigned int icolor;
Packit ed3af9
			for(icolor=0; icolor < pal->count; icolor++) {
Packit ed3af9
				nim->open[icolor] = 0;
Packit ed3af9
				nim->red[icolor] = pal->entries[icolor].r * gdRedMax/255;
Packit ed3af9
				nim->green[icolor] = pal->entries[icolor].g * gdGreenMax/255;
Packit ed3af9
				nim->blue[icolor] = pal->entries[icolor].b * gdBlueMax/255;
Packit ed3af9
				int alpha = pal->entries[icolor].a * gdAlphaMax/255;
Packit ed3af9
				if (gdAlphaOpaque < gdAlphaTransparent) {
Packit ed3af9
					alpha = gdAlphaTransparent - alpha;
Packit ed3af9
				}
Packit ed3af9
				nim->alpha[icolor] = alpha;
Packit ed3af9
				if (nim->transparent == -1 && alpha == gdAlphaTransparent) {
Packit ed3af9
					nim->transparent = icolor;
Packit ed3af9
				}
Packit ed3af9
			}
Packit ed3af9
			nim->colorsTotal = pal->count;
Packit ed3af9
		}
Packit ed3af9
		liq_result_destroy(remap);
Packit ed3af9
		liq_image_destroy(image);
Packit ed3af9
		liq_attr_destroy(attr);
Packit ed3af9
Packit ed3af9
		if (remapped_ok) {
Packit ed3af9
			if (!cimP) {
Packit ed3af9
				free_truecolor_image_data(oim);
Packit ed3af9
			}
Packit ed3af9
			return TRUE;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
	cquantize = (my_cquantize_ptr) gdCalloc (sizeof (my_cquantizer), 1);
Packit ed3af9
	if (!cquantize) {
Packit ed3af9
		/* No can do */
Packit ed3af9
		goto outOfMemory;
Packit ed3af9
	}
Packit ed3af9
	cquantize->fserrors = NULL;	/* flag optional arrays not allocated */
Packit ed3af9
	cquantize->error_limiter = NULL;
Packit ed3af9
Packit ed3af9
Packit ed3af9
	/* Allocate the histogram/inverse colormap storage */
Packit ed3af9
	cquantize->histogram = (hist3d) gdMalloc (HIST_C0_ELEMS * sizeof (hist2d));
Packit ed3af9
	for (i = 0; i < HIST_C0_ELEMS; i++) {
Packit ed3af9
		cquantize->histogram[i] =
Packit ed3af9
		    (hist2d) gdMalloc (HIST_C1_ELEMS * HIST_C2_ELEMS * sizeof (histcell));
Packit ed3af9
		if (!cquantize->histogram[i]) {
Packit ed3af9
			goto outOfMemory;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
Packit ed3af9
	cquantize->fserrors = (FSERRPTR) gdMalloc (3 * sizeof (FSERROR));
Packit ed3af9
	init_error_limit (oim, nim, cquantize);
Packit ed3af9
	arraysize = (size_t) ((nim->sx + 2) * (3 * sizeof (FSERROR)));
Packit ed3af9
	/* Allocate Floyd-Steinberg workspace. */
Packit ed3af9
	cquantize->fserrors = gdReallocEx(cquantize->fserrors, arraysize);
Packit ed3af9
	if (!cquantize->fserrors) {
Packit ed3af9
		goto outOfMemory;
Packit ed3af9
	}
Packit ed3af9
	memset(cquantize->fserrors, 0, arraysize);
Packit ed3af9
	cquantize->on_odd_row = FALSE;
Packit ed3af9
Packit ed3af9
	/* Do the work! */
Packit ed3af9
	zeroHistogram (cquantize->histogram);
Packit ed3af9
	prescan_quantize (oim, nim, cquantize);
Packit ed3af9
	/* TBB 2.0.5: pass colorsWanted, not 256! */
Packit ed3af9
	select_colors (oim, nim, cquantize, colorsWanted);
Packit ed3af9
	zeroHistogram (cquantize->histogram);
Packit ed3af9
	if (dither) {
Packit ed3af9
		pass2_fs_dither (oim, nim, cquantize);
Packit ed3af9
	} else {
Packit ed3af9
		pass2_no_dither (oim, nim, cquantize);
Packit ed3af9
	}
Packit ed3af9
#if 0				/* 2.0.12; we no longer attempt full alpha in palettes */
Packit ed3af9
	if (cquantize->transparentIsPresent) {
Packit ed3af9
		int mt = -1;
Packit ed3af9
		int mtIndex = -1;
Packit ed3af9
		for (i = 0; (i < im->colorsTotal); i++) {
Packit ed3af9
			if (im->alpha[i] > mt) {
Packit ed3af9
				mtIndex = i;
Packit ed3af9
				mt = im->alpha[i];
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
		for (i = 0; (i < im->colorsTotal); i++) {
Packit ed3af9
			if (im->alpha[i] == mt) {
Packit ed3af9
				im->alpha[i] = gdAlphaTransparent;
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
	if (cquantize->opaqueIsPresent) {
Packit ed3af9
		int mo = 128;
Packit ed3af9
		int moIndex = -1;
Packit ed3af9
		for (i = 0; (i < im->colorsTotal); i++) {
Packit ed3af9
			if (im->alpha[i] < mo) {
Packit ed3af9
				moIndex = i;
Packit ed3af9
				mo = im->alpha[i];
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
		for (i = 0; (i < im->colorsTotal); i++) {
Packit ed3af9
			if (im->alpha[i] == mo) {
Packit ed3af9
				im->alpha[i] = gdAlphaOpaque;
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
	/* If we had a 'transparent' color, increment the color count so it's
Packit ed3af9
	 * officially in the palette and convert the transparent variable to point to
Packit ed3af9
	 * an index rather than a color (Its data already exists and transparent
Packit ed3af9
	 * pixels have already been mapped to it by this point, it is done late as to
Packit ed3af9
	 * avoid color matching / dithering with it). */
Packit ed3af9
	if (oim->transparent >= 0) {
Packit ed3af9
		nim->transparent = nim->colorsTotal;
Packit ed3af9
		nim->colorsTotal++;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* Success! Get rid of the truecolor image data. */
Packit ed3af9
	conversionSucceeded = TRUE;
Packit ed3af9
	if (!cimP) {
Packit ed3af9
		free_truecolor_image_data(oim);
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	goto freeQuantizeData;
Packit ed3af9
	/* Tediously free stuff. */
Packit ed3af9
outOfMemory:
Packit ed3af9
	conversionSucceeded = FALSE;
Packit ed3af9
	if (oim->trueColor) {
Packit ed3af9
		if (!cimP) {
Packit ed3af9
			/* On failure only */
Packit ed3af9
			if (nim->pixels) {
Packit ed3af9
				for (i = 0; i < nim->sy; i++) {
Packit ed3af9
					if (nim->pixels[i]) {
Packit ed3af9
						gdFree (nim->pixels[i]);
Packit ed3af9
					}
Packit ed3af9
				}
Packit ed3af9
				gdFree (nim->pixels);
Packit ed3af9
			}
Packit ed3af9
			nim->pixels = NULL;
Packit ed3af9
		} else {
Packit ed3af9
			gdImageDestroy(nim);
Packit ed3af9
			*cimP = 0;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
freeQuantizeData:
Packit ed3af9
	if (cquantize) {
Packit ed3af9
		if (cquantize->histogram) {
Packit ed3af9
			for (i = 0; i < HIST_C0_ELEMS; i++) {
Packit ed3af9
				if (cquantize->histogram[i]) {
Packit ed3af9
					gdFree (cquantize->histogram[i]);
Packit ed3af9
				}
Packit ed3af9
			}
Packit ed3af9
			gdFree (cquantize->histogram);
Packit ed3af9
		}
Packit ed3af9
		if (cquantize->fserrors) {
Packit ed3af9
			gdFree (cquantize->fserrors);
Packit ed3af9
		}
Packit ed3af9
		if (cquantize->error_limiter_storage) {
Packit ed3af9
			gdFree (cquantize->error_limiter_storage);
Packit ed3af9
		}
Packit ed3af9
		gdFree (cquantize);
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	return conversionSucceeded;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
#endif