1 
2 /*
3  * Apply median cut on an image.
4  *
5  * tiffmedian [-c n] [-f] input output
6  *     -C n		- set colortable size.  Default is 256.
7  *     -f		- use Floyd-Steinberg dithering.
8  *     -c lzw		- compress output with LZW
9  *     -c none		- use no compression on output
10  *     -c packbits	- use packbits compression on output
11  *     -r n		- create output with n rows/strip of data
12  * (by default the compression scheme and rows/strip are taken
13  *  from the input file)
14  *
15  * Notes:
16  *
17  * [1] Floyd-Steinberg dither:
18  *  I should point out that the actual fractions we used were, assuming
19  *  you are at X, moving left to right:
20  *
21  *		    X     7/16
22  *	     3/16   5/16  1/16
23  *
24  *  Note that the error goes to four neighbors, not three.  I think this
25  *  will probably do better (at least for black and white) than the
26  *  3/8-3/8-1/4 distribution, at the cost of greater processing.  I have
27  *  seen the 3/8-3/8-1/4 distribution described as "our" algorithm before,
28  *  but I have no idea who the credit really belongs to.
29 
30  *  Also, I should add that if you do zig-zag scanning (see my immediately
31  *  previous message), it is sufficient (but not quite as good) to send
32  *  half the error one pixel ahead (e.g. to the right on lines you scan
33  *  left to right), and half one pixel straight down.  Again, this is for
34  *  black and white;  I've not tried it with color.
35  *  --
36  *					    Lou Steinberg
37  *
38  * [2] Color Image Quantization for Frame Buffer Display, Paul Heckbert,
39  *	Siggraph '82 proceedings, pp. 297-307
40  */
41 
42 #include "tif_config.h"
43 
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 
48 #ifdef HAVE_UNISTD_H
49 # include <unistd.h>
50 #endif
51 
52 #ifdef NEED_LIBPORT
53 # include "libport.h"
54 #endif
55 
56 #include "tiffio.h"
57 
58 #define	MAX_CMAP_SIZE	256
59 
60 #define	streq(a,b)	(strcmp(a,b) == 0)
61 #define	strneq(a,b,n)	(strncmp(a,b,n) == 0)
62 
63 #define	COLOR_DEPTH	8
64 #define	MAX_COLOR	256
65 
66 #define	B_DEPTH		5		/* # bits/pixel to use */
67 #define	B_LEN		(1L<<B_DEPTH)
68 
69 #define	C_DEPTH		2
70 #define	C_LEN		(1L<<C_DEPTH)	/* # cells/color to use */
71 
72 #define	COLOR_SHIFT	(COLOR_DEPTH-B_DEPTH)
73 
74 typedef	struct colorbox {
75 	struct	colorbox *next, *prev;
76 	int	rmin, rmax;
77 	int	gmin, gmax;
78 	int	bmin, bmax;
79 	uint32	total;
80 } Colorbox;
81 
82 typedef struct {
83 	int	num_ents;
84 	int	entries[MAX_CMAP_SIZE][2];
85 } C_cell;
86 
87 uint16	rm[MAX_CMAP_SIZE], gm[MAX_CMAP_SIZE], bm[MAX_CMAP_SIZE];
88 int	num_colors;
89 uint32	histogram[B_LEN][B_LEN][B_LEN];
90 Colorbox *freeboxes;
91 Colorbox *usedboxes;
92 C_cell	**ColorCells;
93 TIFF	*in, *out;
94 uint32	rowsperstrip = (uint32) -1;
95 uint16	compression = (uint16) -1;
96 uint16	bitspersample = 1;
97 uint16	samplesperpixel;
98 uint32	imagewidth;
99 uint32	imagelength;
100 uint16	predictor = 0;
101 
102 static	void get_histogram(TIFF*, Colorbox*);
103 static	void splitbox(Colorbox*);
104 static	void shrinkbox(Colorbox*);
105 static	void map_colortable(void);
106 static	void quant(TIFF*, TIFF*);
107 static	void quant_fsdither(TIFF*, TIFF*);
108 static	Colorbox* largest_box(void);
109 
110 static	void usage(void);
111 static	int processCompressOptions(char*);
112 
113 #define	CopyField(tag, v) \
114 	if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
115 
116 int
main(int argc,char * argv[])117 main(int argc, char* argv[])
118 {
119 	int i, dither = 0;
120 	uint16 shortv, config, photometric;
121 	Colorbox *box_list, *ptr;
122 	float floatv;
123 	uint32 longv;
124 	int c;
125 	extern int optind;
126 	extern char* optarg;
127 
128 	num_colors = MAX_CMAP_SIZE;
129 	while ((c = getopt(argc, argv, "c:C:r:f")) != -1)
130 		switch (c) {
131 		case 'c':		/* compression scheme */
132 			if (!processCompressOptions(optarg))
133 				usage();
134 			break;
135 		case 'C':		/* set colormap size */
136 			num_colors = atoi(optarg);
137 			if (num_colors > MAX_CMAP_SIZE) {
138 				fprintf(stderr,
139 				   "-c: colormap too big, max %d\n",
140 				   MAX_CMAP_SIZE);
141 				usage();
142 			}
143 			break;
144 		case 'f':		/* dither */
145 			dither = 1;
146 			break;
147 		case 'r':		/* rows/strip */
148 			rowsperstrip = atoi(optarg);
149 			break;
150 		case '?':
151 			usage();
152 			/*NOTREACHED*/
153 		}
154 	if (argc - optind != 2)
155 		usage();
156 	in = TIFFOpen(argv[optind], "r");
157 	if (in == NULL)
158 		return (-1);
159 	TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &imagewidth);
160 	TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength);
161 	TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample);
162 	TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
163 	if (bitspersample != 8 && bitspersample != 16) {
164 		fprintf(stderr, "%s: Image must have at least 8-bits/sample\n",
165 		    argv[optind]);
166 		return (-3);
167 	}
168 	if (!TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric) ||
169 	    photometric != PHOTOMETRIC_RGB || samplesperpixel < 3) {
170 		fprintf(stderr, "%s: Image must have RGB data\n", argv[optind]);
171 		return (-4);
172 	}
173 	TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config);
174 	if (config != PLANARCONFIG_CONTIG) {
175 		fprintf(stderr, "%s: Can only handle contiguous data packing\n",
176 		    argv[optind]);
177 		return (-5);
178 	}
179 
180 	/*
181 	 * STEP 1:  create empty boxes
182 	 */
183 	usedboxes = NULL;
184 	box_list = freeboxes = (Colorbox *)_TIFFmalloc(num_colors*sizeof (Colorbox));
185 	freeboxes[0].next = &freeboxes[1];
186 	freeboxes[0].prev = NULL;
187 	for (i = 1; i < num_colors-1; ++i) {
188 		freeboxes[i].next = &freeboxes[i+1];
189 		freeboxes[i].prev = &freeboxes[i-1];
190 	}
191 	freeboxes[num_colors-1].next = NULL;
192 	freeboxes[num_colors-1].prev = &freeboxes[num_colors-2];
193 
194 	/*
195 	 * STEP 2: get histogram, initialize first box
196 	 */
197 	ptr = freeboxes;
198 	freeboxes = ptr->next;
199 	if (freeboxes)
200 		freeboxes->prev = NULL;
201 	ptr->next = usedboxes;
202 	usedboxes = ptr;
203 	if (ptr->next)
204 		ptr->next->prev = ptr;
205 	get_histogram(in, ptr);
206 
207 	/*
208 	 * STEP 3: continually subdivide boxes until no more free
209 	 * boxes remain or until all colors assigned.
210 	 */
211 	while (freeboxes != NULL) {
212 		ptr = largest_box();
213 		if (ptr != NULL)
214 			splitbox(ptr);
215 		else
216 			freeboxes = NULL;
217 	}
218 
219 	/*
220 	 * STEP 4: assign colors to all boxes
221 	 */
222 	for (i = 0, ptr = usedboxes; ptr != NULL; ++i, ptr = ptr->next) {
223 		rm[i] = ((ptr->rmin + ptr->rmax) << COLOR_SHIFT) / 2;
224 		gm[i] = ((ptr->gmin + ptr->gmax) << COLOR_SHIFT) / 2;
225 		bm[i] = ((ptr->bmin + ptr->bmax) << COLOR_SHIFT) / 2;
226 	}
227 
228 	/* We're done with the boxes now */
229 	_TIFFfree(box_list);
230 	freeboxes = usedboxes = NULL;
231 
232 	/*
233 	 * STEP 5: scan histogram and map all values to closest color
234 	 */
235 	/* 5a: create cell list as described in Heckbert[2] */
236 	ColorCells = (C_cell **)_TIFFmalloc(C_LEN*C_LEN*C_LEN*sizeof (C_cell*));
237 	_TIFFmemset(ColorCells, 0, C_LEN*C_LEN*C_LEN*sizeof (C_cell*));
238 	/* 5b: create mapping from truncated pixel space to color
239 	   table entries */
240 	map_colortable();
241 
242 	/*
243 	 * STEP 6: scan image, match input values to table entries
244 	 */
245 	out = TIFFOpen(argv[optind+1], "w");
246 	if (out == NULL)
247 		return (-2);
248 
249 	CopyField(TIFFTAG_SUBFILETYPE, longv);
250 	CopyField(TIFFTAG_IMAGEWIDTH, longv);
251 	TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (short)COLOR_DEPTH);
252 	if (compression != (uint16)-1) {
253 		TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
254 		switch (compression) {
255 		case COMPRESSION_LZW:
256 		case COMPRESSION_DEFLATE:
257 			if (predictor != 0)
258 				TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
259 			break;
260 		}
261 	} else
262 		CopyField(TIFFTAG_COMPRESSION, compression);
263 	TIFFSetField(out, TIFFTAG_PHOTOMETRIC, (short)PHOTOMETRIC_PALETTE);
264 	CopyField(TIFFTAG_ORIENTATION, shortv);
265 	TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, (short)1);
266 	CopyField(TIFFTAG_PLANARCONFIG, shortv);
267 	TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
268 	    TIFFDefaultStripSize(out, rowsperstrip));
269 	CopyField(TIFFTAG_MINSAMPLEVALUE, shortv);
270 	CopyField(TIFFTAG_MAXSAMPLEVALUE, shortv);
271 	CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
272 	CopyField(TIFFTAG_XRESOLUTION, floatv);
273 	CopyField(TIFFTAG_YRESOLUTION, floatv);
274 	CopyField(TIFFTAG_XPOSITION, floatv);
275 	CopyField(TIFFTAG_YPOSITION, floatv);
276 
277 	if (dither)
278 		quant_fsdither(in, out);
279 	else
280 		quant(in, out);
281 	/*
282 	 * Scale colormap to TIFF-required 16-bit values.
283 	 */
284 #define	SCALE(x)	(((x)*((1L<<16)-1))/255)
285 	for (i = 0; i < MAX_CMAP_SIZE; ++i) {
286 		rm[i] = SCALE(rm[i]);
287 		gm[i] = SCALE(gm[i]);
288 		bm[i] = SCALE(bm[i]);
289 	}
290 	TIFFSetField(out, TIFFTAG_COLORMAP, rm, gm, bm);
291 	(void) TIFFClose(out);
292 	return (0);
293 }
294 
295 static int
processCompressOptions(char * opt)296 processCompressOptions(char* opt)
297 {
298 	if (streq(opt, "none"))
299 		compression = COMPRESSION_NONE;
300 	else if (streq(opt, "packbits"))
301 		compression = COMPRESSION_PACKBITS;
302 	else if (strneq(opt, "lzw", 3)) {
303 		char* cp = strchr(opt, ':');
304 		if (cp)
305 			predictor = atoi(cp+1);
306 		compression = COMPRESSION_LZW;
307 	} else if (strneq(opt, "zip", 3)) {
308 		char* cp = strchr(opt, ':');
309 		if (cp)
310 			predictor = atoi(cp+1);
311 		compression = COMPRESSION_DEFLATE;
312 	} else
313 		return (0);
314 	return (1);
315 }
316 
317 char* stuff[] = {
318 "usage: tiffmedian [options] input.tif output.tif",
319 "where options are:",
320 " -r #		make each strip have no more than # rows",
321 " -C #		create a colormap with # entries",
322 " -f		use Floyd-Steinberg dithering",
323 " -c lzw[:opts]	compress output with Lempel-Ziv & Welch encoding",
324 " -c zip[:opts]	compress output with deflate encoding",
325 " -c packbits	compress output with packbits encoding",
326 " -c none	use no compression algorithm on output",
327 "",
328 "LZW and deflate options:",
329 " #		set predictor value",
330 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
331 NULL
332 };
333 
334 static void
usage(void)335 usage(void)
336 {
337 	char buf[BUFSIZ];
338 	int i;
339 
340 	setbuf(stderr, buf);
341         fprintf(stderr, "%s\n\n", TIFFGetVersion());
342 	for (i = 0; stuff[i] != NULL; i++)
343 		fprintf(stderr, "%s\n", stuff[i]);
344 	exit(-1);
345 }
346 
347 static void
get_histogram(TIFF * in,Colorbox * box)348 get_histogram(TIFF* in, Colorbox* box)
349 {
350 	register unsigned char *inptr;
351 	register int red, green, blue;
352 	register uint32 j, i;
353 	unsigned char *inputline;
354 
355 	inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
356 	if (inputline == NULL) {
357 		fprintf(stderr, "No space for scanline buffer\n");
358 		exit(-1);
359 	}
360 	box->rmin = box->gmin = box->bmin = 999;
361 	box->rmax = box->gmax = box->bmax = -1;
362 	box->total = imagewidth * imagelength;
363 
364 	{ register uint32 *ptr = &histogram[0][0][0];
365 	  for (i = B_LEN*B_LEN*B_LEN; i-- > 0;)
366 		*ptr++ = 0;
367 	}
368 	for (i = 0; i < imagelength; i++) {
369 		if (TIFFReadScanline(in, inputline, i, 0) <= 0)
370 			break;
371 		inptr = inputline;
372 		for (j = imagewidth; j-- > 0;) {
373 			red = *inptr++ >> COLOR_SHIFT;
374 			green = *inptr++ >> COLOR_SHIFT;
375 			blue = *inptr++ >> COLOR_SHIFT;
376 			if (red < box->rmin)
377 				box->rmin = red;
378 		        if (red > box->rmax)
379 				box->rmax = red;
380 		        if (green < box->gmin)
381 				box->gmin = green;
382 		        if (green > box->gmax)
383 				box->gmax = green;
384 		        if (blue < box->bmin)
385 				box->bmin = blue;
386 		        if (blue > box->bmax)
387 				box->bmax = blue;
388 		        histogram[red][green][blue]++;
389 		}
390 	}
391 	_TIFFfree(inputline);
392 }
393 
394 static Colorbox *
largest_box(void)395 largest_box(void)
396 {
397 	register Colorbox *p, *b;
398 	register uint32 size;
399 
400 	b = NULL;
401 	size = 0;
402 	for (p = usedboxes; p != NULL; p = p->next)
403 		if ((p->rmax > p->rmin || p->gmax > p->gmin ||
404 		    p->bmax > p->bmin) &&  p->total > size)
405 		        size = (b = p)->total;
406 	return (b);
407 }
408 
409 static void
splitbox(Colorbox * ptr)410 splitbox(Colorbox* ptr)
411 {
412 	uint32		hist2[B_LEN];
413 	int		first=0, last=0;
414 	register Colorbox	*new;
415 	register uint32	*iptr, *histp;
416 	register int	i, j;
417 	register int	ir,ig,ib;
418 	register uint32 sum, sum1, sum2;
419 	enum { RED, GREEN, BLUE } axis;
420 
421 	/*
422 	 * See which axis is the largest, do a histogram along that
423 	 * axis.  Split at median point.  Contract both new boxes to
424 	 * fit points and return
425 	 */
426 	i = ptr->rmax - ptr->rmin;
427 	if (i >= ptr->gmax - ptr->gmin && i >= ptr->bmax - ptr->bmin)
428 		axis = RED;
429 	else if (ptr->gmax - ptr->gmin >= ptr->bmax - ptr->bmin)
430 		axis = GREEN;
431 	else
432 		axis = BLUE;
433 	/* get histogram along longest axis */
434 	switch (axis) {
435 	case RED:
436 		histp = &hist2[ptr->rmin];
437 	        for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
438 			*histp = 0;
439 			for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
440 				iptr = &histogram[ir][ig][ptr->bmin];
441 				for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
442 					*histp += *iptr++;
443 			}
444 			histp++;
445 	        }
446 	        first = ptr->rmin;
447 		last = ptr->rmax;
448 	        break;
449 	case GREEN:
450 	        histp = &hist2[ptr->gmin];
451 	        for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
452 			*histp = 0;
453 			for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
454 				iptr = &histogram[ir][ig][ptr->bmin];
455 				for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
456 					*histp += *iptr++;
457 			}
458 			histp++;
459 	        }
460 	        first = ptr->gmin;
461 		last = ptr->gmax;
462 	        break;
463 	case BLUE:
464 	        histp = &hist2[ptr->bmin];
465 	        for (ib = ptr->bmin; ib <= ptr->bmax; ++ib) {
466 			*histp = 0;
467 			for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
468 				iptr = &histogram[ir][ptr->gmin][ib];
469 				for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
470 					*histp += *iptr;
471 					iptr += B_LEN;
472 				}
473 			}
474 			histp++;
475 	        }
476 	        first = ptr->bmin;
477 		last = ptr->bmax;
478 	        break;
479 	}
480 	/* find median point */
481 	sum2 = ptr->total / 2;
482 	histp = &hist2[first];
483 	sum = 0;
484 	for (i = first; i <= last && (sum += *histp++) < sum2; ++i)
485 		;
486 	if (i == first)
487 		i++;
488 
489 	/* Create new box, re-allocate points */
490 	new = freeboxes;
491 	freeboxes = new->next;
492 	if (freeboxes)
493 		freeboxes->prev = NULL;
494 	if (usedboxes)
495 		usedboxes->prev = new;
496 	new->next = usedboxes;
497 	usedboxes = new;
498 
499 	histp = &hist2[first];
500 	for (sum1 = 0, j = first; j < i; j++)
501 		sum1 += *histp++;
502 	for (sum2 = 0, j = i; j <= last; j++)
503 	    sum2 += *histp++;
504 	new->total = sum1;
505 	ptr->total = sum2;
506 
507 	new->rmin = ptr->rmin;
508 	new->rmax = ptr->rmax;
509 	new->gmin = ptr->gmin;
510 	new->gmax = ptr->gmax;
511 	new->bmin = ptr->bmin;
512 	new->bmax = ptr->bmax;
513 	switch (axis) {
514 	case RED:
515 		new->rmax = i-1;
516 	        ptr->rmin = i;
517 	        break;
518 	case GREEN:
519 	        new->gmax = i-1;
520 	        ptr->gmin = i;
521 	        break;
522 	case BLUE:
523 	        new->bmax = i-1;
524 	        ptr->bmin = i;
525 	        break;
526 	}
527 	shrinkbox(new);
528 	shrinkbox(ptr);
529 }
530 
531 static void
shrinkbox(Colorbox * box)532 shrinkbox(Colorbox* box)
533 {
534 	register uint32 *histp;
535 	register int	ir, ig, ib;
536 
537 	if (box->rmax > box->rmin) {
538 		for (ir = box->rmin; ir <= box->rmax; ++ir)
539 			for (ig = box->gmin; ig <= box->gmax; ++ig) {
540 				histp = &histogram[ir][ig][box->bmin];
541 			        for (ib = box->bmin; ib <= box->bmax; ++ib)
542 					if (*histp++ != 0) {
543 						box->rmin = ir;
544 						goto have_rmin;
545 					}
546 			}
547 	have_rmin:
548 		if (box->rmax > box->rmin)
549 			for (ir = box->rmax; ir >= box->rmin; --ir)
550 				for (ig = box->gmin; ig <= box->gmax; ++ig) {
551 					histp = &histogram[ir][ig][box->bmin];
552 					ib = box->bmin;
553 					for (; ib <= box->bmax; ++ib)
554 						if (*histp++ != 0) {
555 							box->rmax = ir;
556 							goto have_rmax;
557 						}
558 			        }
559 	}
560 have_rmax:
561 	if (box->gmax > box->gmin) {
562 		for (ig = box->gmin; ig <= box->gmax; ++ig)
563 			for (ir = box->rmin; ir <= box->rmax; ++ir) {
564 				histp = &histogram[ir][ig][box->bmin];
565 			        for (ib = box->bmin; ib <= box->bmax; ++ib)
566 				if (*histp++ != 0) {
567 					box->gmin = ig;
568 					goto have_gmin;
569 				}
570 			}
571 	have_gmin:
572 		if (box->gmax > box->gmin)
573 			for (ig = box->gmax; ig >= box->gmin; --ig)
574 				for (ir = box->rmin; ir <= box->rmax; ++ir) {
575 					histp = &histogram[ir][ig][box->bmin];
576 					ib = box->bmin;
577 					for (; ib <= box->bmax; ++ib)
578 						if (*histp++ != 0) {
579 							box->gmax = ig;
580 							goto have_gmax;
581 						}
582 			        }
583 	}
584 have_gmax:
585 	if (box->bmax > box->bmin) {
586 		for (ib = box->bmin; ib <= box->bmax; ++ib)
587 			for (ir = box->rmin; ir <= box->rmax; ++ir) {
588 				histp = &histogram[ir][box->gmin][ib];
589 			        for (ig = box->gmin; ig <= box->gmax; ++ig) {
590 					if (*histp != 0) {
591 						box->bmin = ib;
592 						goto have_bmin;
593 					}
594 					histp += B_LEN;
595 			        }
596 		        }
597 	have_bmin:
598 		if (box->bmax > box->bmin)
599 			for (ib = box->bmax; ib >= box->bmin; --ib)
600 				for (ir = box->rmin; ir <= box->rmax; ++ir) {
601 					histp = &histogram[ir][box->gmin][ib];
602 					ig = box->gmin;
603 					for (; ig <= box->gmax; ++ig) {
604 						if (*histp != 0) {
605 							box->bmax = ib;
606 							goto have_bmax;
607 						}
608 						histp += B_LEN;
609 					}
610 			        }
611 	}
612 have_bmax:
613 	;
614 }
615 
616 static C_cell *
create_colorcell(int red,int green,int blue)617 create_colorcell(int red, int green, int blue)
618 {
619 	register int ir, ig, ib, i;
620 	register C_cell *ptr;
621 	int mindist, next_n;
622 	register int tmp, dist, n;
623 
624 	ir = red >> (COLOR_DEPTH-C_DEPTH);
625 	ig = green >> (COLOR_DEPTH-C_DEPTH);
626 	ib = blue >> (COLOR_DEPTH-C_DEPTH);
627 	ptr = (C_cell *)_TIFFmalloc(sizeof (C_cell));
628 	*(ColorCells + ir*C_LEN*C_LEN + ig*C_LEN + ib) = ptr;
629 	ptr->num_ents = 0;
630 
631 	/*
632 	 * Step 1: find all colors inside this cell, while we're at
633 	 *	   it, find distance of centermost point to furthest corner
634 	 */
635 	mindist = 99999999;
636 	for (i = 0; i < num_colors; ++i) {
637 		if (rm[i]>>(COLOR_DEPTH-C_DEPTH) != ir  ||
638 		    gm[i]>>(COLOR_DEPTH-C_DEPTH) != ig  ||
639 		    bm[i]>>(COLOR_DEPTH-C_DEPTH) != ib)
640 			continue;
641 		ptr->entries[ptr->num_ents][0] = i;
642 		ptr->entries[ptr->num_ents][1] = 0;
643 		++ptr->num_ents;
644 	        tmp = rm[i] - red;
645 	        if (tmp < (MAX_COLOR/C_LEN/2))
646 			tmp = MAX_COLOR/C_LEN-1 - tmp;
647 	        dist = tmp*tmp;
648 	        tmp = gm[i] - green;
649 	        if (tmp < (MAX_COLOR/C_LEN/2))
650 			tmp = MAX_COLOR/C_LEN-1 - tmp;
651 	        dist += tmp*tmp;
652 	        tmp = bm[i] - blue;
653 	        if (tmp < (MAX_COLOR/C_LEN/2))
654 			tmp = MAX_COLOR/C_LEN-1 - tmp;
655 	        dist += tmp*tmp;
656 	        if (dist < mindist)
657 			mindist = dist;
658 	}
659 
660 	/*
661 	 * Step 3: find all points within that distance to cell.
662 	 */
663 	for (i = 0; i < num_colors; ++i) {
664 		if (rm[i] >> (COLOR_DEPTH-C_DEPTH) == ir  &&
665 		    gm[i] >> (COLOR_DEPTH-C_DEPTH) == ig  &&
666 		    bm[i] >> (COLOR_DEPTH-C_DEPTH) == ib)
667 			continue;
668 		dist = 0;
669 	        if ((tmp = red - rm[i]) > 0 ||
670 		    (tmp = rm[i] - (red + MAX_COLOR/C_LEN-1)) > 0 )
671 			dist += tmp*tmp;
672 	        if ((tmp = green - gm[i]) > 0 ||
673 		    (tmp = gm[i] - (green + MAX_COLOR/C_LEN-1)) > 0 )
674 			dist += tmp*tmp;
675 	        if ((tmp = blue - bm[i]) > 0 ||
676 		    (tmp = bm[i] - (blue + MAX_COLOR/C_LEN-1)) > 0 )
677 			dist += tmp*tmp;
678 	        if (dist < mindist) {
679 			ptr->entries[ptr->num_ents][0] = i;
680 			ptr->entries[ptr->num_ents][1] = dist;
681 			++ptr->num_ents;
682 	        }
683 	}
684 
685 	/*
686 	 * Sort color cells by distance, use cheap exchange sort
687 	 */
688 	for (n = ptr->num_ents - 1; n > 0; n = next_n) {
689 		next_n = 0;
690 		for (i = 0; i < n; ++i)
691 			if (ptr->entries[i][1] > ptr->entries[i+1][1]) {
692 				tmp = ptr->entries[i][0];
693 				ptr->entries[i][0] = ptr->entries[i+1][0];
694 				ptr->entries[i+1][0] = tmp;
695 				tmp = ptr->entries[i][1];
696 				ptr->entries[i][1] = ptr->entries[i+1][1];
697 				ptr->entries[i+1][1] = tmp;
698 				next_n = i;
699 		        }
700 	}
701 	return (ptr);
702 }
703 
704 static void
map_colortable(void)705 map_colortable(void)
706 {
707 	register uint32 *histp = &histogram[0][0][0];
708 	register C_cell *cell;
709 	register int j, tmp, d2, dist;
710 	int ir, ig, ib, i;
711 
712 	for (ir = 0; ir < B_LEN; ++ir)
713 		for (ig = 0; ig < B_LEN; ++ig)
714 			for (ib = 0; ib < B_LEN; ++ib, histp++) {
715 				if (*histp == 0) {
716 					*histp = -1;
717 					continue;
718 				}
719 				cell = *(ColorCells +
720 				    (((ir>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2) +
721 				    ((ig>>(B_DEPTH-C_DEPTH)) << C_DEPTH) +
722 				    (ib>>(B_DEPTH-C_DEPTH))));
723 				if (cell == NULL )
724 					cell = create_colorcell(
725 					    ir << COLOR_SHIFT,
726 					    ig << COLOR_SHIFT,
727 					    ib << COLOR_SHIFT);
728 				dist = 9999999;
729 				for (i = 0; i < cell->num_ents &&
730 				    dist > cell->entries[i][1]; ++i) {
731 					j = cell->entries[i][0];
732 					d2 = rm[j] - (ir << COLOR_SHIFT);
733 					d2 *= d2;
734 					tmp = gm[j] - (ig << COLOR_SHIFT);
735 					d2 += tmp*tmp;
736 					tmp = bm[j] - (ib << COLOR_SHIFT);
737 					d2 += tmp*tmp;
738 					if (d2 < dist) {
739 						dist = d2;
740 						*histp = j;
741 					}
742 				}
743 			}
744 }
745 
746 /*
747  * straight quantization.  Each pixel is mapped to the colors
748  * closest to it.  Color values are rounded to the nearest color
749  * table entry.
750  */
751 static void
quant(TIFF * in,TIFF * out)752 quant(TIFF* in, TIFF* out)
753 {
754 	unsigned char	*outline, *inputline;
755 	register unsigned char	*outptr, *inptr;
756 	register uint32 i, j;
757 	register int red, green, blue;
758 
759 	inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
760 	outline = (unsigned char *)_TIFFmalloc(imagewidth);
761 	for (i = 0; i < imagelength; i++) {
762 		if (TIFFReadScanline(in, inputline, i, 0) <= 0)
763 			break;
764 		inptr = inputline;
765 		outptr = outline;
766 		for (j = 0; j < imagewidth; j++) {
767 			red = *inptr++ >> COLOR_SHIFT;
768 			green = *inptr++ >> COLOR_SHIFT;
769 			blue = *inptr++ >> COLOR_SHIFT;
770 			*outptr++ = (unsigned char)histogram[red][green][blue];
771 		}
772 		if (TIFFWriteScanline(out, outline, i, 0) < 0)
773 			break;
774 	}
775 	_TIFFfree(inputline);
776 	_TIFFfree(outline);
777 }
778 
779 #define	SWAP(type,a,b)	{ type p; p = a; a = b; b = p; }
780 
781 #define	GetInputLine(tif, row, bad)				\
782 	if (TIFFReadScanline(tif, inputline, row, 0) <= 0)	\
783 		bad;						\
784 	inptr = inputline;					\
785 	nextptr = nextline;					\
786 	for (j = 0; j < imagewidth; ++j) {			\
787 		*nextptr++ = *inptr++;				\
788 		*nextptr++ = *inptr++;				\
789 		*nextptr++ = *inptr++;				\
790 	}
791 #define	GetComponent(raw, cshift, c)				\
792 	cshift = raw;						\
793 	if (cshift < 0)						\
794 		cshift = 0;					\
795 	else if (cshift >= MAX_COLOR)				\
796 		cshift = MAX_COLOR-1;				\
797 	c = cshift;						\
798 	cshift >>= COLOR_SHIFT;
799 
800 static void
quant_fsdither(TIFF * in,TIFF * out)801 quant_fsdither(TIFF* in, TIFF* out)
802 {
803 	unsigned char *outline, *inputline, *inptr;
804 	short *thisline, *nextline;
805 	register unsigned char	*outptr;
806 	register short *thisptr, *nextptr;
807 	register uint32 i, j;
808 	uint32 imax, jmax;
809 	int lastline, lastpixel;
810 
811 	imax = imagelength - 1;
812 	jmax = imagewidth - 1;
813 	inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
814 	thisline = (short *)_TIFFmalloc(imagewidth * 3 * sizeof (short));
815 	nextline = (short *)_TIFFmalloc(imagewidth * 3 * sizeof (short));
816 	outline = (unsigned char *) _TIFFmalloc(TIFFScanlineSize(out));
817 
818 	GetInputLine(in, 0, goto bad);		/* get first line */
819 	for (i = 1; i <= imagelength; ++i) {
820 		SWAP(short *, thisline, nextline);
821 		lastline = (i >= imax);
822 		if (i <= imax)
823 			GetInputLine(in, i, break);
824 		thisptr = thisline;
825 		nextptr = nextline;
826 		outptr = outline;
827 		for (j = 0; j < imagewidth; ++j) {
828 			int red, green, blue;
829 			register int oval, r2, g2, b2;
830 
831 			lastpixel = (j == jmax);
832 			GetComponent(*thisptr++, r2, red);
833 			GetComponent(*thisptr++, g2, green);
834 			GetComponent(*thisptr++, b2, blue);
835 			oval = histogram[r2][g2][b2];
836 			if (oval == -1) {
837 				int ci;
838 				register int cj, tmp, d2, dist;
839 				register C_cell	*cell;
840 
841 				cell = *(ColorCells +
842 				    (((r2>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2) +
843 				    ((g2>>(B_DEPTH-C_DEPTH)) << C_DEPTH ) +
844 				    (b2>>(B_DEPTH-C_DEPTH))));
845 				if (cell == NULL)
846 					cell = create_colorcell(red,
847 					    green, blue);
848 				dist = 9999999;
849 				for (ci = 0; ci < cell->num_ents && dist > cell->entries[ci][1]; ++ci) {
850 					cj = cell->entries[ci][0];
851 					d2 = (rm[cj] >> COLOR_SHIFT) - r2;
852 					d2 *= d2;
853 					tmp = (gm[cj] >> COLOR_SHIFT) - g2;
854 					d2 += tmp*tmp;
855 					tmp = (bm[cj] >> COLOR_SHIFT) - b2;
856 					d2 += tmp*tmp;
857 					if (d2 < dist) {
858 						dist = d2;
859 						oval = cj;
860 					}
861 				}
862 				histogram[r2][g2][b2] = oval;
863 			}
864 			*outptr++ = oval;
865 			red -= rm[oval];
866 			green -= gm[oval];
867 			blue -= bm[oval];
868 			if (!lastpixel) {
869 				thisptr[0] += blue * 7 / 16;
870 				thisptr[1] += green * 7 / 16;
871 				thisptr[2] += red * 7 / 16;
872 			}
873 			if (!lastline) {
874 				if (j != 0) {
875 					nextptr[-3] += blue * 3 / 16;
876 					nextptr[-2] += green * 3 / 16;
877 					nextptr[-1] += red * 3 / 16;
878 				}
879 				nextptr[0] += blue * 5 / 16;
880 				nextptr[1] += green * 5 / 16;
881 				nextptr[2] += red * 5 / 16;
882 				if (!lastpixel) {
883 					nextptr[3] += blue / 16;
884 				        nextptr[4] += green / 16;
885 				        nextptr[5] += red / 16;
886 				}
887 				nextptr += 3;
888 			}
889 		}
890 		if (TIFFWriteScanline(out, outline, i-1, 0) < 0)
891 			break;
892 	}
893 bad:
894 	_TIFFfree(inputline);
895 	_TIFFfree(thisline);
896 	_TIFFfree(nextline);
897 	_TIFFfree(outline);
898 }
899 /*
900  * Local Variables:
901  * mode: c
902  * c-basic-offset: 8
903  * fill-column: 78
904  * End:
905  */
906