]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/tools/tiffdither.c
08eb59df9c14c5905ac035fe43d4237bb9fe70b6
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"
43 #define streq(a,b) (strcmp(a,b) == 0)
44 #define strneq(a,b,n) (strncmp(a,b,n) == 0)
46 #define CopyField(tag, v) \
47 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
53 static void usage(void);
56 * Floyd-Steinberg error propragation with threshold.
57 * This code is stolen from tiffmedian.
60 fsdither(TIFF
* in
, TIFF
* out
)
62 unsigned char *outline
, *inputline
, *inptr
;
63 short *thisline
, *nextline
, *tmpptr
;
64 register unsigned char *outptr
;
65 register short *thisptr
, *nextptr
;
68 int lastline
, lastpixel
;
72 imax
= imagelength
- 1;
73 jmax
= imagewidth
- 1;
74 inputline
= (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in
));
75 thisline
= (short *)_TIFFmalloc(imagewidth
* sizeof (short));
76 nextline
= (short *)_TIFFmalloc(imagewidth
* sizeof (short));
77 outlinesize
= TIFFScanlineSize(out
);
78 outline
= (unsigned char *) _TIFFmalloc(outlinesize
);
83 if (TIFFReadScanline(in
, inputline
, 0, 0) <= 0)
88 for (j
= 0; j
< imagewidth
; ++j
)
89 *nextptr
++ = *inptr
++;
90 for (i
= 1; i
< imagelength
; ++i
) {
94 lastline
= (i
== imax
);
95 if (TIFFReadScanline(in
, inputline
, i
, 0) <= 0)
99 for (j
= 0; j
< imagewidth
; ++j
)
100 *nextptr
++ = *inptr
++;
103 _TIFFmemset(outptr
= outline
, 0, outlinesize
);
105 for (j
= 0; j
< imagewidth
; ++j
) {
108 lastpixel
= (j
== jmax
);
124 thisptr
[0] += v
* 7 / 16;
127 nextptr
[-1] += v
* 3 / 16;
128 *nextptr
++ += v
* 5 / 16;
130 nextptr
[0] += v
/ 16;
133 if (TIFFWriteScanline(out
, outline
, i
-1, 0) < 0)
137 _TIFFfree(inputline
);
143 static uint16 compression
= COMPRESSION_PACKBITS
;
144 static uint16 predictor
= 0;
145 static uint32 group3options
= 0;
148 processG3Options(char* cp
)
150 if ((cp
= strchr(cp
, ':'))) {
153 if (strneq(cp
, "1d", 2))
154 group3options
&= ~GROUP3OPT_2DENCODING
;
155 else if (strneq(cp
, "2d", 2))
156 group3options
|= GROUP3OPT_2DENCODING
;
157 else if (strneq(cp
, "fill", 4))
158 group3options
|= GROUP3OPT_FILLBITS
;
161 } while ((cp
= strchr(cp
, ':')));
166 processCompressOptions(char* opt
)
168 if (streq(opt
, "none"))
169 compression
= COMPRESSION_NONE
;
170 else if (streq(opt
, "packbits"))
171 compression
= COMPRESSION_PACKBITS
;
172 else if (strneq(opt
, "g3", 2)) {
173 processG3Options(opt
);
174 compression
= COMPRESSION_CCITTFAX3
;
175 } else if (streq(opt
, "g4"))
176 compression
= COMPRESSION_CCITTFAX4
;
177 else if (strneq(opt
, "lzw", 3)) {
178 char* cp
= strchr(opt
, ':');
180 predictor
= atoi(cp
+1);
181 compression
= COMPRESSION_LZW
;
182 } else if (strneq(opt
, "zip", 3)) {
183 char* cp
= strchr(opt
, ':');
185 predictor
= atoi(cp
+1);
186 compression
= COMPRESSION_DEFLATE
;
193 main(int argc
, char* argv
[])
196 uint16 samplesperpixel
, bitspersample
= 1, shortv
;
199 uint32 rowsperstrip
= (uint32
) -1;
200 uint16 fillorder
= 0;
205 while ((c
= getopt(argc
, argv
, "c:f:r:t:")) != -1)
207 case 'c': /* compression scheme */
208 if (!processCompressOptions(optarg
))
211 case 'f': /* fill order */
212 if (streq(optarg
, "lsb2msb"))
213 fillorder
= FILLORDER_LSB2MSB
;
214 else if (streq(optarg
, "msb2lsb"))
215 fillorder
= FILLORDER_MSB2LSB
;
219 case 'r': /* rows/strip */
220 rowsperstrip
= atoi(optarg
);
223 threshold
= atoi(optarg
);
226 else if (threshold
> 255)
233 if (argc
- optind
< 2)
235 in
= TIFFOpen(argv
[optind
], "r");
238 TIFFGetField(in
, TIFFTAG_SAMPLESPERPIXEL
, &samplesperpixel
);
239 if (samplesperpixel
!= 1) {
240 fprintf(stderr
, "%s: Not a b&w image.\n", argv
[0]);
243 TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &bitspersample
);
244 if (bitspersample
!= 8) {
246 " %s: Sorry, only handle 8-bit samples.\n", argv
[0]);
249 out
= TIFFOpen(argv
[optind
+1], "w");
252 CopyField(TIFFTAG_IMAGEWIDTH
, imagewidth
);
253 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &imagelength
);
254 TIFFSetField(out
, TIFFTAG_IMAGELENGTH
, imagelength
-1);
255 TIFFSetField(out
, TIFFTAG_BITSPERSAMPLE
, 1);
256 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, 1);
257 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, PLANARCONFIG_CONTIG
);
258 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
);
260 TIFFSetField(out
, TIFFTAG_FILLORDER
, fillorder
);
262 CopyField(TIFFTAG_FILLORDER
, shortv
);
263 sprintf(thing
, "Dithered B&W version of %s", argv
[optind
]);
264 TIFFSetField(out
, TIFFTAG_IMAGEDESCRIPTION
, thing
);
265 CopyField(TIFFTAG_PHOTOMETRIC
, shortv
);
266 CopyField(TIFFTAG_ORIENTATION
, shortv
);
267 CopyField(TIFFTAG_XRESOLUTION
, floatv
);
268 CopyField(TIFFTAG_YRESOLUTION
, floatv
);
269 CopyField(TIFFTAG_RESOLUTIONUNIT
, shortv
);
270 rowsperstrip
= TIFFDefaultStripSize(out
, rowsperstrip
);
271 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip
);
272 switch (compression
) {
273 case COMPRESSION_CCITTFAX3
:
274 TIFFSetField(out
, TIFFTAG_GROUP3OPTIONS
, group3options
);
276 case COMPRESSION_LZW
:
277 case COMPRESSION_DEFLATE
:
279 TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
);
289 "usage: tiffdither [options] input.tif output.tif",
290 "where options are:",
291 " -r # make each strip have no more than # rows",
292 " -f lsb2msb force lsb-to-msb FillOrder for output",
293 " -f msb2lsb force msb-to-lsb FillOrder for output",
294 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
295 " -c zip[:opts] compress output with deflate encoding",
296 " -c packbits compress output with packbits encoding",
297 " -c g3[:opts] compress output with CCITT Group 3 encoding",
298 " -c g4 compress output with CCITT Group 4 encoding",
299 " -c none use no compression algorithm on output",
302 " 1d use default CCITT Group 3 1D-encoding",
303 " 2d use optional CCITT Group 3 2D-encoding",
304 " fill byte-align EOL codes",
305 "For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
307 "LZW and deflate options:",
308 " # set predictor value",
309 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
320 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
321 for (i
= 0; stuff
[i
] != NULL
; i
++)
322 fprintf(stderr
, "%s\n", stuff
[i
]);
326 /* vim: set ts=8 sts=8 sw=8 noet: */