]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/tools/tiffmedian.c
cab8d2957d1957b25b3789f5fa5b43674369967c
4 * Apply median cut on an image.
6 * tiffmedian [-c n] [-f] input output
7 * -C n - set colortable size. Default is 256.
8 * -f - use Floyd-Steinberg dithering.
9 * -c lzw - compress output with LZW
10 * -c none - use no compression on output
11 * -c packbits - use packbits compression on output
12 * -r n - create output with n rows/strip of data
13 * (by default the compression scheme and rows/strip are taken
14 * from the input file)
18 * [1] Floyd-Steinberg dither:
19 * I should point out that the actual fractions we used were, assuming
20 * you are at X, moving left to right:
25 * Note that the error goes to four neighbors, not three. I think this
26 * will probably do better (at least for black and white) than the
27 * 3/8-3/8-1/4 distribution, at the cost of greater processing. I have
28 * seen the 3/8-3/8-1/4 distribution described as "our" algorithm before,
29 * but I have no idea who the credit really belongs to.
31 * Also, I should add that if you do zig-zag scanning (see my immediately
32 * previous message), it is sufficient (but not quite as good) to send
33 * half the error one pixel ahead (e.g. to the right on lines you scan
34 * left to right), and half one pixel straight down. Again, this is for
35 * black and white; I've not tried it with color.
39 * [2] Color Image Quantization for Frame Buffer Display, Paul Heckbert,
40 * Siggraph '82 proceedings, pp. 297-307
43 #include "tif_config.h"
59 #define MAX_CMAP_SIZE 256
61 #define streq(a,b) (strcmp(a,b) == 0)
62 #define strneq(a,b,n) (strncmp(a,b,n) == 0)
67 #define B_DEPTH 5 /* # bits/pixel to use */
68 #define B_LEN (1L<<B_DEPTH)
71 #define C_LEN (1L<<C_DEPTH) /* # cells/color to use */
73 #define COLOR_SHIFT (COLOR_DEPTH-B_DEPTH)
75 typedef struct colorbox
{
76 struct colorbox
*next
, *prev
;
85 int entries
[MAX_CMAP_SIZE
][2];
88 uint16 rm
[MAX_CMAP_SIZE
], gm
[MAX_CMAP_SIZE
], bm
[MAX_CMAP_SIZE
];
90 uint32 histogram
[B_LEN
][B_LEN
][B_LEN
];
95 uint32 rowsperstrip
= (uint32
) -1;
96 uint16 compression
= (uint16
) -1;
97 uint16 bitspersample
= 1;
98 uint16 samplesperpixel
;
101 uint16 predictor
= 0;
103 static void get_histogram(TIFF
*, Colorbox
*);
104 static void splitbox(Colorbox
*);
105 static void shrinkbox(Colorbox
*);
106 static void map_colortable(void);
107 static void quant(TIFF
*, TIFF
*);
108 static void quant_fsdither(TIFF
*, TIFF
*);
109 static Colorbox
* largest_box(void);
111 static void usage(void);
112 static int processCompressOptions(char*);
114 #define CopyField(tag, v) \
115 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
118 main(int argc
, char* argv
[])
121 uint16 shortv
, config
, photometric
;
122 Colorbox
*box_list
, *ptr
;
129 num_colors
= MAX_CMAP_SIZE
;
130 while ((c
= getopt(argc
, argv
, "c:C:r:f")) != -1)
132 case 'c': /* compression scheme */
133 if (!processCompressOptions(optarg
))
136 case 'C': /* set colormap size */
137 num_colors
= atoi(optarg
);
138 if (num_colors
> MAX_CMAP_SIZE
) {
140 "-c: colormap too big, max %d\n",
145 case 'f': /* dither */
148 case 'r': /* rows/strip */
149 rowsperstrip
= atoi(optarg
);
155 if (argc
- optind
!= 2)
157 in
= TIFFOpen(argv
[optind
], "r");
160 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &imagewidth
);
161 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &imagelength
);
162 TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &bitspersample
);
163 TIFFGetField(in
, TIFFTAG_SAMPLESPERPIXEL
, &samplesperpixel
);
164 if (bitspersample
!= 8 && bitspersample
!= 16) {
165 fprintf(stderr
, "%s: Image must have at least 8-bits/sample\n",
169 if (!TIFFGetField(in
, TIFFTAG_PHOTOMETRIC
, &photometric
) ||
170 photometric
!= PHOTOMETRIC_RGB
|| samplesperpixel
< 3) {
171 fprintf(stderr
, "%s: Image must have RGB data\n", argv
[optind
]);
174 TIFFGetField(in
, TIFFTAG_PLANARCONFIG
, &config
);
175 if (config
!= PLANARCONFIG_CONTIG
) {
176 fprintf(stderr
, "%s: Can only handle contiguous data packing\n",
182 * STEP 1: create empty boxes
185 box_list
= freeboxes
= (Colorbox
*)_TIFFmalloc(num_colors
*sizeof (Colorbox
));
186 freeboxes
[0].next
= &freeboxes
[1];
187 freeboxes
[0].prev
= NULL
;
188 for (i
= 1; i
< num_colors
-1; ++i
) {
189 freeboxes
[i
].next
= &freeboxes
[i
+1];
190 freeboxes
[i
].prev
= &freeboxes
[i
-1];
192 freeboxes
[num_colors
-1].next
= NULL
;
193 freeboxes
[num_colors
-1].prev
= &freeboxes
[num_colors
-2];
196 * STEP 2: get histogram, initialize first box
199 freeboxes
= ptr
->next
;
201 freeboxes
->prev
= NULL
;
202 ptr
->next
= usedboxes
;
205 ptr
->next
->prev
= ptr
;
206 get_histogram(in
, ptr
);
209 * STEP 3: continually subdivide boxes until no more free
210 * boxes remain or until all colors assigned.
212 while (freeboxes
!= NULL
) {
221 * STEP 4: assign colors to all boxes
223 for (i
= 0, ptr
= usedboxes
; ptr
!= NULL
; ++i
, ptr
= ptr
->next
) {
224 rm
[i
] = ((ptr
->rmin
+ ptr
->rmax
) << COLOR_SHIFT
) / 2;
225 gm
[i
] = ((ptr
->gmin
+ ptr
->gmax
) << COLOR_SHIFT
) / 2;
226 bm
[i
] = ((ptr
->bmin
+ ptr
->bmax
) << COLOR_SHIFT
) / 2;
229 /* We're done with the boxes now */
231 freeboxes
= usedboxes
= NULL
;
234 * STEP 5: scan histogram and map all values to closest color
236 /* 5a: create cell list as described in Heckbert[2] */
237 ColorCells
= (C_cell
**)_TIFFmalloc(C_LEN
*C_LEN
*C_LEN
*sizeof (C_cell
*));
238 _TIFFmemset(ColorCells
, 0, C_LEN
*C_LEN
*C_LEN
*sizeof (C_cell
*));
239 /* 5b: create mapping from truncated pixel space to color
244 * STEP 6: scan image, match input values to table entries
246 out
= TIFFOpen(argv
[optind
+1], "w");
250 CopyField(TIFFTAG_SUBFILETYPE
, longv
);
251 CopyField(TIFFTAG_IMAGEWIDTH
, longv
);
252 TIFFSetField(out
, TIFFTAG_BITSPERSAMPLE
, (short)COLOR_DEPTH
);
253 if (compression
!= (uint16
)-1) {
254 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
);
255 switch (compression
) {
256 case COMPRESSION_LZW
:
257 case COMPRESSION_DEFLATE
:
259 TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
);
263 CopyField(TIFFTAG_COMPRESSION
, compression
);
264 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, (short)PHOTOMETRIC_PALETTE
);
265 CopyField(TIFFTAG_ORIENTATION
, shortv
);
266 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, (short)1);
267 CopyField(TIFFTAG_PLANARCONFIG
, shortv
);
268 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
,
269 TIFFDefaultStripSize(out
, rowsperstrip
));
270 CopyField(TIFFTAG_MINSAMPLEVALUE
, shortv
);
271 CopyField(TIFFTAG_MAXSAMPLEVALUE
, shortv
);
272 CopyField(TIFFTAG_RESOLUTIONUNIT
, shortv
);
273 CopyField(TIFFTAG_XRESOLUTION
, floatv
);
274 CopyField(TIFFTAG_YRESOLUTION
, floatv
);
275 CopyField(TIFFTAG_XPOSITION
, floatv
);
276 CopyField(TIFFTAG_YPOSITION
, floatv
);
279 quant_fsdither(in
, out
);
283 * Scale colormap to TIFF-required 16-bit values.
285 #define SCALE(x) (((x)*((1L<<16)-1))/255)
286 for (i
= 0; i
< MAX_CMAP_SIZE
; ++i
) {
287 rm
[i
] = SCALE(rm
[i
]);
288 gm
[i
] = SCALE(gm
[i
]);
289 bm
[i
] = SCALE(bm
[i
]);
291 TIFFSetField(out
, TIFFTAG_COLORMAP
, rm
, gm
, bm
);
292 (void) TIFFClose(out
);
297 processCompressOptions(char* opt
)
299 if (streq(opt
, "none"))
300 compression
= COMPRESSION_NONE
;
301 else if (streq(opt
, "packbits"))
302 compression
= COMPRESSION_PACKBITS
;
303 else if (strneq(opt
, "lzw", 3)) {
304 char* cp
= strchr(opt
, ':');
306 predictor
= atoi(cp
+1);
307 compression
= COMPRESSION_LZW
;
308 } else if (strneq(opt
, "zip", 3)) {
309 char* cp
= strchr(opt
, ':');
311 predictor
= atoi(cp
+1);
312 compression
= COMPRESSION_DEFLATE
;
319 "usage: tiffmedian [options] input.tif output.tif",
320 "where options are:",
321 " -r # make each strip have no more than # rows",
322 " -C # create a colormap with # entries",
323 " -f use Floyd-Steinberg dithering",
324 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
325 " -c zip[:opts] compress output with deflate encoding",
326 " -c packbits compress output with packbits encoding",
327 " -c none use no compression algorithm on output",
329 "LZW and deflate options:",
330 " # set predictor value",
331 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
342 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
343 for (i
= 0; stuff
[i
] != NULL
; i
++)
344 fprintf(stderr
, "%s\n", stuff
[i
]);
349 get_histogram(TIFF
* in
, Colorbox
* box
)
351 register unsigned char *inptr
;
352 register int red
, green
, blue
;
353 register uint32 j
, i
;
354 unsigned char *inputline
;
356 inputline
= (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in
));
357 if (inputline
== NULL
) {
358 fprintf(stderr
, "No space for scanline buffer\n");
361 box
->rmin
= box
->gmin
= box
->bmin
= 999;
362 box
->rmax
= box
->gmax
= box
->bmax
= -1;
363 box
->total
= imagewidth
* imagelength
;
365 { register uint32
*ptr
= &histogram
[0][0][0];
366 for (i
= B_LEN
*B_LEN
*B_LEN
; i
-- > 0;)
369 for (i
= 0; i
< imagelength
; i
++) {
370 if (TIFFReadScanline(in
, inputline
, i
, 0) <= 0)
373 for (j
= imagewidth
; j
-- > 0;) {
374 red
= *inptr
++ >> COLOR_SHIFT
;
375 green
= *inptr
++ >> COLOR_SHIFT
;
376 blue
= *inptr
++ >> COLOR_SHIFT
;
381 if (green
< box
->gmin
)
383 if (green
> box
->gmax
)
385 if (blue
< box
->bmin
)
387 if (blue
> box
->bmax
)
389 histogram
[red
][green
][blue
]++;
392 _TIFFfree(inputline
);
398 register Colorbox
*p
, *b
;
399 register uint32 size
;
403 for (p
= usedboxes
; p
!= NULL
; p
= p
->next
)
404 if ((p
->rmax
> p
->rmin
|| p
->gmax
> p
->gmin
||
405 p
->bmax
> p
->bmin
) && p
->total
> size
)
406 size
= (b
= p
)->total
;
411 splitbox(Colorbox
* ptr
)
415 register Colorbox
*new;
416 register uint32
*iptr
, *histp
;
418 register int ir
,ig
,ib
;
419 register uint32 sum
, sum1
, sum2
;
420 enum { RED
, GREEN
, BLUE
} axis
;
423 * See which axis is the largest, do a histogram along that
424 * axis. Split at median point. Contract both new boxes to
425 * fit points and return
427 i
= ptr
->rmax
- ptr
->rmin
;
428 if (i
>= ptr
->gmax
- ptr
->gmin
&& i
>= ptr
->bmax
- ptr
->bmin
)
430 else if (ptr
->gmax
- ptr
->gmin
>= ptr
->bmax
- ptr
->bmin
)
434 /* get histogram along longest axis */
437 histp
= &hist2
[ptr
->rmin
];
438 for (ir
= ptr
->rmin
; ir
<= ptr
->rmax
; ++ir
) {
440 for (ig
= ptr
->gmin
; ig
<= ptr
->gmax
; ++ig
) {
441 iptr
= &histogram
[ir
][ig
][ptr
->bmin
];
442 for (ib
= ptr
->bmin
; ib
<= ptr
->bmax
; ++ib
)
451 histp
= &hist2
[ptr
->gmin
];
452 for (ig
= ptr
->gmin
; ig
<= ptr
->gmax
; ++ig
) {
454 for (ir
= ptr
->rmin
; ir
<= ptr
->rmax
; ++ir
) {
455 iptr
= &histogram
[ir
][ig
][ptr
->bmin
];
456 for (ib
= ptr
->bmin
; ib
<= ptr
->bmax
; ++ib
)
465 histp
= &hist2
[ptr
->bmin
];
466 for (ib
= ptr
->bmin
; ib
<= ptr
->bmax
; ++ib
) {
468 for (ir
= ptr
->rmin
; ir
<= ptr
->rmax
; ++ir
) {
469 iptr
= &histogram
[ir
][ptr
->gmin
][ib
];
470 for (ig
= ptr
->gmin
; ig
<= ptr
->gmax
; ++ig
) {
481 /* find median point */
482 sum2
= ptr
->total
/ 2;
483 histp
= &hist2
[first
];
485 for (i
= first
; i
<= last
&& (sum
+= *histp
++) < sum2
; ++i
)
490 /* Create new box, re-allocate points */
492 freeboxes
= new->next
;
494 freeboxes
->prev
= NULL
;
496 usedboxes
->prev
= new;
497 new->next
= usedboxes
;
500 histp
= &hist2
[first
];
501 for (sum1
= 0, j
= first
; j
< i
; j
++)
503 for (sum2
= 0, j
= i
; j
<= last
; j
++)
508 new->rmin
= ptr
->rmin
;
509 new->rmax
= ptr
->rmax
;
510 new->gmin
= ptr
->gmin
;
511 new->gmax
= ptr
->gmax
;
512 new->bmin
= ptr
->bmin
;
513 new->bmax
= ptr
->bmax
;
533 shrinkbox(Colorbox
* box
)
535 register uint32
*histp
;
536 register int ir
, ig
, ib
;
538 if (box
->rmax
> box
->rmin
) {
539 for (ir
= box
->rmin
; ir
<= box
->rmax
; ++ir
)
540 for (ig
= box
->gmin
; ig
<= box
->gmax
; ++ig
) {
541 histp
= &histogram
[ir
][ig
][box
->bmin
];
542 for (ib
= box
->bmin
; ib
<= box
->bmax
; ++ib
)
549 if (box
->rmax
> box
->rmin
)
550 for (ir
= box
->rmax
; ir
>= box
->rmin
; --ir
)
551 for (ig
= box
->gmin
; ig
<= box
->gmax
; ++ig
) {
552 histp
= &histogram
[ir
][ig
][box
->bmin
];
554 for (; ib
<= box
->bmax
; ++ib
)
562 if (box
->gmax
> box
->gmin
) {
563 for (ig
= box
->gmin
; ig
<= box
->gmax
; ++ig
)
564 for (ir
= box
->rmin
; ir
<= box
->rmax
; ++ir
) {
565 histp
= &histogram
[ir
][ig
][box
->bmin
];
566 for (ib
= box
->bmin
; ib
<= box
->bmax
; ++ib
)
573 if (box
->gmax
> box
->gmin
)
574 for (ig
= box
->gmax
; ig
>= box
->gmin
; --ig
)
575 for (ir
= box
->rmin
; ir
<= box
->rmax
; ++ir
) {
576 histp
= &histogram
[ir
][ig
][box
->bmin
];
578 for (; ib
<= box
->bmax
; ++ib
)
586 if (box
->bmax
> box
->bmin
) {
587 for (ib
= box
->bmin
; ib
<= box
->bmax
; ++ib
)
588 for (ir
= box
->rmin
; ir
<= box
->rmax
; ++ir
) {
589 histp
= &histogram
[ir
][box
->gmin
][ib
];
590 for (ig
= box
->gmin
; ig
<= box
->gmax
; ++ig
) {
599 if (box
->bmax
> box
->bmin
)
600 for (ib
= box
->bmax
; ib
>= box
->bmin
; --ib
)
601 for (ir
= box
->rmin
; ir
<= box
->rmax
; ++ir
) {
602 histp
= &histogram
[ir
][box
->gmin
][ib
];
604 for (; ig
<= box
->gmax
; ++ig
) {
618 create_colorcell(int red
, int green
, int blue
)
620 register int ir
, ig
, ib
, i
;
621 register C_cell
*ptr
;
623 register int tmp
, dist
, n
;
625 ir
= red
>> (COLOR_DEPTH
-C_DEPTH
);
626 ig
= green
>> (COLOR_DEPTH
-C_DEPTH
);
627 ib
= blue
>> (COLOR_DEPTH
-C_DEPTH
);
628 ptr
= (C_cell
*)_TIFFmalloc(sizeof (C_cell
));
629 *(ColorCells
+ ir
*C_LEN
*C_LEN
+ ig
*C_LEN
+ ib
) = ptr
;
633 * Step 1: find all colors inside this cell, while we're at
634 * it, find distance of centermost point to furthest corner
637 for (i
= 0; i
< num_colors
; ++i
) {
638 if (rm
[i
]>>(COLOR_DEPTH
-C_DEPTH
) != ir
||
639 gm
[i
]>>(COLOR_DEPTH
-C_DEPTH
) != ig
||
640 bm
[i
]>>(COLOR_DEPTH
-C_DEPTH
) != ib
)
642 ptr
->entries
[ptr
->num_ents
][0] = i
;
643 ptr
->entries
[ptr
->num_ents
][1] = 0;
646 if (tmp
< (MAX_COLOR
/C_LEN
/2))
647 tmp
= MAX_COLOR
/C_LEN
-1 - tmp
;
650 if (tmp
< (MAX_COLOR
/C_LEN
/2))
651 tmp
= MAX_COLOR
/C_LEN
-1 - tmp
;
654 if (tmp
< (MAX_COLOR
/C_LEN
/2))
655 tmp
= MAX_COLOR
/C_LEN
-1 - tmp
;
662 * Step 3: find all points within that distance to cell.
664 for (i
= 0; i
< num_colors
; ++i
) {
665 if (rm
[i
] >> (COLOR_DEPTH
-C_DEPTH
) == ir
&&
666 gm
[i
] >> (COLOR_DEPTH
-C_DEPTH
) == ig
&&
667 bm
[i
] >> (COLOR_DEPTH
-C_DEPTH
) == ib
)
670 if ((tmp
= red
- rm
[i
]) > 0 ||
671 (tmp
= rm
[i
] - (red
+ MAX_COLOR
/C_LEN
-1)) > 0 )
673 if ((tmp
= green
- gm
[i
]) > 0 ||
674 (tmp
= gm
[i
] - (green
+ MAX_COLOR
/C_LEN
-1)) > 0 )
676 if ((tmp
= blue
- bm
[i
]) > 0 ||
677 (tmp
= bm
[i
] - (blue
+ MAX_COLOR
/C_LEN
-1)) > 0 )
679 if (dist
< mindist
) {
680 ptr
->entries
[ptr
->num_ents
][0] = i
;
681 ptr
->entries
[ptr
->num_ents
][1] = dist
;
687 * Sort color cells by distance, use cheap exchange sort
689 for (n
= ptr
->num_ents
- 1; n
> 0; n
= next_n
) {
691 for (i
= 0; i
< n
; ++i
)
692 if (ptr
->entries
[i
][1] > ptr
->entries
[i
+1][1]) {
693 tmp
= ptr
->entries
[i
][0];
694 ptr
->entries
[i
][0] = ptr
->entries
[i
+1][0];
695 ptr
->entries
[i
+1][0] = tmp
;
696 tmp
= ptr
->entries
[i
][1];
697 ptr
->entries
[i
][1] = ptr
->entries
[i
+1][1];
698 ptr
->entries
[i
+1][1] = tmp
;
708 register uint32
*histp
= &histogram
[0][0][0];
709 register C_cell
*cell
;
710 register int j
, tmp
, d2
, dist
;
713 for (ir
= 0; ir
< B_LEN
; ++ir
)
714 for (ig
= 0; ig
< B_LEN
; ++ig
)
715 for (ib
= 0; ib
< B_LEN
; ++ib
, histp
++) {
720 cell
= *(ColorCells
+
721 (((ir
>>(B_DEPTH
-C_DEPTH
)) << C_DEPTH
*2) +
722 ((ig
>>(B_DEPTH
-C_DEPTH
)) << C_DEPTH
) +
723 (ib
>>(B_DEPTH
-C_DEPTH
))));
725 cell
= create_colorcell(
730 for (i
= 0; i
< cell
->num_ents
&&
731 dist
> cell
->entries
[i
][1]; ++i
) {
732 j
= cell
->entries
[i
][0];
733 d2
= rm
[j
] - (ir
<< COLOR_SHIFT
);
735 tmp
= gm
[j
] - (ig
<< COLOR_SHIFT
);
737 tmp
= bm
[j
] - (ib
<< COLOR_SHIFT
);
748 * straight quantization. Each pixel is mapped to the colors
749 * closest to it. Color values are rounded to the nearest color
753 quant(TIFF
* in
, TIFF
* out
)
755 unsigned char *outline
, *inputline
;
756 register unsigned char *outptr
, *inptr
;
757 register uint32 i
, j
;
758 register int red
, green
, blue
;
760 inputline
= (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in
));
761 outline
= (unsigned char *)_TIFFmalloc(imagewidth
);
762 for (i
= 0; i
< imagelength
; i
++) {
763 if (TIFFReadScanline(in
, inputline
, i
, 0) <= 0)
767 for (j
= 0; j
< imagewidth
; j
++) {
768 red
= *inptr
++ >> COLOR_SHIFT
;
769 green
= *inptr
++ >> COLOR_SHIFT
;
770 blue
= *inptr
++ >> COLOR_SHIFT
;
771 *outptr
++ = (unsigned char)histogram
[red
][green
][blue
];
773 if (TIFFWriteScanline(out
, outline
, i
, 0) < 0)
776 _TIFFfree(inputline
);
780 #define SWAP(type,a,b) { type p; p = a; a = b; b = p; }
782 #define GetInputLine(tif, row, bad) \
783 if (TIFFReadScanline(tif, inputline, row, 0) <= 0) \
786 nextptr = nextline; \
787 for (j = 0; j < imagewidth; ++j) { \
788 *nextptr++ = *inptr++; \
789 *nextptr++ = *inptr++; \
790 *nextptr++ = *inptr++; \
792 #define GetComponent(raw, cshift, c) \
796 else if (cshift >= MAX_COLOR) \
797 cshift = MAX_COLOR-1; \
799 cshift >>= COLOR_SHIFT;
802 quant_fsdither(TIFF
* in
, TIFF
* out
)
804 unsigned char *outline
, *inputline
, *inptr
;
805 short *thisline
, *nextline
;
806 register unsigned char *outptr
;
807 register short *thisptr
, *nextptr
;
808 register uint32 i
, j
;
810 int lastline
, lastpixel
;
812 imax
= imagelength
- 1;
813 jmax
= imagewidth
- 1;
814 inputline
= (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in
));
815 thisline
= (short *)_TIFFmalloc(imagewidth
* 3 * sizeof (short));
816 nextline
= (short *)_TIFFmalloc(imagewidth
* 3 * sizeof (short));
817 outline
= (unsigned char *) _TIFFmalloc(TIFFScanlineSize(out
));
819 GetInputLine(in
, 0, goto bad
); /* get first line */
820 for (i
= 1; i
<= imagelength
; ++i
) {
821 SWAP(short *, thisline
, nextline
);
822 lastline
= (i
>= imax
);
824 GetInputLine(in
, i
, break);
828 for (j
= 0; j
< imagewidth
; ++j
) {
829 int red
, green
, blue
;
830 register int oval
, r2
, g2
, b2
;
832 lastpixel
= (j
== jmax
);
833 GetComponent(*thisptr
++, r2
, red
);
834 GetComponent(*thisptr
++, g2
, green
);
835 GetComponent(*thisptr
++, b2
, blue
);
836 oval
= histogram
[r2
][g2
][b2
];
839 register int cj
, tmp
, d2
, dist
;
840 register C_cell
*cell
;
842 cell
= *(ColorCells
+
843 (((r2
>>(B_DEPTH
-C_DEPTH
)) << C_DEPTH
*2) +
844 ((g2
>>(B_DEPTH
-C_DEPTH
)) << C_DEPTH
) +
845 (b2
>>(B_DEPTH
-C_DEPTH
))));
847 cell
= create_colorcell(red
,
850 for (ci
= 0; ci
< cell
->num_ents
&& dist
> cell
->entries
[ci
][1]; ++ci
) {
851 cj
= cell
->entries
[ci
][0];
852 d2
= (rm
[cj
] >> COLOR_SHIFT
) - r2
;
854 tmp
= (gm
[cj
] >> COLOR_SHIFT
) - g2
;
856 tmp
= (bm
[cj
] >> COLOR_SHIFT
) - b2
;
863 histogram
[r2
][g2
][b2
] = oval
;
870 thisptr
[0] += blue
* 7 / 16;
871 thisptr
[1] += green
* 7 / 16;
872 thisptr
[2] += red
* 7 / 16;
876 nextptr
[-3] += blue
* 3 / 16;
877 nextptr
[-2] += green
* 3 / 16;
878 nextptr
[-1] += red
* 3 / 16;
880 nextptr
[0] += blue
* 5 / 16;
881 nextptr
[1] += green
* 5 / 16;
882 nextptr
[2] += red
* 5 / 16;
884 nextptr
[3] += blue
/ 16;
885 nextptr
[4] += green
/ 16;
886 nextptr
[5] += red
/ 16;
891 if (TIFFWriteScanline(out
, outline
, i
-1, 0) < 0)
895 _TIFFfree(inputline
);