New comit of SDL2
[supertux.git] / src / SDL2 / external / tiff-4.0.3 / tools / tiffgt.c
1 /* $Id: tiffgt.c,v 1.10 2010-07-01 15:56:56 dron Exp $ */
2
3 /*
4  * Copyright (c) 1988-1997 Sam Leffler
5  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6  * Copyright (c) 2003, Andrey Kiselev <dron@ak4719.spb.edu>
7  *
8  * Permission to use, copy, modify, distribute, and sell this software and 
9  * its documentation for any purpose is hereby granted without fee, provided
10  * that (i) the above copyright notices and this permission notice appear in
11  * all copies of the software and related documentation, and (ii) the names of
12  * Sam Leffler and Silicon Graphics may not be used in any advertising or
13  * publicity relating to the software without the specific, prior written
14  * permission of Sam Leffler and Silicon Graphics.
15  * 
16  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
17  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
18  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
19  * 
20  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
21  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
22  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
24  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
25  * OF THIS SOFTWARE.
26  */
27
28 #include "tif_config.h"
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #if HAVE_APPLE_OPENGL_FRAMEWORK
35 # include <OpenGL/gl.h>
36 # include <GLUT/glut.h>
37 #else
38 # include <GL/gl.h>
39 # include <GL/glut.h>
40 #endif
41
42 #include "tiffio.h"
43 #include "tiffiop.h"
44
45 #ifndef HAVE_GETOPT
46 extern int getopt(int, char**, char*);
47 #endif
48
49 static  uint32  width = 0, height = 0;          /* window width & height */
50 static  uint32* raster = NULL;                  /* displayable image */
51 static TIFFRGBAImage img;
52 static int      order0 = 0, order;
53 static uint16   photo0 = (uint16) -1, photo;
54 static int      stoponerr = 0;                  /* stop on read error */
55 static int      verbose = 0;
56 #define TITLE_LENGTH    1024
57 static char     title[TITLE_LENGTH];            /* window title line */
58 static uint32   xmax, ymax;
59 static char**   filelist = NULL;
60 static int      fileindex;
61 static int      filenum;
62 static TIFFErrorHandler oerror;
63 static TIFFErrorHandler owarning;
64
65 static void     cleanup_and_exit(void);
66 static int      initImage(void);
67 static int      prevImage(void);
68 static int      nextImage(void);
69 static void     setWindowSize(void);
70 static void     usage(void);
71 static uint16   photoArg(const char*);
72 static void     raster_draw(void);
73 static void     raster_reshape(int, int);
74 static void     raster_keys(unsigned char, int, int);
75 static void     raster_special(int, int, int);
76
77 extern  char* optarg;
78 extern  int optind;
79 static TIFF* tif = NULL;
80
81 int
82 main(int argc, char* argv[])
83 {
84         int c;
85         int dirnum = -1;
86         uint32 diroff = 0;
87
88         oerror = TIFFSetErrorHandler(NULL);
89         owarning = TIFFSetWarningHandler(NULL);
90         while ((c = getopt(argc, argv, "d:o:p:eflmsvw?")) != -1)
91             switch (c) {
92             case 'd':
93                 dirnum = atoi(optarg);
94                 break;
95             case 'e':
96                 oerror = TIFFSetErrorHandler(oerror);
97                 break;
98             case 'l':
99                 order0 = FILLORDER_LSB2MSB;
100                 break;
101             case 'm':
102                 order0 = FILLORDER_MSB2LSB;
103                 break;
104             case 'o':
105                 diroff = strtoul(optarg, NULL, 0);
106                 break;
107             case 'p':
108                 photo0 = photoArg(optarg);
109                 break;
110             case 's':
111                 stoponerr = 1;
112                 break;
113             case 'w':
114                 owarning = TIFFSetWarningHandler(owarning);
115                 break;
116             case 'v':
117                 verbose = 1;
118                 break;
119             case '?':
120                 usage();
121                 /*NOTREACHED*/
122             }
123         filenum = argc - optind;
124         if ( filenum < 1)
125                 usage();
126
127         glutInit(&argc, argv);
128         glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
129
130         /*
131          * Get the screen size
132          */
133         xmax = glutGet(GLUT_SCREEN_WIDTH);
134         ymax = glutGet(GLUT_SCREEN_HEIGHT);
135
136         /*
137          * Use 90% of the screen size
138          */
139         xmax = xmax - xmax / 10.0;
140         ymax = ymax - ymax / 10.0;
141
142         filelist = (char **) _TIFFmalloc(filenum * sizeof(char*));
143         if (!filelist) {
144                 TIFFError(argv[0], "Can not allocate space for the file list.");
145                 return 1;
146         }
147         _TIFFmemcpy(filelist, argv + optind, filenum * sizeof(char*));
148         fileindex = -1;
149         if (nextImage() < 0) {
150                 _TIFFfree(filelist);
151                 return 2;
152         }
153         /*
154          * Set initial directory if user-specified
155          * file was opened successfully.
156          */
157         if (dirnum != -1 && !TIFFSetDirectory(tif, dirnum))
158             TIFFError(argv[0], "Error, seeking to directory %d", dirnum);
159         if (diroff != 0 && !TIFFSetSubDirectory(tif, diroff))
160             TIFFError(argv[0], "Error, setting subdirectory at %#x", diroff);
161         order = order0;
162         photo = photo0;
163         if (initImage() < 0){
164                 _TIFFfree(filelist);
165                 return 3;
166         }
167         /*
168          * Create a new window or reconfigure an existing
169          * one to suit the image to be displayed.
170          */
171         glutInitWindowSize(width, height);
172         snprintf(title, TITLE_LENGTH - 1, "%s [%u]", filelist[fileindex],
173                 (unsigned int) TIFFCurrentDirectory(tif));
174         glutCreateWindow(title);
175         glutDisplayFunc(raster_draw);
176         glutReshapeFunc(raster_reshape);
177         glutKeyboardFunc(raster_keys);
178         glutSpecialFunc(raster_special);
179         glutMainLoop();
180
181         cleanup_and_exit();
182         return 0;
183 }
184
185 static void 
186 cleanup_and_exit(void)
187 {
188         TIFFRGBAImageEnd(&img);
189         if (filelist != NULL)
190                 _TIFFfree(filelist);
191         if (raster != NULL)
192                 _TIFFfree(raster);
193         if (tif != NULL)
194                 TIFFClose(tif);
195         exit(0);
196 }
197
198 static int
199 initImage(void)
200 {
201         uint32 w, h;
202
203         if (order)
204                 TIFFSetField(tif, TIFFTAG_FILLORDER, order);
205         if (photo != (uint16) -1)
206                 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photo);
207         if (!TIFFRGBAImageBegin(&img, tif, stoponerr, title)) {
208                 TIFFError(filelist[fileindex], "%s", title);
209                 TIFFClose(tif);
210                 tif = NULL;
211                 return -1;
212         }
213
214         /*
215          * Setup the image raster as required.
216          */
217         h = img.height;
218         w = img.width;
219         if (h > ymax) {
220                 w = (int)(w * ((float)ymax / h));
221                 h = ymax;
222         }
223         if (w > xmax) {
224                 h = (int)(h * ((float)xmax / w));
225                 w = xmax;
226         }
227
228         if (w != width || h != height) {
229                 uint32 rastersize =
230                         _TIFFMultiply32(tif, img.width, img.height, "allocating raster buffer");
231                 if (raster != NULL)
232                         _TIFFfree(raster), raster = NULL;
233                 raster = (uint32*) _TIFFCheckMalloc(tif, rastersize, sizeof (uint32),
234                                                     "allocating raster buffer");
235                 if (raster == NULL) {
236                         width = height = 0;
237                         TIFFError(filelist[fileindex], "No space for raster buffer");
238                         cleanup_and_exit();
239                 }
240                 width = w;
241                 height = h;
242         }
243         TIFFRGBAImageGet(&img, raster, img.width, img.height);
244 #if HOST_BIGENDIAN
245         TIFFSwabArrayOfLong(raster,img.width*img.height);
246 #endif
247         return 0;
248 }
249
250 static int
251 prevImage(void)
252 {
253         if (fileindex > 0)
254                 fileindex--;
255         else if (tif)
256                 return fileindex;
257         if (tif)
258                 TIFFClose(tif);
259         tif = TIFFOpen(filelist[fileindex], "r");
260         if (tif == NULL)
261                 return -1;
262         return fileindex;
263 }
264
265 static int
266 nextImage(void)
267 {
268         if (fileindex < filenum - 1)
269                 fileindex++;
270         else if (tif)
271                 return fileindex;
272         if (tif)
273                 TIFFClose(tif);
274         tif = TIFFOpen(filelist[fileindex], "r");
275         if (tif == NULL)
276                 return -1;
277         return fileindex;
278 }
279
280 static void
281 setWindowSize(void)
282 {
283         glutReshapeWindow(width, height);
284 }
285
286 static void
287 raster_draw(void)
288 {
289   glDrawPixels(img.width, img.height, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid *) raster);
290 }
291
292 static void
293 raster_reshape(int win_w, int win_h)
294 {
295         GLfloat xratio = (GLfloat)win_w/img.width;
296         GLfloat yratio = (GLfloat)win_h/img.height;
297         int     ratio = (int)(((xratio > yratio)?xratio:yratio) * 100);
298
299         glPixelZoom(xratio, yratio);
300         glViewport(0, 0, win_w, win_h);
301         snprintf(title, 1024, "%s [%u] %d%%", filelist[fileindex],
302                 (unsigned int) TIFFCurrentDirectory(tif), ratio);
303         glutSetWindowTitle(title);
304 }
305
306 static void
307 raster_keys(unsigned char key, int x, int y)
308 {
309         switch (key) {
310                 case 'b':                       /* photometric MinIsBlack */
311                     photo = PHOTOMETRIC_MINISBLACK;
312                     initImage();
313                     break;
314                 case 'l':                       /* lsb-to-msb FillOrder */
315                     order = FILLORDER_LSB2MSB;
316                     initImage();
317                     break;
318                 case 'm':                       /* msb-to-lsb FillOrder */
319                     order = FILLORDER_MSB2LSB;
320                     initImage();
321                     break;
322                 case 'w':                       /* photometric MinIsWhite */
323                     photo = PHOTOMETRIC_MINISWHITE;
324                     initImage();
325                     break;
326                 case 'W':                       /* toggle warnings */
327                     owarning = TIFFSetWarningHandler(owarning);
328                     initImage();
329                     break;
330                 case 'E':                       /* toggle errors */
331                     oerror = TIFFSetErrorHandler(oerror);
332                     initImage();
333                     break;
334                 case 'z':                       /* reset to defaults */
335                 case 'Z':
336                     order = order0;
337                     photo = photo0;
338                     if (owarning == NULL)
339                         owarning = TIFFSetWarningHandler(NULL);
340                     if (oerror == NULL)
341                         oerror = TIFFSetErrorHandler(NULL);
342                     initImage();
343                     break;
344                 case 'q':                       /* exit */
345                 case '\033':
346                     cleanup_and_exit();
347         }
348         glutPostRedisplay();
349 }
350
351 static void
352 raster_special(int key, int x, int y)
353 {
354         switch (key) {
355                 case GLUT_KEY_PAGE_UP:          /* previous logical image */
356                     if (TIFFCurrentDirectory(tif) > 0) {
357                             if (TIFFSetDirectory(tif,
358                                                  TIFFCurrentDirectory(tif)-1)) {
359                                     initImage();
360                                     setWindowSize();
361                         }
362                     } else {
363                             TIFFRGBAImageEnd(&img);
364                             prevImage();
365                             initImage();
366                             setWindowSize();
367                     }
368                 break;
369                 case GLUT_KEY_PAGE_DOWN:        /* next logical image */
370                     if (!TIFFLastDirectory(tif)) {
371                             if (TIFFReadDirectory(tif)) {
372                                     initImage();
373                                     setWindowSize();
374                             }
375                     } else {
376                             TIFFRGBAImageEnd(&img);
377                             nextImage();
378                             initImage();
379                             setWindowSize();
380                     }
381                 break;
382                 case GLUT_KEY_HOME:             /* 1st image in current file */
383                         if (TIFFSetDirectory(tif, 0)) {
384                                 TIFFRGBAImageEnd(&img);
385                                 initImage();
386                                 setWindowSize();
387                         }
388                 break;
389                 case GLUT_KEY_END:              /* last image in current file */
390                         TIFFRGBAImageEnd(&img);
391                         while (!TIFFLastDirectory(tif))
392                                 TIFFReadDirectory(tif);
393                         initImage();
394                         setWindowSize();
395                 break;
396         }
397         glutPostRedisplay();
398 }
399
400
401
402 char* stuff[] = {
403 "usage: tiffgt [options] file.tif",
404 "where options are:",
405 " -c            use colormap visual",
406 " -d dirnum     set initial directory (default is 0)",
407 " -e            enable display of TIFF error messages",
408 " -l            force lsb-to-msb FillOrder",
409 " -m            force msb-to-lsb FillOrder",
410 " -o offset     set initial directory offset",
411 " -p photo      override photometric interpretation",
412 " -r            use fullcolor visual",
413 " -s            stop decoding on first error (default is ignore errors)",
414 " -v            enable verbose mode",
415 " -w            enable display of TIFF warning messages",
416 NULL
417 };
418
419 static void
420 usage(void)
421 {
422         char buf[BUFSIZ];
423         int i;
424
425         setbuf(stderr, buf);
426                 fprintf(stderr, "%s\n\n", TIFFGetVersion());
427         for (i = 0; stuff[i] != NULL; i++)
428                 fprintf(stderr, "%s\n", stuff[i]);
429         exit(-1);
430 }
431
432 static uint16
433 photoArg(const char* arg)
434 {
435         if (strcmp(arg, "miniswhite") == 0)
436             return (PHOTOMETRIC_MINISWHITE);
437         else if (strcmp(arg, "minisblack") == 0)
438             return (PHOTOMETRIC_MINISBLACK);
439         else if (strcmp(arg, "rgb") == 0)
440             return (PHOTOMETRIC_RGB);
441         else if (strcmp(arg, "palette") == 0)
442             return (PHOTOMETRIC_PALETTE);
443         else if (strcmp(arg, "mask") == 0)
444             return (PHOTOMETRIC_MASK);
445         else if (strcmp(arg, "separated") == 0)
446             return (PHOTOMETRIC_SEPARATED);
447         else if (strcmp(arg, "ycbcr") == 0)
448             return (PHOTOMETRIC_YCBCR);
449         else if (strcmp(arg, "cielab") == 0)
450             return (PHOTOMETRIC_CIELAB);
451         else if (strcmp(arg, "logl") == 0)
452             return (PHOTOMETRIC_LOGL);
453         else if (strcmp(arg, "logluv") == 0)
454             return (PHOTOMETRIC_LOGLUV);
455         else
456             return ((uint16) -1);
457 }
458
459 /* vim: set ts=8 sts=8 sw=8 noet: */
460 /*
461  * Local Variables:
462  * mode: c
463  * c-basic-offset: 8
464  * fill-column: 78
465  * End:
466  */