Blame tools/tiffmedian.c

Packit 7838c8
/* $Id: tiffmedian.c,v 1.13 2015-06-21 01:09:11 bfriesen Exp $ */
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Apply median cut on an image.
Packit 7838c8
 *
Packit 7838c8
 * tiffmedian [-c n] [-f] input output
Packit 7838c8
 *     -C n		- set colortable size.  Default is 256.
Packit 7838c8
 *     -f		- use Floyd-Steinberg dithering.
Packit 7838c8
 *     -c lzw		- compress output with LZW 
Packit 7838c8
 *     -c none		- use no compression on output
Packit 7838c8
 *     -c packbits	- use packbits compression on output
Packit 7838c8
 *     -r n		- create output with n rows/strip of data
Packit 7838c8
 * (by default the compression scheme and rows/strip are taken
Packit 7838c8
 *  from the input file)
Packit 7838c8
 *
Packit 7838c8
 * Notes:
Packit 7838c8
 *
Packit 7838c8
 * [1] Floyd-Steinberg dither:
Packit 7838c8
 *  I should point out that the actual fractions we used were, assuming
Packit 7838c8
 *  you are at X, moving left to right:
Packit 7838c8
 *
Packit 7838c8
 *		    X     7/16
Packit 7838c8
 *	     3/16   5/16  1/16    
Packit 7838c8
 *
Packit 7838c8
 *  Note that the error goes to four neighbors, not three.  I think this
Packit 7838c8
 *  will probably do better (at least for black and white) than the
Packit 7838c8
 *  3/8-3/8-1/4 distribution, at the cost of greater processing.  I have
Packit 7838c8
 *  seen the 3/8-3/8-1/4 distribution described as "our" algorithm before,
Packit 7838c8
 *  but I have no idea who the credit really belongs to.
Packit 7838c8
Packit 7838c8
 *  Also, I should add that if you do zig-zag scanning (see my immediately
Packit 7838c8
 *  previous message), it is sufficient (but not quite as good) to send
Packit 7838c8
 *  half the error one pixel ahead (e.g. to the right on lines you scan
Packit 7838c8
 *  left to right), and half one pixel straight down.  Again, this is for
Packit 7838c8
 *  black and white;  I've not tried it with color.
Packit 7838c8
 *  -- 
Packit 7838c8
 *					    Lou Steinberg
Packit 7838c8
 *
Packit 7838c8
 * [2] Color Image Quantization for Frame Buffer Display, Paul Heckbert,
Packit 7838c8
 *	Siggraph '82 proceedings, pp. 297-307
Packit 7838c8
 */
Packit 7838c8
Packit 7838c8
#include "tif_config.h"
Packit 7838c8
Packit 7838c8
#include <stdio.h>
Packit 7838c8
#include <stdlib.h>
Packit 7838c8
#include <string.h>
Packit 7838c8
Packit 7838c8
#ifdef HAVE_UNISTD_H
Packit 7838c8
# include <unistd.h>
Packit 7838c8
#endif
Packit 7838c8
Packit 7838c8
#ifdef NEED_LIBPORT
Packit 7838c8
# include "libport.h"
Packit 7838c8
#endif
Packit 7838c8
Packit 7838c8
#include "tiffio.h"
Packit 7838c8
Packit 7838c8
#define	MAX_CMAP_SIZE	256
Packit 7838c8
Packit 7838c8
#define	streq(a,b)	(strcmp(a,b) == 0)
Packit 7838c8
#define	strneq(a,b,n)	(strncmp(a,b,n) == 0)
Packit 7838c8
Packit 7838c8
#define	COLOR_DEPTH	8
Packit 7838c8
#define	MAX_COLOR	256
Packit 7838c8
Packit 7838c8
#define	B_DEPTH		5		/* # bits/pixel to use */
Packit 7838c8
#define	B_LEN		(1L<
Packit 7838c8
Packit 7838c8
#define	C_DEPTH		2
Packit 7838c8
#define	C_LEN		(1L<
Packit 7838c8
Packit 7838c8
#define	COLOR_SHIFT	(COLOR_DEPTH-B_DEPTH)
Packit 7838c8
Packit 7838c8
typedef	struct colorbox {
Packit 7838c8
	struct	colorbox *next, *prev;
Packit 7838c8
	int	rmin, rmax;
Packit 7838c8
	int	gmin, gmax;
Packit 7838c8
	int	bmin, bmax;
Packit 7838c8
	uint32	total;
Packit 7838c8
} Colorbox;
Packit 7838c8
Packit 7838c8
typedef struct {
Packit 7838c8
	int	num_ents;
Packit 7838c8
	int	entries[MAX_CMAP_SIZE][2];
Packit 7838c8
} C_cell;
Packit 7838c8
Packit 7838c8
uint16	rm[MAX_CMAP_SIZE], gm[MAX_CMAP_SIZE], bm[MAX_CMAP_SIZE];
Packit 7838c8
int	num_colors;
Packit 7838c8
uint32	histogram[B_LEN][B_LEN][B_LEN];
Packit 7838c8
Colorbox *freeboxes;
Packit 7838c8
Colorbox *usedboxes;
Packit 7838c8
C_cell	**ColorCells;
Packit 7838c8
TIFF	*in, *out;
Packit 7838c8
uint32	rowsperstrip = (uint32) -1;
Packit 7838c8
uint16	compression = (uint16) -1;
Packit 7838c8
uint16	bitspersample = 1;
Packit 7838c8
uint16	samplesperpixel;
Packit 7838c8
uint32	imagewidth;
Packit 7838c8
uint32	imagelength;
Packit 7838c8
uint16	predictor = 0;
Packit 7838c8
Packit 7838c8
static	void get_histogram(TIFF*, Colorbox*);
Packit 7838c8
static	void splitbox(Colorbox*);
Packit 7838c8
static	void shrinkbox(Colorbox*);
Packit 7838c8
static	void map_colortable(void);
Packit 7838c8
static	void quant(TIFF*, TIFF*);
Packit 7838c8
static	void quant_fsdither(TIFF*, TIFF*);
Packit 7838c8
static	Colorbox* largest_box(void);
Packit 7838c8
Packit 7838c8
static	void usage(void);
Packit 7838c8
static	int processCompressOptions(char*);
Packit 7838c8
Packit 7838c8
#define	CopyField(tag, v) \
Packit 7838c8
	if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
