New comit of SDL2
[supertux.git] / src / SDL2 / external / tiff-4.0.3 / tools / tiffdither.c
1 /* $Id: tiffdither.c,v 1.12 2010-03-10 18:56:50 bfriesen Exp $ */
2
3 /*
4  * Copyright (c) 1988-1997 Sam Leffler
5  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6  *
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.
14  * 
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.  
18  * 
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 
24  * OF THIS SOFTWARE.
25  */
26
27 #include "tif_config.h"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
36
37 #ifdef NEED_LIBPORT
38 # include "libport.h"
39 #endif
40
41 #include "tiffio.h"
42
43 #define streq(a,b)      (strcmp(a,b) == 0)
44 #define strneq(a,b,n)   (strncmp(a,b,n) == 0)
45
46 #define CopyField(tag, v) \
47         if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
48
49 uint32  imagewidth;
50 uint32  imagelength;
51 int     threshold = 128;
52
53 static  void usage(void);
54
55 /* 
56  * Floyd-Steinberg error propragation with threshold.
57  * This code is stolen from tiffmedian.
58  */
59 static void
60 fsdither(TIFF* in, TIFF* out)
61 {
62         unsigned char *outline, *inputline, *inptr;
63         short *thisline, *nextline, *tmpptr;
64         register unsigned char  *outptr;
65         register short *thisptr, *nextptr;
66         register uint32 i, j;
67         uint32 imax, jmax;
68         int lastline, lastpixel;
69         int bit;
70         tsize_t outlinesize;
71
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);
79
80         /*
81          * Get first line
82          */
83         if (TIFFReadScanline(in, inputline, 0, 0) <= 0)
84             goto skip_on_error;
85
86         inptr = inputline;
87         nextptr = nextline;
88         for (j = 0; j < imagewidth; ++j)
89                 *nextptr++ = *inptr++;
90         for (i = 1; i < imagelength; ++i) {
91                 tmpptr = thisline;
92                 thisline = nextline;
93                 nextline = tmpptr;
94                 lastline = (i == imax);
95                 if (TIFFReadScanline(in, inputline, i, 0) <= 0)
96                         break;
97                 inptr = inputline;
98                 nextptr = nextline;
99                 for (j = 0; j < imagewidth; ++j)
100                         *nextptr++ = *inptr++;
101                 thisptr = thisline;
102                 nextptr = nextline;
103                 _TIFFmemset(outptr = outline, 0, outlinesize);
104                 bit = 0x80;
105                 for (j = 0; j < imagewidth; ++j) {
106                         register int v;
107
108                         lastpixel = (j == jmax);
109                         v = *thisptr++;
110                         if (v < 0)
111                                 v = 0;
112                         else if (v > 255)
113                                 v = 255;
114                         if (v > threshold) {
115                                 *outptr |= bit;
116                                 v -= 255;
117                         }
118                         bit >>= 1;
119                         if (bit == 0) {
120                                 outptr++;
121                                 bit = 0x80;
122                         }
123                         if (!lastpixel)
124                                 thisptr[0] += v * 7 / 16;
125                         if (!lastline) {
126                                 if (j != 0)
127                                         nextptr[-1] += v * 3 / 16;
128                                 *nextptr++ += v * 5 / 16;
129                                 if (!lastpixel)
130                                         nextptr[0] += v / 16;
131                         }
132                 }
133                 if (TIFFWriteScanline(out, outline, i-1, 0) < 0)
134                         break;
135         }
136   skip_on_error:
137         _TIFFfree(inputline);
138         _TIFFfree(thisline);
139         _TIFFfree(nextline);
140         _TIFFfree(outline);
141 }
142
143 static  uint16 compression = COMPRESSION_PACKBITS;
144 static  uint16 predictor = 0;
145 static  uint32 group3options = 0;
146
147 static void
148 processG3Options(char* cp)
149 {
150         if ((cp = strchr(cp, ':'))) {
151                 do {
152                         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;
159                         else
160                                 usage();
161                 } while ((cp = strchr(cp, ':')));
162         }
163 }
164
165 static int
166 processCompressOptions(char* opt)
167 {
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, ':');
179                 if (cp)
180                         predictor = atoi(cp+1);
181                 compression = COMPRESSION_LZW;
182         } else if (strneq(opt, "zip", 3)) {
183                 char* cp = strchr(opt, ':');
184                 if (cp)
185                         predictor = atoi(cp+1);
186                 compression = COMPRESSION_DEFLATE;
187         } else
188                 return (0);
189         return (1);
190 }
191
192 int
193 main(int argc, char* argv[])
194 {
195         TIFF *in, *out;
196         uint16 samplesperpixel, bitspersample = 1, shortv;
197         float floatv;
198         char thing[1024];
199         uint32 rowsperstrip = (uint32) -1;
200         uint16 fillorder = 0;
201         int c;
202         extern int optind;
203         extern char *optarg;
204
205         while ((c = getopt(argc, argv, "c:f:r:t:")) != -1)
206                 switch (c) {
207                 case 'c':               /* compression scheme */
208                         if (!processCompressOptions(optarg))
209                                 usage();
210                         break;
211                 case 'f':               /* fill order */
212                         if (streq(optarg, "lsb2msb"))
213                                 fillorder = FILLORDER_LSB2MSB;
214                         else if (streq(optarg, "msb2lsb"))
215                                 fillorder = FILLORDER_MSB2LSB;
216                         else
217                                 usage();
218                         break;
219                 case 'r':               /* rows/strip */
220                         rowsperstrip = atoi(optarg);
221                         break;
222                 case 't':
223                         threshold = atoi(optarg);
224                         if (threshold < 0)
225                                 threshold = 0;
226                         else if (threshold > 255)
227                                 threshold = 255;
228                         break;
229                 case '?':
230                         usage();
231                         /*NOTREACHED*/
232                 }
233         if (argc - optind < 2)
234                 usage();
235         in = TIFFOpen(argv[optind], "r");
236         if (in == NULL)
237                 return (-1);
238         TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
239         if (samplesperpixel != 1) {
240                 fprintf(stderr, "%s: Not a b&w image.\n", argv[0]);
241                 return (-1);
242         }
243         TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample);
244         if (bitspersample != 8) {
245                 fprintf(stderr,
246                     " %s: Sorry, only handle 8-bit samples.\n", argv[0]);
247                 return (-1);
248         }
249         out = TIFFOpen(argv[optind+1], "w");
250         if (out == NULL)
251                 return (-1);
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);
259         if (fillorder)
260                 TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
261         else
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);
275                 break;
276         case COMPRESSION_LZW:
277         case COMPRESSION_DEFLATE:
278                 if (predictor)
279                         TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
280                 break;
281         }
282         fsdither(in, out);
283         TIFFClose(in);
284         TIFFClose(out);
285         return (0);
286 }
287
288 char* stuff[] = {
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",
300 "",
301 "Group 3 options:",
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",
306 "",
307 "LZW and deflate options:",
308 " #             set predictor value",
309 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
310 NULL
311 };
312
313 static void
314 usage(void)
315 {
316         char buf[BUFSIZ];
317         int i;
318
319         setbuf(stderr, buf);
320         fprintf(stderr, "%s\n\n", TIFFGetVersion());
321         for (i = 0; stuff[i] != NULL; i++)
322                 fprintf(stderr, "%s\n", stuff[i]);
323         exit(-1);
324 }
325
326 /* vim: set ts=8 sts=8 sw=8 noet: */
327 /*
328  * Local Variables:
329  * mode: c
330  * c-basic-offset: 8
331  * fill-column: 78
332  * End:
333  */