1
/* $Id: tiffdither.c,v 1.9.2.1 2010-06-08 18:50:44 bfriesen Exp $ */
4
* Copyright (c) 1988-1997 Sam Leffler
5
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
7
* Permission to use, copy, modify, distribute, and sell this software and
8
* its documentation for any purpose is hereby granted without fee, provided
9
* that (i) the above copyright notices and this permission notice appear in
10
* all copies of the software and related documentation, and (ii) the names of
11
* Sam Leffler and Silicon Graphics may not be used in any advertising or
12
* publicity relating to the software without the specific, prior written
13
* permission of Sam Leffler and Silicon Graphics.
15
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
27
#include "tif_config.h"
39
#define streq(a,b) (strcmp(a,b) == 0)
40
#define strneq(a,b,n) (strncmp(a,b,n) == 0)
42
#define CopyField(tag, v) \
43
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
49
static void usage(void);
52
* Floyd-Steinberg error propragation with threshold.
53
* This code is stolen from tiffmedian.
56
fsdither(TIFF* in, TIFF* out)
58
unsigned char *outline, *inputline, *inptr;
59
short *thisline, *nextline, *tmpptr;
60
register unsigned char *outptr;
61
register short *thisptr, *nextptr;
64
int lastline, lastpixel;
68
imax = imagelength - 1;
69
jmax = imagewidth - 1;
70
inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
71
thisline = (short *)_TIFFmalloc(imagewidth * sizeof (short));
72
nextline = (short *)_TIFFmalloc(imagewidth * sizeof (short));
73
outlinesize = TIFFScanlineSize(out);
74
outline = (unsigned char *) _TIFFmalloc(outlinesize);
79
if (TIFFReadScanline(in, inputline, 0, 0) <= 0)
83
for (j = 0; j < imagewidth; ++j)
84
*nextptr++ = *inptr++;
85
for (i = 1; i < imagelength; ++i) {
89
lastline = (i == imax);
90
if (TIFFReadScanline(in, inputline, i, 0) <= 0)
94
for (j = 0; j < imagewidth; ++j)
95
*nextptr++ = *inptr++;
98
_TIFFmemset(outptr = outline, 0, outlinesize);
100
for (j = 0; j < imagewidth; ++j) {
103
lastpixel = (j == jmax);
119
thisptr[0] += v * 7 / 16;
122
nextptr[-1] += v * 3 / 16;
123
*nextptr++ += v * 5 / 16;
125
nextptr[0] += v / 16;
128
if (TIFFWriteScanline(out, outline, i-1, 0) < 0)
131
_TIFFfree(inputline);
137
static uint16 compression = COMPRESSION_PACKBITS;
138
static uint16 predictor = 0;
139
static uint32 group3options = 0;
142
processG3Options(char* cp)
144
if ((cp = strchr(cp, ':'))) {
147
if (strneq(cp, "1d", 2))
148
group3options &= ~GROUP3OPT_2DENCODING;
149
else if (strneq(cp, "2d", 2))
150
group3options |= GROUP3OPT_2DENCODING;
151
else if (strneq(cp, "fill", 4))
152
group3options |= GROUP3OPT_FILLBITS;
155
} while ((cp = strchr(cp, ':')));
160
processCompressOptions(char* opt)
162
if (streq(opt, "none"))
163
compression = COMPRESSION_NONE;
164
else if (streq(opt, "packbits"))
165
compression = COMPRESSION_PACKBITS;
166
else if (strneq(opt, "g3", 2)) {
167
processG3Options(opt);
168
compression = COMPRESSION_CCITTFAX3;
169
} else if (streq(opt, "g4"))
170
compression = COMPRESSION_CCITTFAX4;
171
else if (strneq(opt, "lzw", 3)) {
172
char* cp = strchr(opt, ':');
174
predictor = atoi(cp+1);
175
compression = COMPRESSION_LZW;
176
} else if (strneq(opt, "zip", 3)) {
177
char* cp = strchr(opt, ':');
179
predictor = atoi(cp+1);
180
compression = COMPRESSION_DEFLATE;
187
main(int argc, char* argv[])
190
uint16 samplesperpixel, bitspersample = 1, shortv;
193
uint32 rowsperstrip = (uint32) -1;
195
uint16 fillorder = 0;
200
while ((c = getopt(argc, argv, "c:f:r:t:")) != -1)
202
case 'c': /* compression scheme */
203
if (!processCompressOptions(optarg))
206
case 'f': /* fill order */
207
if (streq(optarg, "lsb2msb"))
208
fillorder = FILLORDER_LSB2MSB;
209
else if (streq(optarg, "msb2lsb"))
210
fillorder = FILLORDER_MSB2LSB;
214
case 'r': /* rows/strip */
215
rowsperstrip = atoi(optarg);
219
threshold = atoi(optarg);
222
else if (threshold > 255)
229
if (argc - optind < 2)
231
in = TIFFOpen(argv[optind], "r");
234
TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
235
if (samplesperpixel != 1) {
236
fprintf(stderr, "%s: Not a b&w image.\n", argv[0]);
239
TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample);
240
if (bitspersample != 8) {
242
" %s: Sorry, only handle 8-bit samples.\n", argv[0]);
245
out = TIFFOpen(argv[optind+1], "w");
248
CopyField(TIFFTAG_IMAGEWIDTH, imagewidth);
249
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength);
250
TIFFSetField(out, TIFFTAG_IMAGELENGTH, imagelength-1);
251
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1);
252
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
253
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
254
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
256
TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
258
CopyField(TIFFTAG_FILLORDER, shortv);
259
snprintf(thing, sizeof(thing), "Dithered B&W version of %s", argv[optind]);
260
TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, thing);
261
CopyField(TIFFTAG_PHOTOMETRIC, shortv);
262
CopyField(TIFFTAG_ORIENTATION, shortv);
263
CopyField(TIFFTAG_XRESOLUTION, floatv);
264
CopyField(TIFFTAG_YRESOLUTION, floatv);
265
CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
267
rowsperstrip = imagelength-1;
269
rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
270
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
271
switch (compression) {
272
case COMPRESSION_CCITTFAX3:
273
TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, group3options);
275
case COMPRESSION_LZW:
276
case COMPRESSION_DEFLATE:
278
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
288
"usage: tiffdither [options] input.tif output.tif",
289
"where options are:",
290
" -r # make each strip have no more than # rows",
291
" -f lsb2msb force lsb-to-msb FillOrder for output",
292
" -f msb2lsb force msb-to-lsb FillOrder for output",
293
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
294
" -c zip[:opts] compress output with deflate encoding",
295
" -c packbits compress output with packbits encoding",
296
" -c g3[:opts] compress output with CCITT Group 3 encoding",
297
" -c g4 compress output with CCITT Group 4 encoding",
298
" -c none use no compression algorithm on output",
301
" 1d use default CCITT Group 3 1D-encoding",
302
" 2d use optional CCITT Group 3 2D-encoding",
303
" fill byte-align EOL codes",
304
"For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
306
"LZW and deflate options:",
307
" # set predictor value",
308
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
319
fprintf(stderr, "%s\n\n", TIFFGetVersion());
320
for (i = 0; stuff[i] != NULL; i++)
321
fprintf(stderr, "%s\n", stuff[i]);
325
/* vim: set ts=8 sts=8 sw=8 noet: */