Packit 7838c8
Packit 7838c8
int
Packit 7838c8
main(int argc, char* argv[])
Packit 7838c8
{
Packit 7838c8
	int i, dither = 0;
Packit 7838c8
	uint16 shortv, config, photometric;
Packit 7838c8
	Colorbox *box_list, *ptr;
Packit 7838c8
	float floatv;
Packit 7838c8
	uint32 longv;
Packit 7838c8
	int c;
Packit 7838c8
#if !HAVE_DECL_OPTARG
Packit 7838c8
	extern int optind;
Packit 7838c8
	extern char* optarg;
Packit 7838c8
#endif
Packit 7838c8
Packit 7838c8
	num_colors = MAX_CMAP_SIZE;
Packit 7838c8
	while ((c = getopt(argc, argv, "c:C:r:f")) != -1)
Packit 7838c8
		switch (c) {
Packit 7838c8
		case 'c':		/* compression scheme */
Packit 7838c8
			if (!processCompressOptions(optarg))
Packit 7838c8
				usage();
Packit 7838c8
			break;
Packit 7838c8
		case 'C':		/* set colormap size */
Packit 7838c8
			num_colors = atoi(optarg);
Packit 7838c8
			if (num_colors > MAX_CMAP_SIZE) {
Packit 7838c8
				fprintf(stderr,
Packit 7838c8
				   "-c: colormap too big, max %d\n",
Packit 7838c8
				   MAX_CMAP_SIZE);
Packit 7838c8
				usage();
Packit 7838c8
			}
Packit 7838c8
			break;
Packit 7838c8
		case 'f':		/* dither */
Packit 7838c8
			dither = 1;
Packit 7838c8
			break;
Packit 7838c8
		case 'r':		/* rows/strip */
Packit 7838c8
			rowsperstrip = atoi(optarg);
Packit 7838c8
			break;
Packit 7838c8
		case '?':
Packit 7838c8
			usage();
Packit 7838c8
			/*NOTREACHED*/
Packit 7838c8
		}
Packit 7838c8
	if (argc - optind != 2)
Packit 7838c8
		usage();
Packit 7838c8
	in = TIFFOpen(argv[optind], "r");
Packit 7838c8
	if (in == NULL)
Packit 7838c8
		return (-1);
Packit 7838c8
	TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &imagewidth);
Packit 7838c8
	TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength);
Packit 7838c8
	TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample);
Packit 7838c8
	TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
Packit 7838c8
	if (bitspersample != 8 && bitspersample != 16) {
Packit 7838c8
		fprintf(stderr, "%s: Image must have at least 8-bits/sample\n",
Packit 7838c8
		    argv[optind]);
Packit 7838c8
		return (-3);
Packit 7838c8
	}
Packit 7838c8
	if (!TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric) ||
Packit 7838c8
	    photometric != PHOTOMETRIC_RGB || samplesperpixel < 3) {
Packit 7838c8
		fprintf(stderr, "%s: Image must have RGB data\n", argv[optind]);
Packit 7838c8
		return (-4);
Packit 7838c8
	}
Packit 7838c8
	TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config);
Packit 7838c8
	if (config != PLANARCONFIG_CONTIG) {
Packit 7838c8
		fprintf(stderr, "%s: Can only handle contiguous data packing\n",
Packit 7838c8
		    argv[optind]);
Packit 7838c8
		return (-5);
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
	/*
Packit 7838c8
	 * STEP 1:  create empty boxes
Packit 7838c8
	 */
Packit 7838c8
	usedboxes = NULL;
Packit 7838c8
	box_list = freeboxes = (Colorbox *)_TIFFmalloc(num_colors*sizeof (Colorbox));
Packit 7838c8
	freeboxes[0].next = &freeboxes[1];
Packit 7838c8
	freeboxes[0].prev = NULL;
Packit 7838c8
	for (i = 1; i < num_colors-1; ++i) {
Packit 7838c8
		freeboxes[i].next = &freeboxes[i+1];
Packit 7838c8
		freeboxes[i].prev = &freeboxes[i-1];
Packit 7838c8
	}
Packit 7838c8
	freeboxes[num_colors-1].next = NULL;
Packit 7838c8
	freeboxes[num_colors-1].prev = &freeboxes[num_colors-2];
Packit 7838c8
Packit 7838c8
	/*
Packit 7838c8
	 * STEP 2: get histogram, initialize first box
Packit 7838c8
	 */
Packit 7838c8
	ptr = freeboxes;
Packit 7838c8
	freeboxes = ptr->next;
Packit 7838c8
	if (freeboxes)
Packit 7838c8
		freeboxes->prev = NULL;
Packit 7838c8
	ptr->next = usedboxes;
Packit 7838c8
	usedboxes = ptr;
Packit 7838c8
	if (ptr->next)
Packit 7838c8
		ptr->next->prev = ptr;
Packit 7838c8
	get_histogram(in, ptr);
Packit 7838c8
Packit 7838c8
	/*
Packit 7838c8
	 * STEP 3: continually subdivide boxes until no more free
Packit 7838c8
	 * boxes remain or until all colors assigned.
Packit 7838c8
	 */
Packit 7838c8
	while (freeboxes != NULL) {
Packit 7838c8
		ptr = largest_box();
Packit 7838c8
		if (ptr != NULL)
Packit 7838c8
			splitbox(ptr);
Packit 7838c8
		else
Packit 7838c8
			freeboxes = NULL;
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
	/*
Packit 7838c8
	 * STEP 4: assign colors to all boxes
Packit 7838c8
	 */
Packit 7838c8
	for (i = 0, ptr = usedboxes; ptr != NULL; ++i, ptr = ptr->next) {
Packit 7838c8
		rm[i] = ((ptr->rmin + ptr->rmax) << COLOR_SHIFT) / 2;
Packit 7838c8
		gm[i] = ((ptr->gmin + ptr->gmax) << COLOR_SHIFT) / 2;
Packit 7838c8
		bm[i] = ((ptr->bmin + ptr->bmax) << COLOR_SHIFT) / 2;
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
	/* We're done with the boxes now */
Packit 7838c8
	_TIFFfree(box_list);
Packit 7838c8
	freeboxes = usedboxes = NULL;
Packit 7838c8
Packit 7838c8
	/*
Packit 7838c8
	 * STEP 5: scan histogram and map all values to closest color
Packit 7838c8
	 */
Packit 7838c8
	/* 5a: create cell list as described in Heckbert[2] */
Packit 7838c8
	ColorCells = (C_cell **)_TIFFmalloc(C_LEN*C_LEN*C_LEN*sizeof (C_cell*));
Packit 7838c8
	_TIFFmemset(ColorCells, 0, C_LEN*C_LEN*C_LEN*sizeof (C_cell*));
Packit 7838c8
	/* 5b: create mapping from truncated pixel space to color
Packit 7838c8
	   table entries */
Packit 7838c8
	map_colortable();
Packit 7838c8
Packit 7838c8
	/*
Packit 7838c8
	 * STEP 6: scan image, match input values to table entries
Packit 7838c8
	 */
Packit 7838c8
	out = TIFFOpen(argv[optind+1], "w");
Packit 7838c8
	if (out == NULL)
Packit 7838c8
		return (-2);
Packit 7838c8
Packit 7838c8
	CopyField(TIFFTAG_SUBFILETYPE, longv);
Packit 7838c8
	CopyField(TIFFTAG_IMAGEWIDTH, longv);
Packit 7838c8
	TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (short)COLOR_DEPTH);
Packit 7838c8
	if (compression != (uint16)-1) {
Packit 7838c8
		TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
Packit 7838c8
		switch (compression) {
Packit 7838c8
		case COMPRESSION_LZW:
Packit 7838c8
		case COMPRESSION_DEFLATE:
Packit 7838c8
			if (predictor != 0)
Packit 7838c8
				TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
Packit 7838c8
			break;
Packit 7838c8
		}
Packit 7838c8
	} else
Packit 7838c8
		CopyField(TIFFTAG_COMPRESSION, compression);
Packit 7838c8
	TIFFSetField(out, TIFFTAG_PHOTOMETRIC, (short)PHOTOMETRIC_PALETTE);
Packit 7838c8
	CopyField(TIFFTAG_ORIENTATION, shortv);
Packit 7838c8
	TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, (short)1);
Packit 7838c8
	CopyField(TIFFTAG_PLANARCONFIG, shortv);
Packit 7838c8
	TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
Packit 7838c8
	    TIFFDefaultStripSize(out, rowsperstrip));
