1 /* loadtiff.c - loads a tiff file into memory
2    Copyright (C) 1996-2017 Paul Sheer
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307, USA.
18  */
19 
20 /* this file is highly dependent on a long int being 4 bytes */
21 
22 /* NLS through this whole file ? */
23 
24 #include <config.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 
28 #include <X11/Xlib.h>
29 #include <X11/Xutil.h>
30 
31 #include <math.h>
32 
33 #include "stringtools.h"
34 #include "app_glob.c"
35 
36 #include "coolwidget.h"
37 
38 #include "mad.h"
39 
40 
41 #define TPRINTF tiffprintf
42 /*tiffprintf*/
43 
44 /* #define ABORT_ON_ERROR */
45 
46 
47 
48 short highbytefirst = 0;
49 
fgetshort(FILE * f)50 short fgetshort(FILE *f)
51 {
52 if(highbytefirst)
53     return (getc(f)<<8) + getc(f);
54 else
55     return getc(f) + (getc(f) << 8);
56 }
57 
58 
fgetlong(FILE * f)59 long fgetlong (FILE * f)
60 {
61     if (highbytefirst)
62 	return (getc (f) << 24) + (getc (f) << 16) + (getc (f) << 8) + getc (f);
63     else
64 	return getc (f) + (getc (f) << 8) + (getc (f) << 16) + (getc (f) << 24);
65 }
66 
67 /*
68 Gets an array of unsigned char at offset 'offset' from the beginning
69 of the file, of length 'length' bytes. It returns a pointer to the data
70 although the data is malloced from within the function, the function
71 checks on each call to free previous mallocs, and does so
72 if necessary. Therefore DO NOT FREE the pointer returned by this function.
73 Also copy the results before the next call to fgetstring.
74 */
75 
fgetstring(FILE * f,long offset,long length)76 unsigned char *fgetstring (FILE * f, long offset, long length)
77 {
78     static unsigned char *str = NULL;
79 
80     if (str)
81 	free (str);
82     if ((str = malloc (length + 1)) == NULL) {
83 /* Not essential to translate */
84 	printf(_("Could not allocate memory in fgetstring.\n"));
85 	abort();
86     }
87 
88     fseek (f, offset, SEEK_SET);
89     fread (str, length, 1, f);
90     str[length] = 0;
91 
92     return str;
93 }
94 
tiffprintf(const char * str,...)95 void tiffprintf(const char *str, ...)
96 {
97 
98 }
99 
100 
101 struct IFDentry {
102     short tag;
103     short fieldtype;
104     long length;
105     long valueoffset;
106     short shortvalue;		/*this is duplicate of the lower numbered
107 				   two bytes of valueoffset, for when valueoffset contains a
108 				   short value */
109 };
110 
111 
112 /*gets the value of an IFD entry. If the value is small enough
113    to fit in the valueoffset it gets it from there.
114    Handles correctly both arrays and single numbers */
getvalue(FILE * fp,struct IFDentry * entry,long * retval,long numtoget,int size)115 void getvalue (FILE * fp, struct IFDentry *entry, long *retval, long numtoget, int size)
116 {
117     int j;
118     if (size == 2 || (entry->fieldtype == 3 && size == 0)) {
119 	TPRINTF (" (short) ");
120 	if (numtoget <= 2) {
121 	    retval[0] = entry->shortvalue;
122 	    if (numtoget == 2)
123 		if (highbytefirst)
124 		    retval[1] = entry->valueoffset && 0xFFFF;
125 		else
126 		    retval[1] = entry->valueoffset >> 16;
127 	} else {
128 	    fseek (fp, entry->valueoffset, SEEK_SET);
129 	    for (j = 0; j < numtoget; j++)
130 		retval[j] = fgetshort (fp);
131 	}
132     }
133     if (size == 4 || (entry->fieldtype == 4 && size == 0)) {
134 	TPRINTF (" (long) ");
135 	if (numtoget <= 1) {
136 	    retval[0] = entry->valueoffset;
137 	} else {
138 	    fseek (fp, entry->valueoffset, SEEK_SET);
139 	    for (j = 0; j < numtoget; j++)
140 		retval[j] = fgetlong (fp);
141 	}
142     }
143 }
144 
145 
146 
147 
148 
tifferror(const char * errmessage)149 void tifferror (const char *errmessage)
150 {
151   fprintf(stderr, errmessage); /* OR for the application:  */
152 #ifdef ABORT_ON_ERROR
153 abort();
154 #endif
155 /*    CError (errmessage);  */
156 /********/
157 }
158 
159 /*
160 The return value must be free'd by the calling application
161 since the function malloc's it.
162 
163 loads an uncompressed class G tiff file. This is a greyscale file.
164 Presently, this routine only supports, topdown orientation (Orientation = 1)
165 1 sample per pixel of 8 bits. It uses the greyresponse curve and assumes the
166 monitor to have a linear response.
167 It will interprete PhotometricInterpretation of 0 or 1 (reverse or normal).
168 It can handle multiple strips of any size and reads and displays most of the
169 important fields (although it only actually interprets class G fields).
170 
171 rowstart and rowend are used to specify what part of the image to load
172 for very large files. If they go past the end of a file. The calling
173 application must check the size of the returned data by looking
174 at the height returned. To load the whole file,set rowstart = 0,
175 rowend = 2^31 - 1.
176 loadgreytiff returns contigous rows, 1 byte/pixel (0-255, black-white),
177 exclusive of rowend. Hence rowend-rowstart rows/scanlines are returned.
178 The first row/scanline is number zero, the last is numbered height - 1.
179 */
180 
181 
loadgreytiff(const char * fname,long * width,long * height,long rowstart,long rowend,float gamma)182 unsigned char *loadgreytiff (const char *fname, long *width, long *height, long rowstart, long rowend, float gamma)
183 {
184 
185     FILE *fp = NULL;
186     int i, j, c;
187     long IFDoffset;
188     struct IFDentry *theIFD = NULL;
189     short numberofIFDentries;
190     int numinterpreted;
191     long *greyresponsecurve = NULL;
192     long *stripbytecounts = NULL, *stripoffsets = NULL;
193     long numstrips;
194     float xresolution, yresolution;
195     long bitspersample[3] =
196     {8, 8, 8};
197     long index;
198     long maxgrey, mingrey;
199 
200     unsigned char *pic8 = NULL;
201     unsigned char *pp = NULL;
202 
203     int numgreylevels = 0;	/*number of entries in the grey response curve array */
204 
205 /*options: */
206     int photointerp = 1, spp = 1, comptype = 1, fillorder = 1, planarconfig = 1,
207      orient = 1;
208     long rps = 0x7FFFFFFF;
209 
210 
211     if ((fp = fopen (fname, "r")) == NULL) {
212 /* NLS ? */
213 	tifferror ("Cannot open tiff image file.\n");
214 	goto freeall;
215     }
216 
217     if ((c = fgetshort (fp)) != 'I' + 256 * 'I')
218 	highbytefirst = 1;
219     TPRINTF ("00; %c%c\n", (unsigned char) c, (unsigned char) c);
220     if ((c = fgetshort (fp)) != 42) {
221 	tifferror ("Not a recognised (meaning of life) tiff file.\n");
222 	goto freeall;
223     }
224     TPRINTF ("02; %d\n", c);
225     IFDoffset = fgetlong (fp);
226     if (IFDoffset < 8) {
227 	tifferror ("Not a recognised tiff file.\n");
228 	goto freeall;
229     }
230     TPRINTF ("04; %ld\n", IFDoffset);
231 
232     if (fseek (fp, IFDoffset, SEEK_SET)) {
233 	tifferror ("Tiff IFD passed end of file.\n");
234 	goto freeall;
235     }
236 /*now read the Image File Directory (IFD) */
237 
238     numberofIFDentries = fgetshort (fp);
239     TPRINTF ("\nNumber IFD entries = %d\n", numberofIFDentries);
240 
241     if ((theIFD = malloc (numberofIFDentries * sizeof (struct IFDentry))) == NULL) {
242 	tifferror ("Cannot allocate memory for tiff file.\n");
243 	goto freeall;
244     }
245     for (i = 0; i < numberofIFDentries; i++) {
246 /*TPRINTF's are for debug */
247 /*      TPRINTF ("\n"); */
248 	theIFD[i].tag = fgetshort (fp);
249 /*      TPRINTF ("IFD %ld;%d\n", IFDoffset + 0 + 12 * i, theIFD[i].tag); */
250 	theIFD[i].fieldtype = fgetshort (fp);
251 /*      TPRINTF ("IFD %ld;%d\n", IFDoffset + 2 + 12 * i, theIFD[i].fieldtype); */
252 	theIFD[i].length = fgetlong (fp);
253 /*      TPRINTF ("IFD %ld;%ld\n", IFDoffset + 4 + 12 * i, theIFD[i].length); */
254 	theIFD[i].valueoffset = fgetlong (fp);
255 /*      TPRINTF ("IFD %ld;%ld\n", IFDoffset + 8 + 12 * i, theIFD[i].valueoffset); */
256 	if (!highbytefirst)
257 	    theIFD[i].shortvalue = (long) theIFD[i].valueoffset & 0xFFFF;
258 	else
259 	    theIFD[i].shortvalue = (long) theIFD[i].valueoffset >> 16;
260     }
261 
262 
263 /*now loop through the IFD and check tags */
264 
265     TPRINTF ("\n");
266 
267     numinterpreted = numberofIFDentries;
268 
269     for (i = 0; i < numberofIFDentries; i++) {
270 	switch (theIFD[i].tag) {
271 	case 254:
272 	    TPRINTF ("NewSubfileType = %ld\n", theIFD[i].valueoffset);
273 	    break;
274 	case 256:
275 	    getvalue (fp, theIFD + i, width, 1, 0);
276 	    TPRINTF ("Image width = %ld\n", *width);
277 	    break;
278 	case 257:
279 	    getvalue (fp, theIFD + i, height, 1, 0);
280 	    TPRINTF ("Image length = %ld\n", *height);
281 	    break;
282 	case 258:
283 	    getvalue (fp, theIFD + i, bitspersample, theIFD[i].length, 2);
284 	    TPRINTF ("BitsPerSample\n");
285 	    for (j = 0; j < theIFD[i].length; j++)
286 		TPRINTF ("%ld ", bitspersample[j]);
287 	    TPRINTF ("\n");
288 	    break;
289 	case 259:
290 	    TPRINTF ("Compressing is type %d\n", theIFD[i].shortvalue);
291 	    comptype = theIFD[i].shortvalue;
292 	    break;
293 	case 262:
294 	    TPRINTF ("Photometric interpretation = %d\n", (int) theIFD[i].shortvalue);
295 	    photointerp = theIFD[i].shortvalue;
296 	    break;
297 	case 266:
298 	    TPRINTF ("Fillorder = %d\n", theIFD[i].shortvalue);
299 	    fillorder = theIFD[i].shortvalue;
300 	    break;
301 	case 269:
302 	    TPRINTF ("DocumentName: %s\n", fgetstring (fp, theIFD[i].valueoffset, theIFD[i].length));
303 	    break;
304 	case 270:
305 	    TPRINTF ("ImageDescription: %s\n", fgetstring (fp, theIFD[i].valueoffset, theIFD[i].length));
306 	    break;
307 	case 271:
308 	    TPRINTF ("Make: %s\n", fgetstring (fp, theIFD[i].valueoffset, theIFD[i].length));
309 	    break;
310 	case 272:
311 	    TPRINTF ("Model: %s\n", fgetstring (fp, theIFD[i].valueoffset, theIFD[i].length));
312 	    break;
313 	case 273:
314 	    numstrips = theIFD[i].length;
315 
316 	    if ((stripoffsets = malloc (numstrips * sizeof (long))) == NULL) {
317 		tifferror ("Cannot allocate memory for tiff file.\n");
318 		goto freeall;
319 	    }
320 	    getvalue (fp, theIFD + i, stripoffsets, numstrips, 0);
321 	    TPRINTF ("StripOffsets: %ld\n", numstrips);
322 	    for (j = 0; j < numstrips; j++)
323 		TPRINTF ("%ld ", stripoffsets[j]);
324 	    TPRINTF ("\n");
325 	    break;
326 	case 274:
327 	    TPRINTF ("Orientation = %d\n", theIFD[i].shortvalue);
328 	    orient = theIFD[i].shortvalue;
329 	    break;
330 	case 277:
331 	    TPRINTF ("SamplesPerPixel = %d\n", theIFD[i].shortvalue);
332 	    spp = theIFD[i].shortvalue;
333 	    break;
334 	case 278:
335 	    getvalue (fp, theIFD + i, &rps, 1, 0);
336 	    TPRINTF ("RowsPerStrip = %ld\n", rps);
337 	    break;
338 	case 279:
339 	    numstrips = theIFD[i].length;
340 	    if ((stripbytecounts = malloc (numstrips * sizeof (long))) == NULL) {
341 		tifferror ("Cannot allocate memory for tiff file.\n");
342 		goto freeall;
343 	    }
344 	    getvalue (fp, theIFD + i, stripbytecounts, numstrips, 0);
345 	    TPRINTF ("StripByteCounts: %ld\n", numstrips);
346 	    for (j = 0; j < numstrips; j++)
347 		TPRINTF ("%ld ", stripbytecounts[j]);
348 	    TPRINTF ("\n");
349 	    break;
350 	case 282:
351 	    TPRINTF ("Xresolution at %ld\n", theIFD[i].valueoffset);
352 	    fseek (fp, theIFD[i].valueoffset, SEEK_SET);
353 	    xresolution = (float) fgetlong (fp) / fgetlong (fp);
354 	    TPRINTF ("  %f\n", xresolution);
355 	    break;
356 	case 283:
357 	    TPRINTF ("Yresolution at %ld\n", theIFD[i].valueoffset);
358 	    fseek (fp, theIFD[i].valueoffset, SEEK_SET);
359 	    yresolution = (float) fgetlong (fp) / fgetlong (fp);
360 	    TPRINTF ("  %f\n", yresolution);
361 	    break;
362 	case 284:
363 	    TPRINTF ("PlanarConfiguration = %d\n", theIFD[i].shortvalue);
364 	    planarconfig = theIFD[i].shortvalue;
365 	    break;
366 	case 285:
367 	    TPRINTF ("PageName: %s\n", fgetstring (fp, theIFD[i].valueoffset, theIFD[i].length));
368 	    break;
369 	case 290:
370 	    TPRINTF ("GrayResponseUnit = %d\n", theIFD[i].shortvalue);
371 	    break;
372 	case 291:
373 	    TPRINTF ("GrayResponseCurve at %ld, length %ld\n", theIFD[i].valueoffset, theIFD[i].length);
374 	    numgreylevels = theIFD[i].length;
375 
376 	    if ((greyresponsecurve = malloc (numgreylevels * sizeof (long))) == NULL) {
377 abort();
378 		tifferror ("Cannot allocate memory for tiff file.\n");
379 		goto freeall;
380 	    }
381 	    getvalue (fp, theIFD + i, greyresponsecurve, numgreylevels, 2);
382 	    for (j = 0; j < numgreylevels; j++)
383 		TPRINTF ("%ld ", greyresponsecurve[j]);
384 	    TPRINTF ("\n");
385 	    break;
386 	case 296:
387 	    TPRINTF ("ResolutionUnit = %d\n", theIFD[i].shortvalue);
388 	    break;
389 	case 301:
390 	    TPRINTF ("Color response curve present at %ld, length %ld\n", theIFD[i].valueoffset, theIFD[i].length);
391 	    break;
392 	case 320:
393 	    TPRINTF ("Colormap present at %ld\n", theIFD[i].valueoffset);
394 	    break;
395 	default:
396 	    TPRINTF ("Tag %d unread.\n", theIFD[i].tag);
397 	    numinterpreted--;
398 	}
399     }
400 
401     TPRINTF ("Number of fields interpreted = %d\n\n", numinterpreted);
402 
403 /*now that we've read most of what we might want to know, we can't
404    scratch all images that are too tedious to interpret. What we
405    are looking for is a class G greyscale with no compression */
406 
407     if (spp != 1 || bitspersample[0] != 8 || comptype != 1 || fillorder != 1
408 	|| orient != 1) {
409 	tifferror ("This kind of tiff file is not supported.\n");
410 	goto freeall;
411     }
412 
413 /*printf("rowstart = %ld, rowend = %ld.\n", rowstart, rowend);
414 */
415 
416 /*check that rowstart and rowend are ok*/
417 
418     if(rowstart > rowend) {
419 	tifferror("Tiff called with rowstart > rowend.\n");
420 	goto freeall;
421     }
422 
423     if(rowstart > *height) rowstart = *height;
424 
425     if(rowstart < 0) rowstart = 0;
426 
427     if(rowend > *height) rowend = *height;
428 
429 /*printf("width = %ld\n", *width);
430 printf("changeto rowstart = %ld, rowend = %ld.\n", rowstart, rowend);
431 */
432 
433     if ((  pic8 = malloc ((rowend-rowstart) * *width + 1)  ) == NULL) {
434 	tifferror ("Cannot allocate memory for tiff file.\n");
435 	goto freeall;
436     }
437 
438     index = 0;
439     if(gamma == 0) gamma = 1.5;
440 
441     maxgrey = 0; mingrey = 1 << 30;
442     if(numgreylevels) {
443 	for(i=0;i<numgreylevels;i++) {
444 	    maxgrey = max(maxgrey, greyresponsecurve[i]);
445 	    mingrey = min(mingrey, greyresponsecurve[i]);
446 	}
447 	for(i=0;i<numgreylevels;i++)
448 	    greyresponsecurve[i] = (double) 255 * pow((double) 1 - (double) ((double) greyresponsecurve[i] - mingrey) / (maxgrey - mingrey), (double) 1 / gamma);
449     }
450 
451     if(rowend > rowstart)
452     for(i=rowstart;i<rowend;i++) {
453 		/*:loop through all rows*/
454 
455 	pp = fgetstring (fp, stripoffsets[i/rps] + (i%rps) * *width, *width);
456 		/*:load the row*/
457 
458 /*OR  pp = fdecodeLZW (fp, stripoffsets[i/rps] + (i%rps) * *width, *width); <-- for later*/
459 
460 	if(numgreylevels) {
461 	    for(j=0;j<*width;j++)
462 		pic8[index++] = greyresponsecurve[pp[j]];
463 	} else {
464 	    if(photointerp == 1)
465 		for(j=0;j<*width;j++)
466 		    pic8[index++] = pp[j];
467 	    else
468 		for(j=0;j<*width;j++)
469 		    pic8[index++] = 255 - pp[j];
470 	}
471     if(index > (rowend-rowstart) * *width) {
472 printf("Index past end of array\n\n");
473 abort();
474 }
475     }
476 
477   freeall:
478 
479 
480     if (greyresponsecurve)
481 	free (greyresponsecurve);
482     if (stripbytecounts)
483 	free (stripbytecounts);
484     if (stripoffsets)
485 	free (stripoffsets);
486     if (theIFD)
487 	free (theIFD);
488 
489     if(fp) fclose(fp);
490 
491     return pic8;
492 }
493 
494 
495