summaryrefslogtreecommitdiff
path: root/tools/tiffmedian.c
diff options
context:
space:
mode:
authorpre-commit run by Even Rouault <even.rouault-bot@spatialys.com>2022-12-08 19:19:07 +0100
committerEven Rouault <even.rouault@spatialys.com>2022-12-08 19:19:07 +0100
commitb0ae5d7071890160da67d2e833d84a400e0406d0 (patch)
treeb827d1395fda08ad29130a964a313eccb7d07413 /tools/tiffmedian.c
parent42173d6ace476b5228d866640b5355f74e5a108d (diff)
downloadlibtiff-git-b0ae5d7071890160da67d2e833d84a400e0406d0.tar.gz
Reformatting in tools/ using 'pre-commit run'
Diffstat (limited to 'tools/tiffmedian.c')
-rw-r--r--tools/tiffmedian.c1683
1 files changed, 877 insertions, 806 deletions
diff --git a/tools/tiffmedian.c b/tools/tiffmedian.c
index 259525dd..8225970c 100644
--- a/tools/tiffmedian.c
+++ b/tools/tiffmedian.c
@@ -4,7 +4,7 @@
* 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 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
@@ -18,7 +18,7 @@
* you are at X, moving left to right:
*
* X 7/16
- * 3/16 5/16 1/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
@@ -31,22 +31,22 @@
* 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 "libport.h"
+#include "tif_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
-# include <unistd.h>
+#include <unistd.h>
#endif
#include "tiffio.h"
@@ -58,714 +58,767 @@
#define EXIT_FAILURE 1
#endif
-#define MAX_CMAP_SIZE 256
+#define MAX_CMAP_SIZE 256
-#define streq(a,b) (strcmp(a,b) == 0)
-#define strneq(a,b,n) (strncmp(a,b,n) == 0)
+#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 COLOR_DEPTH 8
+#define MAX_COLOR 256
-#define B_DEPTH 5 /* # bits/pixel to use */
-#define B_LEN (1L<<B_DEPTH)
+#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 C_DEPTH 2
+#define C_LEN (1L << C_DEPTH) /* # cells/color to use */
-#define COLOR_SHIFT (COLOR_DEPTH-B_DEPTH)
+#define COLOR_SHIFT (COLOR_DEPTH - B_DEPTH)
-typedef struct colorbox {
- struct colorbox *next, *prev;
- int rmin, rmax;
- int gmin, gmax;
- int bmin, bmax;
- uint32_t total;
+typedef struct colorbox
+{
+ struct colorbox *next, *prev;
+ int rmin, rmax;
+ int gmin, gmax;
+ int bmin, bmax;
+ uint32_t total;
} Colorbox;
-typedef struct {
- int num_ents;
- int entries[MAX_CMAP_SIZE][2];
+typedef struct
+{
+ int num_ents;
+ int entries[MAX_CMAP_SIZE][2];
} C_cell;
-static uint16_t rm[MAX_CMAP_SIZE], gm[MAX_CMAP_SIZE], bm[MAX_CMAP_SIZE];
-static int num_colors;
-static uint32_t histogram[B_LEN][B_LEN][B_LEN];
+static uint16_t rm[MAX_CMAP_SIZE], gm[MAX_CMAP_SIZE], bm[MAX_CMAP_SIZE];
+static int num_colors;
+static uint32_t histogram[B_LEN][B_LEN][B_LEN];
static Colorbox *freeboxes;
static Colorbox *usedboxes;
-static C_cell **ColorCells;
-static TIFF *in, *out;
-static uint32_t rowsperstrip = (uint32_t) -1;
-static uint16_t compression = (uint16_t) -1;
-static uint16_t bitspersample = 1;
-static uint16_t samplesperpixel;
-static uint32_t imagewidth;
-static uint32_t imagelength;
-static uint16_t 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(int);
-static int processCompressOptions(char*);
-
-#define CopyField(tag, v) \
- if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
-
-int
-main(int argc, char* argv[])
+static C_cell **ColorCells;
+static TIFF *in, *out;
+static uint32_t rowsperstrip = (uint32_t)-1;
+static uint16_t compression = (uint16_t)-1;
+static uint16_t bitspersample = 1;
+static uint16_t samplesperpixel;
+static uint32_t imagewidth;
+static uint32_t imagelength;
+static uint16_t 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(int);
+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_t shortv, config, photometric;
- Colorbox *box_list, *ptr;
- float floatv;
- uint32_t longv;
- int c;
+ int i, dither = 0;
+ uint16_t shortv, config, photometric;
+ Colorbox *box_list, *ptr;
+ float floatv;
+ uint32_t longv;
+ int c;
#if !HAVE_DECL_OPTARG
- extern int optind;
- extern char* optarg;
+ extern int optind;
+ extern char *optarg;
#endif
- num_colors = MAX_CMAP_SIZE;
- while ((c = getopt(argc, argv, "c:C:r:fh")) != -1)
- switch (c) {
- case 'c': /* compression scheme */
- if (!processCompressOptions(optarg))
- usage(EXIT_FAILURE);
- 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(EXIT_FAILURE);
- }
- break;
- case 'f': /* dither */
- dither = 1;
- break;
- case 'r': /* rows/strip */
- rowsperstrip = atoi(optarg);
- break;
- case 'h':
- usage(EXIT_SUCCESS);
- /*NOTREACHED*/
- break;
- case '?':
- usage(EXIT_FAILURE);
- /*NOTREACHED*/
- break;
- }
- if (argc - optind != 2)
- usage(EXIT_FAILURE);
- in = TIFFOpen(argv[optind], "r");
- if (in == NULL)
- return (EXIT_FAILURE);
- 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 (EXIT_FAILURE);
- }
- if (!TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric) ||
- photometric != PHOTOMETRIC_RGB || samplesperpixel < 3) {
- fprintf(stderr, "%s: Image must have RGB data\n", argv[optind]);
- return (EXIT_FAILURE);
- }
- TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config);
- if (config != PLANARCONFIG_CONTIG) {
- fprintf(stderr, "%s: Can only handle contiguous data packing\n",
- argv[optind]);
- return (EXIT_FAILURE);
- }
-
- /*
- * 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 (EXIT_FAILURE);
-
- CopyField(TIFFTAG_SUBFILETYPE, longv);
- CopyField(TIFFTAG_IMAGEWIDTH, longv);
- TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (short)COLOR_DEPTH);
- if (compression != (uint16_t)-1) {
- TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
- switch (compression) {
- case COMPRESSION_LZW:
- case COMPRESSION_ADOBE_DEFLATE:
- 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 (EXIT_SUCCESS);
+ num_colors = MAX_CMAP_SIZE;
+ while ((c = getopt(argc, argv, "c:C:r:fh")) != -1)
+ switch (c)
+ {
+ case 'c': /* compression scheme */
+ if (!processCompressOptions(optarg))
+ usage(EXIT_FAILURE);
+ 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(EXIT_FAILURE);
+ }
+ break;
+ case 'f': /* dither */
+ dither = 1;
+ break;
+ case 'r': /* rows/strip */
+ rowsperstrip = atoi(optarg);
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ /*NOTREACHED*/
+ break;
+ case '?':
+ usage(EXIT_FAILURE);
+ /*NOTREACHED*/
+ break;
+ }
+ if (argc - optind != 2)
+ usage(EXIT_FAILURE);
+ in = TIFFOpen(argv[optind], "r");
+ if (in == NULL)
+ return (EXIT_FAILURE);
+ 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 (EXIT_FAILURE);
+ }
+ if (!TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric) ||
+ photometric != PHOTOMETRIC_RGB || samplesperpixel < 3)
+ {
+ fprintf(stderr, "%s: Image must have RGB data\n", argv[optind]);
+ return (EXIT_FAILURE);
+ }
+ TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config);
+ if (config != PLANARCONFIG_CONTIG)
+ {
+ fprintf(stderr, "%s: Can only handle contiguous data packing\n",
+ argv[optind]);
+ return (EXIT_FAILURE);
+ }
+
+ /*
+ * 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 (EXIT_FAILURE);
+
+ CopyField(TIFFTAG_SUBFILETYPE, longv);
+ CopyField(TIFFTAG_IMAGEWIDTH, longv);
+ TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (short)COLOR_DEPTH);
+ if (compression != (uint16_t)-1)
+ {
+ TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
+ switch (compression)
+ {
+ case COMPRESSION_LZW:
+ case COMPRESSION_ADOBE_DEFLATE:
+ 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 (EXIT_SUCCESS);
}
-static int
-processCompressOptions(char* opt)
+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_ADOBE_DEFLATE;
- } else
- return (0);
- return (1);
+ 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_ADOBE_DEFLATE;
+ }
+ else
+ return (0);
+ return (1);
}
static const char usage_info[] =
-"Apply the median cut algorithm to an RGB TIFF file\n\n"
-"usage: tiffmedian [options] input.tif output.tif\n"
-"where options are:\n"
-" -r # make each strip have no more than # rows\n"
-" -C # create a colormap with # entries\n"
-" -f use Floyd-Steinberg dithering\n"
-"\n"
+ "Apply the median cut algorithm to an RGB TIFF file\n\n"
+ "usage: tiffmedian [options] input.tif output.tif\n"
+ "where options are:\n"
+ " -r # make each strip have no more than # rows\n"
+ " -C # create a colormap with # entries\n"
+ " -f use Floyd-Steinberg dithering\n"
+ "\n"
#ifdef LZW_SUPPORT
-" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding\n"
-/* " LZW options:" */
-" # set predictor value\n"
-" For example, -c lzw:2 to get LZW-encoded data with horizontal differencing\n"
+ " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding\n"
+ /* " LZW options:" */
+ " # set predictor value\n"
+ " For example, -c lzw:2 to get LZW-encoded data with horizontal "
+ "differencing\n"
#endif
#ifdef ZIP_SUPPORT
-" -c zip[:opts] compress output with deflate encoding\n"
-/* " Deflate (ZIP) options:" */
-" # set predictor value\n"
+ " -c zip[:opts] compress output with deflate encoding\n"
+ /* " Deflate (ZIP) options:" */
+ " # set predictor value\n"
#endif
#ifdef PACKBITS_SUPPORT
-" -c packbits compress output with packbits encoding\n"
+ " -c packbits compress output with packbits encoding\n"
#endif
#if defined(LZW_SUPPORT) || defined(ZIP_SUPPORT) || defined(PACKBITS_SUPPORT)
-" -c none use no compression algorithm on output\n"
+ " -c none use no compression algorithm on output\n"
#endif
-"\n"
-;
+ "\n";
-static void
-usage(int code)
+static void usage(int code)
{
- FILE * out = (code == EXIT_SUCCESS) ? stdout : stderr;
+ FILE *out = (code == EXIT_SUCCESS) ? stdout : stderr;
- fprintf(out, "%s\n\n", TIFFGetVersion());
- fprintf(out, "%s", usage_info);
- exit(code);
+ fprintf(out, "%s\n\n", TIFFGetVersion());
+ fprintf(out, "%s", usage_info);
+ exit(code);
}
-static void
-get_histogram(TIFF* in, Colorbox* box)
+static void get_histogram(TIFF *in, Colorbox *box)
{
- register unsigned char *inptr;
- register int red, green, blue;
- register uint32_t j, i;
- unsigned char *inputline;
-
- inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
- if (inputline == NULL) {
- fprintf(stderr, "No space for scanline buffer\n");
- exit(EXIT_FAILURE);
- }
- box->rmin = box->gmin = box->bmin = 999;
- box->rmax = box->gmax = box->bmax = -1;
- box->total = imagewidth * imagelength;
-
- { register uint32_t *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++) & 0xff >> COLOR_SHIFT;
- green = (*inptr++) & 0xff >> COLOR_SHIFT;
- blue = (*inptr++) & 0xff >> COLOR_SHIFT;
- if ((red | green | blue) >= B_LEN) {
- fprintf(stderr,
- "Logic error. "
- "Histogram array overflow!\n");
- exit(EXIT_FAILURE);
- }
- 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);
+ register unsigned char *inptr;
+ register int red, green, blue;
+ register uint32_t j, i;
+ unsigned char *inputline;
+
+ inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
+ if (inputline == NULL)
+ {
+ fprintf(stderr, "No space for scanline buffer\n");
+ exit(EXIT_FAILURE);
+ }
+ box->rmin = box->gmin = box->bmin = 999;
+ box->rmax = box->gmax = box->bmax = -1;
+ box->total = imagewidth * imagelength;
+
+ {
+ register uint32_t *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++) & 0xff >> COLOR_SHIFT;
+ green = (*inptr++) & 0xff >> COLOR_SHIFT;
+ blue = (*inptr++) & 0xff >> COLOR_SHIFT;
+ if ((red | green | blue) >= B_LEN)
+ {
+ fprintf(stderr, "Logic error. "
+ "Histogram array overflow!\n");
+ exit(EXIT_FAILURE);
+ }
+ 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)
+static Colorbox *largest_box(void)
{
- register Colorbox *p, *b;
- register uint32_t 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);
+ register Colorbox *p, *b;
+ register uint32_t 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)
+static void splitbox(Colorbox *ptr)
{
- uint32_t hist2[B_LEN];
- int first=0, last=0;
- register Colorbox *new;
- register uint32_t *iptr, *histp;
- register int i, j;
- register int ir,ig,ib;
- register uint32_t 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);
+ uint32_t hist2[B_LEN];
+ int first = 0, last = 0;
+ register Colorbox *new;
+ register uint32_t *iptr, *histp;
+ register int i, j;
+ register int ir, ig, ib;
+ register uint32_t 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)
+static void shrinkbox(Colorbox *box)
{
- register uint32_t *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;
- }
- }
- }
+ register uint32_t *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;
- }
- }
- }
+ 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:
- ;
+ 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)
+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);
+ 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)
+static void map_colortable(void)
{
- register uint32_t *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;
- }
- }
- }
+ register uint32_t *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;
+ }
+ }
+ }
}
/*
@@ -773,155 +826,173 @@ map_colortable(void)
* closest to it. Color values are rounded to the nearest color
* table entry.
*/
-static void
-quant(TIFF* in, TIFF* out)
+static void quant(TIFF *in, TIFF *out)
{
- unsigned char *outline, *inputline;
- register unsigned char *outptr, *inptr;
- register uint32_t 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);
+ unsigned char *outline, *inputline;
+ register unsigned char *outptr, *inptr;
+ register uint32_t 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) \
- do { \
- if (TIFFReadScanline(tif, inputline, row, 0) <= 0) \
- bad; \
- inptr = inputline; \
- nextptr = nextline; \
- for (j = 0; j < imagewidth; ++j) { \
- *nextptr++ = *inptr++; \
- *nextptr++ = *inptr++; \
- *nextptr++ = *inptr++; \
- } \
- } while (0);
-#define GetComponent(raw, cshift, c) \
- do { \
- cshift = raw; \
- if (cshift < 0) \
- cshift = 0; \
- else if (cshift >= MAX_COLOR) \
- cshift = MAX_COLOR-1; \
- c = cshift; \
- cshift >>= COLOR_SHIFT; \
- } while (0);
-
-static void
-quant_fsdither(TIFF* in, TIFF* out)
+#define SWAP(type, a, b) \
+ { \
+ type p; \
+ p = a; \
+ a = b; \
+ b = p; \
+ }
+
+#define GetInputLine(tif, row, bad) \
+ do \
+ { \
+ if (TIFFReadScanline(tif, inputline, row, 0) <= 0) \
+ bad; \
+ inptr = inputline; \
+ nextptr = nextline; \
+ for (j = 0; j < imagewidth; ++j) \
+ { \
+ *nextptr++ = *inptr++; \
+ *nextptr++ = *inptr++; \
+ *nextptr++ = *inptr++; \
+ } \
+ } while (0);
+#define GetComponent(raw, cshift, c) \
+ do \
+ { \
+ cshift = raw; \
+ if (cshift < 0) \
+ cshift = 0; \
+ else if (cshift >= MAX_COLOR) \
+ cshift = MAX_COLOR - 1; \
+ c = cshift; \
+ cshift >>= COLOR_SHIFT; \
+ } while (0);
+
+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_t i, j;
- uint32_t 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;
- }
+ unsigned char *outline, *inputline, *inptr;
+ short *thisline, *nextline;
+ register unsigned char *outptr;
+ register short *thisptr, *nextptr;
+ register uint32_t i, j;
+ uint32_t 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);
+ _TIFFfree(inputline);
+ _TIFFfree(thisline);
+ _TIFFfree(nextline);
+ _TIFFfree(outline);
}