Packit 7838c8
	CopyField(TIFFTAG_MINSAMPLEVALUE, shortv);
Packit 7838c8
	CopyField(TIFFTAG_MAXSAMPLEVALUE, shortv);
Packit 7838c8
	CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
Packit 7838c8
	CopyField(TIFFTAG_XRESOLUTION, floatv);
Packit 7838c8
	CopyField(TIFFTAG_YRESOLUTION, floatv);
Packit 7838c8
	CopyField(TIFFTAG_XPOSITION, floatv);
Packit 7838c8
	CopyField(TIFFTAG_YPOSITION, floatv);
Packit 7838c8
Packit 7838c8
	if (dither)
Packit 7838c8
		quant_fsdither(in, out);
Packit 7838c8
	else
Packit 7838c8
		quant(in, out);
Packit 7838c8
	/*
Packit 7838c8
	 * Scale colormap to TIFF-required 16-bit values.
Packit 7838c8
	 */
Packit 7838c8
#define	SCALE(x)	(((x)*((1L<<16)-1))/255)
Packit 7838c8
	for (i = 0; i < MAX_CMAP_SIZE; ++i) {
Packit 7838c8
		rm[i] = SCALE(rm[i]);
Packit 7838c8
		gm[i] = SCALE(gm[i]);
Packit 7838c8
		bm[i] = SCALE(bm[i]);
Packit 7838c8
	}
Packit 7838c8
	TIFFSetField(out, TIFFTAG_COLORMAP, rm, gm, bm);
Packit 7838c8
	(void) TIFFClose(out);
Packit 7838c8
	return (0);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static int
