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