Packit 7838c8
processCompressOptions(char* opt)
Packit 7838c8
{
Packit 7838c8
	if (streq(opt, "none"))
Packit 7838c8
		compression = COMPRESSION_NONE;
Packit 7838c8
	else if (streq(opt, "packbits"))
Packit 7838c8
		compression = COMPRESSION_PACKBITS;
Packit 7838c8
	else if (strneq(opt, "lzw", 3)) {
Packit 7838c8
		char* cp = strchr(opt, ':');
Packit 7838c8
		if (cp)
Packit 7838c8
			predictor = atoi(cp+1);
Packit 7838c8
		compression = COMPRESSION_LZW;
Packit 7838c8
	} else if (strneq(opt, "zip", 3)) {
Packit 7838c8
		char* cp = strchr(opt, ':');
Packit 7838c8
		if (cp)
Packit 7838c8
			predictor = atoi(cp+1);
Packit 7838c8
		compression = COMPRESSION_DEFLATE;
Packit 7838c8
	} else
Packit 7838c8
		return (0);
Packit 7838c8
	return (1);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
char* stuff[] = {
Packit 7838c8
"usage: tiffmedian [options] input.tif output.tif",
Packit 7838c8
"where options are:",
Packit 7838c8
" -r #		make each strip have no more than # rows",
Packit 7838c8
" -C #		create a colormap with # entries",
Packit 7838c8
" -f		use Floyd-Steinberg dithering",
Packit 7838c8
" -c lzw[:opts]	compress output with Lempel-Ziv & Welch encoding",
Packit 7838c8
" -c zip[:opts]	compress output with deflate encoding",
Packit 7838c8
" -c packbits	compress output with packbits encoding",
Packit 7838c8
" -c none	use no compression algorithm on output",
Packit 7838c8
"",
Packit 7838c8
"LZW and deflate options:",
Packit 7838c8
" #		set predictor value",
Packit 7838c8
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
Packit 7838c8
NULL
Packit 7838c8
};
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
usage(void)
Packit 7838c8
{
Packit 7838c8
	char buf[BUFSIZ];
Packit 7838c8
	int i;
Packit 7838c8
Packit 7838c8
	setbuf(stderr, buf);
Packit 7838c8
        fprintf(stderr, "%s\n\n", TIFFGetVersion());
Packit 7838c8
	for (i = 0; stuff[i] != NULL; i++)
Packit 7838c8
		fprintf(stderr, "%s\n", stuff[i]);
Packit 7838c8
	exit(-1);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
get_histogram(TIFF* in, Colorbox* box)
Packit 7838c8
{
Packit 7838c8
	register unsigned char *inptr;
Packit 7838c8
	register int red, green, blue;
Packit 7838c8
	register uint32 j, i;
Packit 7838c8
	unsigned char *inputline;
Packit 7838c8
Packit 7838c8
	inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
Packit 7838c8
	if (inputline == NULL) {
Packit 7838c8
		fprintf(stderr, "No space for scanline buffer\n");
Packit 7838c8
		exit(-1);
Packit 7838c8
	}
Packit 7838c8
	box->rmin = box->gmin = box->bmin = 999;
Packit 7838c8
	box->rmax = box->gmax = box->bmax = -1;
Packit 7838c8
	box->total = imagewidth * imagelength;
Packit 7838c8
Packit 7838c8
	{ register uint32 *ptr = &histogram[0][0][0];
Packit 7838c8
	  for (i = B_LEN*B_LEN*B_LEN; i-- > 0;)
Packit 7838c8
		*ptr++ = 0;
Packit 7838c8
	}
Packit 7838c8
	for (i = 0; i < imagelength; i++) {
Packit 7838c8
		if (TIFFReadScanline(in, inputline, i, 0) <= 0)
Packit 7838c8
			break;
Packit 7838c8
		inptr = inputline;
Packit 7838c8
		for (j = imagewidth; j-- > 0;) {
Packit 7838c8
			red = (*inptr++) & 0xff >> COLOR_SHIFT;
Packit 7838c8
			green = (*inptr++) & 0xff >> COLOR_SHIFT;
Packit 7838c8
			blue = (*inptr++) & 0xff >> COLOR_SHIFT;
Packit 7838c8
                        if ((red | green | blue) >= B_LEN) {
Packit 7838c8
                                fprintf(stderr,
Packit 7838c8
                                        "Logic error. "
Packit 7838c8
                                        "Histogram array overflow!\n");
Packit 7838c8
                                exit(-6);
Packit 7838c8
                        }
Packit 7838c8
			if (red < box->rmin)
Packit 7838c8
				box->rmin = red;
Packit 7838c8
		        if (red > box->rmax)
Packit 7838c8
				box->rmax = red;
Packit 7838c8
		        if (green < box->gmin)
Packit 7838c8
				box->gmin = green;
Packit 7838c8
		        if (green > box->gmax)
Packit 7838c8
				box->gmax = green;
Packit 7838c8
		        if (blue < box->bmin)
Packit 7838c8
				box->bmin = blue;
Packit 7838c8
		        if (blue > box->bmax)
Packit 7838c8
				box->bmax = blue;
Packit 7838c8
		        histogram[red][green][blue]++;
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
	_TIFFfree(inputline);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static Colorbox *
Packit 7838c8
largest_box(void)
Packit 7838c8
{
Packit 7838c8
	register Colorbox *p, *b;
Packit 7838c8
	register uint32 size;
Packit 7838c8
Packit 7838c8
	b = NULL;
Packit 7838c8
	size = 0;
Packit 7838c8
	for (p = usedboxes; p != NULL; p = p->next)
Packit 7838c8
		if ((p->rmax > p->rmin || p->gmax > p->gmin ||
Packit 7838c8
		    p->bmax > p->bmin) &&  p->total > size)
Packit 7838c8
		        size = (b = p)->total;
Packit 7838c8
	return (b);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
splitbox(Colorbox* ptr)
Packit 7838c8
{
Packit 7838c8
	uint32		hist2[B_LEN];
Packit 7838c8
	int		first=0, last=0;
Packit 7838c8
	register Colorbox	*new;
Packit 7838c8
	register uint32	*iptr, *histp;
Packit 7838c8
	register int	i, j;
Packit 7838c8
	register int	ir,ig,ib;
Packit 7838c8
	register uint32 sum, sum1, sum2;
Packit 7838c8
	enum { RED, GREEN, BLUE } axis;
Packit 7838c8
Packit 7838c8
	/*
Packit 7838c8
	 * See which axis is the largest, do a histogram along that
Packit 7838c8
	 * axis.  Split at median point.  Contract both new boxes to
Packit 7838c8
	 * fit points and return
Packit 7838c8
	 */
Packit 7838c8
	i = ptr->rmax - ptr->rmin;
Packit 7838c8
	if (i >= ptr->gmax - ptr->gmin && i >= ptr->bmax - ptr->bmin)
Packit 7838c8
		axis = RED;
Packit 7838c8
	else if (ptr->gmax - ptr->gmin >= ptr->bmax - ptr->bmin)
Packit 7838c8
		axis = GREEN;
Packit 7838c8
	else
Packit 7838c8
		axis = BLUE;
Packit 7838c8
	/* get histogram along longest axis */
Packit 7838c8
	switch (axis) {
Packit 7838c8
	case RED:
Packit 7838c8
		histp = &hist2[ptr->rmin];
Packit 7838c8
	        for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
Packit 7838c8
			*histp = 0;
Packit 7838c8
			for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
Packit 7838c8
				iptr = &histogram[ir][ig][ptr->bmin];
Packit 7838c8
				for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
Packit 7838c8
					*histp += *iptr++;
Packit 7838c8
			}
Packit 7838c8
			histp++;
Packit 7838c8
	        }
Packit 7838c8
	        first = ptr->rmin;
Packit 7838c8
		last = ptr->rmax;
Packit 7838c8
	        break;
Packit 7838c8
	case GREEN:
Packit 7838c8
	        histp = &hist2[ptr->gmin];
Packit 7838c8
	        for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
Packit 7838c8
			*histp = 0;
Packit 7838c8
			for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
Packit 7838c8
				iptr = &histogram[ir][ig][ptr->bmin];
Packit 7838c8
				for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
Packit 7838c8
					*histp += *iptr++;
Packit 7838c8
			}
Packit 7838c8
			histp++;
Packit 7838c8
	        }
Packit 7838c8
	        first = ptr->gmin;
Packit 7838c8
		last = ptr->gmax;
Packit 7838c8
	        break;
Packit 7838c8
	case BLUE:
Packit 7838c8
	        histp = &hist2[ptr->bmin];
Packit 7838c8
	        for (ib = ptr->bmin; ib <= ptr->bmax; ++ib) {
Packit 7838c8
			*histp = 0;
Packit 7838c8
			for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
Packit 7838c8
				iptr = &histogram[ir][ptr->gmin][ib];
Packit 7838c8
				for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
Packit 7838c8
					*histp += *iptr;
Packit 7838c8
					iptr += B_LEN;
Packit 7838c8
				}
Packit 7838c8
			}
Packit 7838c8
			histp++;
Packit 7838c8
	        }
Packit 7838c8
	        first = ptr->bmin;
Packit 7838c8
		last = ptr->bmax;
Packit 7838c8
	        break;
Packit 7838c8
	}
Packit 7838c8
	/* find median point */
Packit 7838c8
	sum2 = ptr->total / 2;
Packit 7838c8
	histp = &hist2[first];
Packit 7838c8
	sum = 0;
Packit 7838c8
	for (i = first; i <= last && (sum += *histp++) < sum2; ++i)
Packit 7838c8
		;
Packit 7838c8
	if (i == first)
Packit 7838c8
		i++;
Packit 7838c8
Packit 7838c8
	/* Create new box, re-allocate points */
Packit 7838c8
	new = freeboxes;
Packit 7838c8
	freeboxes = new->next;
Packit 7838c8
	if (freeboxes)
Packit 7838c8
		freeboxes->prev = NULL;
Packit 7838c8
	if (usedboxes)
Packit 7838c8
		usedboxes->prev = new;
Packit 7838c8
	new->next = usedboxes;
Packit 7838c8
	usedboxes = new;
Packit 7838c8
Packit 7838c8
	histp = &hist2[first];
Packit 7838c8
	for (sum1 = 0, j = first; j < i; j++)
Packit 7838c8
		sum1 += *histp++;
Packit 7838c8
	for (sum2 = 0, j = i; j <= last; j++)
Packit 7838c8
	    sum2 += *histp++;
Packit 7838c8
	new->total = sum1;
Packit 7838c8
	ptr->total = sum2;
Packit 7838c8
Packit 7838c8
	new->rmin = ptr->rmin;
Packit 7838c8
	new->rmax = ptr->rmax;
Packit 7838c8
	new->gmin = ptr->gmin;
Packit 7838c8
	new->gmax = ptr->gmax;
Packit 7838c8
	new->bmin = ptr->bmin;
Packit 7838c8
	new->bmax = ptr->bmax;
Packit 7838c8
	switch (axis) {
Packit 7838c8
	case RED:
Packit 7838c8
		new->rmax = i-1;
Packit 7838c8
	        ptr->rmin = i;
Packit 7838c8
	        break;
Packit 7838c8
	case GREEN:
Packit 7838c8
	        new->gmax = i-1;
Packit 7838c8
	        ptr->gmin = i;
Packit 7838c8
	        break;
Packit 7838c8
	case BLUE:
Packit 7838c8
	        new->bmax = i-1;
Packit 7838c8
	        ptr->bmin = i;
Packit 7838c8
	        break;
Packit 7838c8
	}
Packit 7838c8
	shrinkbox(new);
Packit 7838c8
	shrinkbox(ptr);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
shrinkbox(Colorbox* box)
Packit 7838c8
{
Packit 7838c8
	register uint32 *histp;
Packit 7838c8
	register int	ir, ig, ib;
Packit 7838c8
Packit 7838c8
	if (box->rmax > box->rmin) {
Packit 7838c8
		for (ir = box->rmin; ir <= box->rmax; ++ir)
Packit 7838c8
			for (ig = box->gmin; ig <= box->gmax; ++ig) {
Packit 7838c8
				histp = &histogram[ir][ig][box->bmin];
Packit 7838c8
			        for (ib = box->bmin; ib <= box->bmax; ++ib)
Packit 7838c8
					if (*histp++ != 0) {
Packit 7838c8
						box->rmin = ir;
Packit 7838c8
						goto have_rmin;
Packit 7838c8
					}
Packit 7838c8
			}
Packit 7838c8
	have_rmin:
Packit 7838c8
		if (box->rmax > box->rmin)
Packit 7838c8
			for (ir = box->rmax; ir >= box->rmin; --ir)
Packit 7838c8
				for (ig = box->gmin; ig <= box->gmax; ++ig) {
Packit 7838c8
					histp = &histogram[ir][ig][box->bmin];
Packit 7838c8
					ib = box->bmin;
Packit 7838c8
					for (; ib <= box->bmax; ++ib)
Packit 7838c8
						if (*histp++ != 0) {
Packit 7838c8
							box->rmax = ir;
Packit 7838c8
							goto have_rmax;
Packit 7838c8
						}
Packit 7838c8
			        }
Packit 7838c8
	}
Packit 7838c8
have_rmax:
Packit 7838c8
	if (box->gmax > box->gmin) {
Packit 7838c8
		for (ig = box->gmin; ig <= box->gmax; ++ig)
Packit 7838c8
			for (ir = box->rmin; ir <= box->rmax; ++ir) {
Packit 7838c8
				histp = &histogram[ir][ig][box->bmin];
Packit 7838c8
			        for (ib = box->bmin; ib <= box->bmax; ++ib)
Packit 7838c8
				if (*histp++ != 0) {
Packit 7838c8
					box->gmin = ig;
Packit 7838c8
					goto have_gmin;
Packit 7838c8
				}
Packit 7838c8
			}
Packit 7838c8
	have_gmin:
Packit 7838c8
		if (box->gmax > box->gmin)
Packit 7838c8
			for (ig = box->gmax; ig >= box->gmin; --ig)
Packit 7838c8
				for (ir = box->rmin; ir <= box->rmax; ++ir) {
Packit 7838c8
					histp = &histogram[ir][ig][box->bmin];
Packit 7838c8
					ib = box->bmin;
Packit 7838c8
					for (; ib <= box->bmax; ++ib)
Packit 7838c8
						if (*histp++ != 0) {
Packit 7838c8
							box->gmax = ig;
Packit 7838c8
							goto have_gmax;
Packit 7838c8
						}
Packit 7838c8
			        }
Packit 7838c8
	}
Packit 7838c8
have_gmax:
Packit 7838c8
	if (box->bmax > box->bmin) {
Packit 7838c8
		for (ib = box->bmin; ib <= box->bmax; ++ib)
Packit 7838c8
			for (ir = box->rmin; ir <= box->rmax; ++ir) {
Packit 7838c8
				histp = &histogram[ir][box->gmin][ib];
Packit 7838c8
			        for (ig = box->gmin; ig <= box->gmax; ++ig) {
Packit 7838c8
					if (*histp != 0) {
Packit 7838c8
						box->bmin = ib;
Packit 7838c8
						goto have_bmin;
Packit 7838c8
					}
Packit 7838c8
					histp += B_LEN;
Packit 7838c8
			        }
Packit 7838c8
		        }
Packit 7838c8
	have_bmin:
Packit 7838c8
		if (box->bmax > box->bmin)
Packit 7838c8
			for (ib = box->bmax; ib >= box->bmin; --ib)
Packit 7838c8
				for (ir = box->rmin; ir <= box->rmax; ++ir) {
Packit 7838c8
					histp = &histogram[ir][box->gmin][ib];
Packit 7838c8
					ig = box->gmin;
Packit 7838c8
					for (; ig <= box->gmax; ++ig) {
Packit 7838c8
						if (*histp != 0) {
Packit 7838c8
							box->bmax = ib;
Packit 7838c8
							goto have_bmax;
Packit 7838c8
						}
Packit 7838c8
						histp += B_LEN;
Packit 7838c8
					}
Packit 7838c8
			        }
Packit 7838c8
	}
Packit 7838c8
have_bmax:
Packit 7838c8
	;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static C_cell *
Packit 7838c8
create_colorcell(int red, int green, int blue)
Packit 7838c8
{
Packit 7838c8
	register int ir, ig, ib, i;
Packit 7838c8
	register C_cell *ptr;
Packit 7838c8
	int mindist, next_n;
Packit 7838c8
	register int tmp, dist, n;
Packit 7838c8
Packit 7838c8
	ir = red >> (COLOR_DEPTH-C_DEPTH);
Packit 7838c8
	ig = green >> (COLOR_DEPTH-C_DEPTH);
Packit 7838c8
	ib = blue >> (COLOR_DEPTH-C_DEPTH);
Packit 7838c8
	ptr = (C_cell *)_TIFFmalloc(sizeof (C_cell));
Packit 7838c8
	*(ColorCells + ir*C_LEN*C_LEN + ig*C_LEN + ib) = ptr;
Packit 7838c8
	ptr->num_ents = 0;
Packit 7838c8
Packit 7838c8
	/*
Packit 7838c8
	 * Step 1: find all colors inside this cell, while we're at
Packit 7838c8
	 *	   it, find distance of centermost point to furthest corner
Packit 7838c8
	 */
Packit 7838c8
	mindist = 99999999;
Packit 7838c8
	for (i = 0; i < num_colors; ++i) {
Packit 7838c8
		if (rm[i]>>(COLOR_DEPTH-C_DEPTH) != ir  ||
Packit 7838c8
		    gm[i]>>(COLOR_DEPTH-C_DEPTH) != ig  ||
Packit 7838c8
		    bm[i]>>(COLOR_DEPTH-C_DEPTH) != ib)
Packit 7838c8
			continue;
Packit 7838c8
		ptr->entries[ptr->num_ents][0] = i;
Packit 7838c8
		ptr->entries[ptr->num_ents][1] = 0;
Packit 7838c8
		++ptr->num_ents;
Packit 7838c8
	        tmp = rm[i] - red;
Packit 7838c8
	        if (tmp < (MAX_COLOR/C_LEN/2))
Packit 7838c8
			tmp = MAX_COLOR/C_LEN-1 - tmp;
Packit 7838c8
	        dist = tmp*tmp;
Packit 7838c8
	        tmp = gm[i] - green;
Packit 7838c8
	        if (tmp < (MAX_COLOR/C_LEN/2))
Packit 7838c8
			tmp = MAX_COLOR/C_LEN-1 - tmp;
Packit 7838c8
	        dist += tmp*tmp;
Packit 7838c8
	        tmp = bm[i] - blue;
Packit 7838c8
	        if (tmp < (MAX_COLOR/C_LEN/2))
Packit 7838c8
			tmp = MAX_COLOR/C_LEN-1 - tmp;
Packit 7838c8
	        dist += tmp*tmp;
Packit 7838c8
	        if (dist < mindist)
Packit 7838c8
			mindist = dist;
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
	/*
Packit 7838c8
	 * Step 3: find all points within that distance to cell.
Packit 7838c8
	 */
Packit 7838c8
	for (i = 0; i < num_colors; ++i) {
Packit 7838c8
		if (rm[i] >> (COLOR_DEPTH-C_DEPTH) == ir  &&
Packit 7838c8
		    gm[i] >> (COLOR_DEPTH-C_DEPTH) == ig  &&
Packit 7838c8
		    bm[i] >> (COLOR_DEPTH-C_DEPTH) == ib)
Packit 7838c8
			continue;
Packit 7838c8
		dist = 0;
Packit 7838c8
	        if ((tmp = red - rm[i]) > 0 ||
Packit 7838c8
		    (tmp = rm[i] - (red + MAX_COLOR/C_LEN-1)) > 0 )
Packit 7838c8
			dist += tmp*tmp;
Packit 7838c8
	        if ((tmp = green - gm[i]) > 0 ||
Packit 7838c8
		    (tmp = gm[i] - (green + MAX_COLOR/C_LEN-1)) > 0 )
Packit 7838c8
			dist += tmp*tmp;
Packit 7838c8
	        if ((tmp = blue - bm[i]) > 0 ||
Packit 7838c8
		    (tmp = bm[i] - (blue + MAX_COLOR/C_LEN-1)) > 0 )
Packit 7838c8
			dist += tmp*tmp;
Packit 7838c8
	        if (dist < mindist) {
Packit 7838c8
			ptr->entries[ptr->num_ents][0] = i;
Packit 7838c8
			ptr->entries[ptr->num_ents][1] = dist;
Packit 7838c8
			++ptr->num_ents;
Packit 7838c8
	        }
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
	/*
Packit 7838c8
	 * Sort color cells by distance, use cheap exchange sort
Packit 7838c8
	 */
Packit 7838c8
	for (n = ptr->num_ents - 1; n > 0; n = next_n) {
Packit 7838c8
		next_n = 0;
Packit 7838c8
		for (i = 0; i < n; ++i)
Packit 7838c8
			if (ptr->entries[i][1] > ptr->entries[i+1][1]) {
Packit 7838c8
				tmp = ptr->entries[i][0];
Packit 7838c8
				ptr->entries[i][0] = ptr->entries[i+1][0];
Packit 7838c8
				ptr->entries[i+1][0] = tmp;
Packit 7838c8
				tmp = ptr->entries[i][1];
Packit 7838c8
				ptr->entries[i][1] = ptr->entries[i+1][1];
Packit 7838c8
				ptr->entries[i+1][1] = tmp;
Packit 7838c8
				next_n = i;
Packit 7838c8
		        }
Packit 7838c8
	}
Packit 7838c8
	return (ptr);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
map_colortable(void)
Packit 7838c8
{
Packit 7838c8
	register uint32 *histp = &histogram[0][0][0];
Packit 7838c8
	register C_cell *cell;
Packit 7838c8
	register int j, tmp, d2, dist;
Packit 7838c8
	int ir, ig, ib, i;
Packit 7838c8
Packit 7838c8
	for (ir = 0; ir < B_LEN; ++ir)
Packit 7838c8
		for (ig = 0; ig < B_LEN; ++ig)
Packit 7838c8
			for (ib = 0; ib < B_LEN; ++ib, histp++) {
Packit 7838c8
				if (*histp == 0) {
Packit 7838c8
					*histp = -1;
Packit 7838c8
					continue;
Packit 7838c8
				}
Packit 7838c8
				cell = *(ColorCells +
Packit 7838c8
				    (((ir>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2) +
Packit 7838c8
				    ((ig>>(B_DEPTH-C_DEPTH)) << C_DEPTH) +
Packit 7838c8
				    (ib>>(B_DEPTH-C_DEPTH))));
Packit 7838c8
				if (cell == NULL )
Packit 7838c8
					cell = create_colorcell(
Packit 7838c8
					    ir << COLOR_SHIFT,
Packit 7838c8
					    ig << COLOR_SHIFT,
Packit 7838c8
					    ib << COLOR_SHIFT);
Packit 7838c8
				dist = 9999999;
Packit 7838c8
				for (i = 0; i < cell->num_ents &&
Packit 7838c8
				    dist > cell->entries[i][1]; ++i) {
Packit 7838c8
					j = cell->entries[i][0];
Packit 7838c8
					d2 = rm[j] - (ir << COLOR_SHIFT);
Packit 7838c8
					d2 *= d2;
Packit 7838c8
					tmp = gm[j] - (ig << COLOR_SHIFT);
Packit 7838c8
					d2 += tmp*tmp;
Packit 7838c8
					tmp = bm[j] - (ib << COLOR_SHIFT);
Packit 7838c8
					d2 += tmp*tmp;
Packit 7838c8
					if (d2 < dist) {
Packit 7838c8
						dist = d2;
Packit 7838c8
						*histp = j;
Packit 7838c8
					}
Packit 7838c8
				}
Packit 7838c8
			}
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * straight quantization.  Each pixel is mapped to the colors
Packit 7838c8
 * closest to it.  Color values are rounded to the nearest color
Packit 7838c8
 * table entry.
Packit 7838c8
 */
Packit 7838c8
static void
Packit 7838c8
quant(TIFF* in, TIFF* out)
Packit 7838c8
{
Packit 7838c8
	unsigned char	*outline, *inputline;
Packit 7838c8
	register unsigned char	*outptr, *inptr;
Packit 7838c8
	register uint32 i, j;
Packit 7838c8
	register int red, green, blue;
Packit 7838c8
Packit 7838c8
	inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
Packit 7838c8
	outline = (unsigned char *)_TIFFmalloc(imagewidth);
Packit 7838c8
	for (i = 0; i < imagelength; i++) {
Packit 7838c8
		if (TIFFReadScanline(in, inputline, i, 0) <= 0)
Packit 7838c8
			break;
Packit 7838c8
		inptr = inputline;
Packit 7838c8
		outptr = outline;
Packit 7838c8
		for (j = 0; j < imagewidth; j++) {
Packit 7838c8
			red = *inptr++ >> COLOR_SHIFT;
Packit 7838c8
			green = *inptr++ >> COLOR_SHIFT;
Packit 7838c8
			blue = *inptr++ >> COLOR_SHIFT;
Packit 7838c8
			*outptr++ = (unsigned char)histogram[red][green][blue];
Packit 7838c8
		}
Packit 7838c8
		if (TIFFWriteScanline(out, outline, i, 0) < 0)
Packit 7838c8
			break;
Packit 7838c8
	}
Packit 7838c8
	_TIFFfree(inputline);
Packit 7838c8
	_TIFFfree(outline);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
#define	SWAP(type,a,b)	{ type p; p = a; a = b; b = p; }
Packit 7838c8
Packit 7838c8
#define	GetInputLine(tif, row, bad)                                     \
Packit 7838c8
        do {                                                            \
Packit 7838c8
                if (TIFFReadScanline(tif, inputline, row, 0) <= 0)	\
Packit 7838c8
                        bad;						\
Packit 7838c8
                inptr = inputline;					\
Packit 7838c8
                nextptr = nextline;					\
Packit 7838c8
                for (j = 0; j < imagewidth; ++j) {			\
Packit 7838c8
                        *nextptr++ = *inptr++;				\
Packit 7838c8
                        *nextptr++ = *inptr++;				\
Packit 7838c8
                        *nextptr++ = *inptr++;				\
Packit 7838c8
                }                                                       \
Packit 7838c8
        } while (0);
Packit 7838c8
#define	GetComponent(raw, cshift, c)				\
Packit 7838c8
        do {                                                    \
Packit 7838c8
                cshift = raw;                                   \
Packit 7838c8
                if (cshift < 0)                                 \
Packit 7838c8
                        cshift = 0;                             \
Packit 7838c8
                else if (cshift >= MAX_COLOR)                   \
Packit 7838c8
                        cshift = MAX_COLOR-1;                   \
Packit 7838c8
                c = cshift;                                     \
Packit 7838c8
                cshift >>= COLOR_SHIFT;                         \
Packit 7838c8
        } while (0);
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
quant_fsdither(TIFF* in, TIFF* out)
Packit 7838c8
{
Packit 7838c8
	unsigned char *outline, *inputline, *inptr;
Packit 7838c8
	short *thisline, *nextline;
Packit 7838c8
	register unsigned char	*outptr;
Packit 7838c8
	register short *thisptr, *nextptr;
Packit 7838c8
	register uint32 i, j;
Packit 7838c8
	uint32 imax, jmax;
Packit 7838c8
	int lastline, lastpixel;
Packit 7838c8
Packit 7838c8
	imax = imagelength - 1;
Packit 7838c8
	jmax = imagewidth - 1;
Packit 7838c8
	inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
Packit 7838c8
	thisline = (short *)_TIFFmalloc(imagewidth * 3 * sizeof (short));
Packit 7838c8
	nextline = (short *)_TIFFmalloc(imagewidth * 3 * sizeof (short));
Packit 7838c8
	outline = (unsigned char *) _TIFFmalloc(TIFFScanlineSize(out));
Packit 7838c8
Packit 7838c8
	GetInputLine(in, 0, goto bad);		/* get first line */
Packit 7838c8
	for (i = 1; i <= imagelength; ++i) {
Packit 7838c8
		SWAP(short *, thisline, nextline);
Packit 7838c8
		lastline = (i >= imax);
Packit 7838c8
		if (i <= imax)
Packit 7838c8
			GetInputLine(in, i, break);
Packit 7838c8
		thisptr = thisline;
Packit 7838c8
		nextptr = nextline;
Packit 7838c8
		outptr = outline;
Packit 7838c8
		for (j = 0; j < imagewidth; ++j) {
Packit 7838c8
			int red, green, blue;
Packit 7838c8
			register int oval, r2, g2, b2;
Packit 7838c8
Packit 7838c8
			lastpixel = (j == jmax);
Packit 7838c8
			GetComponent(*thisptr++, r2, red);
Packit 7838c8
			GetComponent(*thisptr++, g2, green);
Packit 7838c8
			GetComponent(*thisptr++, b2, blue);
Packit 7838c8
			oval = histogram[r2][g2][b2];
Packit 7838c8
			if (oval == -1) {
Packit 7838c8
				int ci;
Packit 7838c8
				register int cj, tmp, d2, dist;
Packit 7838c8
				register C_cell	*cell;
Packit 7838c8
Packit 7838c8
				cell = *(ColorCells +
Packit 7838c8
				    (((r2>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2) +
Packit 7838c8
				    ((g2>>(B_DEPTH-C_DEPTH)) << C_DEPTH ) +
Packit 7838c8
				    (b2>>(B_DEPTH-C_DEPTH))));
Packit 7838c8
				if (cell == NULL)
Packit 7838c8
					cell = create_colorcell(red,
Packit 7838c8
					    green, blue);
Packit 7838c8
				dist = 9999999;
Packit 7838c8
				for (ci = 0; ci < cell->num_ents && dist > cell->entries[ci][1]; ++ci) {
Packit 7838c8
					cj = cell->entries[ci][0];
Packit 7838c8
					d2 = (rm[cj] >> COLOR_SHIFT) - r2;
Packit 7838c8
					d2 *= d2;
Packit 7838c8
					tmp = (gm[cj] >> COLOR_SHIFT) - g2;
Packit 7838c8
					d2 += tmp*tmp;
Packit 7838c8
					tmp = (bm[cj] >> COLOR_SHIFT) - b2;
Packit 7838c8
					d2 += tmp*tmp;
Packit 7838c8
					if (d2 < dist) {
Packit 7838c8
						dist = d2;
Packit 7838c8
						oval = cj;
Packit 7838c8
					}
Packit 7838c8
				}
Packit 7838c8
				histogram[r2][g2][b2] = oval;
Packit 7838c8
			}
Packit 7838c8
			*outptr++ = oval;
Packit 7838c8
			red -= rm[oval];
Packit 7838c8
			green -= gm[oval];
Packit 7838c8
			blue -= bm[oval];
Packit 7838c8
			if (!lastpixel) {
Packit 7838c8
				thisptr[0] += blue * 7 / 16;
Packit 7838c8
				thisptr[1] += green * 7 / 16;
Packit 7838c8
				thisptr[2] += red * 7 / 16;
Packit 7838c8
			}
Packit 7838c8
			if (!lastline) {
Packit 7838c8
				if (j != 0) {
Packit 7838c8
					nextptr[-3] += blue * 3 / 16;
Packit 7838c8
					nextptr[-2] += green * 3 / 16;
Packit 7838c8
					nextptr[-1] += red * 3 / 16;
Packit 7838c8
				}
Packit 7838c8
				nextptr[0] += blue * 5 / 16;
Packit 7838c8
				nextptr[1] += green * 5 / 16;
Packit 7838c8
				nextptr[2] += red * 5 / 16;
Packit 7838c8
				if (!lastpixel) {
Packit 7838c8
					nextptr[3] += blue / 16;
Packit 7838c8
				        nextptr[4] += green / 16;
Packit 7838c8
				        nextptr[5] += red / 16;
Packit 7838c8
				}
Packit 7838c8
				nextptr += 3;
Packit 7838c8
			}
Packit 7838c8
		}
Packit 7838c8
		if (TIFFWriteScanline(out, outline, i-1, 0) < 0)
Packit 7838c8
			break;
Packit 7838c8
	}
Packit 7838c8
bad:
Packit 7838c8
	_TIFFfree(inputline);
Packit 7838c8
	_TIFFfree(thisline);
Packit 7838c8
	_TIFFfree(nextline);
Packit 7838c8
	_TIFFfree(outline);
Packit 7838c8
}
Packit 7838c8
/*
Packit 7838c8
 * Local Variables:
Packit 7838c8
 * mode: c
Packit 7838c8
 * c-basic-offset: 8
Packit 7838c8
 * fill-column: 78
Packit 7838c8
 * End:
Packit 7838c8
 */