1 /* Create SANE/tiff headers TIFF interfacing routines for SANE
2    Copyright (C) 2000 Peter Kirchgessner
3    Copyright (C) 2002 Oliver Rauch: added tiff ICC profile
4    Copyright (C) 2017 Aaron Muir Hamilton <aaron@correspondwith.me>
5 
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <https://www.gnu.org/licenses/>.
18 */
19 
20 /* Changes:
21    2000-11-19, PK: Color TIFF-header: write 3 values for bits per sample
22    2001-12-16, PK: Write fill order tag for b/w-images
23    2002-08-27, OR: Added tiff tag for ICC profile
24    2017-04-16, AMH: Separate ICC profile loading into a separate file
25 */
26 #ifdef _AIX
27 # include "../include/lalloca.h"	/* MUST come first for AIX! */
28 #endif
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 
33 #include "../include/sane/config.h"
34 #include "../include/sane/sane.h"
35 
36 #include "sicc.h"
37 #include "stiff.h"
38 
39 typedef struct {
40     int tag, typ, nvals, val;
41 } IFD_ENTRY;
42 
43 
44 typedef struct {
45     int maxtags;
46     int ntags;
47     IFD_ENTRY *ifde;
48 } IFD;
49 
50 #define IFDE_TYP_BYTE     (1)
51 #define IFDE_TYP_ASCII    (2)
52 #define IFDE_TYP_SHORT    (3)
53 #define IFDE_TYP_LONG     (4)
54 #define IFDE_TYP_RATIONAL (5)
55 
56 static IFD *
create_ifd(void)57 create_ifd (void)
58 
59 {   IFD *ifd;
60     int maxtags = 10;
61 
62     ifd = (IFD *)malloc (sizeof (IFD));
63     if (ifd == NULL) return NULL;
64 
65     ifd->ifde = (IFD_ENTRY *)malloc (maxtags * sizeof (IFD_ENTRY));
66     if (ifd->ifde == NULL)
67     {
68         free (ifd);
69         return NULL;
70     }
71     ifd->ntags = 0;
72     ifd->maxtags = maxtags;
73 
74     return ifd;
75 }
76 
77 static void
free_ifd(IFD *ifd)78 free_ifd (IFD *ifd)
79 
80 {
81     if (ifd == NULL) return;
82     if (ifd->ifde != NULL)
83     {
84         free (ifd->ifde);
85         ifd->ifde = NULL;
86     }
87     free (ifd);
88     ifd = NULL;
89 }
90 
91 static void
add_ifd_entry(IFD *ifd, int tag, int typ, int nvals, int val)92 add_ifd_entry (IFD *ifd, int tag, int typ, int nvals, int val)
93 
94 {   IFD_ENTRY *ifde;
95     int add_entries = 10;
96 
97     if (ifd == NULL) return;
98     if (ifd->ntags == ifd->maxtags)
99     {
100         ifde = (IFD_ENTRY *)realloc (ifd->ifde,
101                                      (ifd->maxtags+add_entries)*sizeof (IFD_ENTRY));
102         if (ifde == NULL) return;
103         ifd->ifde = ifde;
104         ifd->maxtags += add_entries;
105     }
106     ifde = &(ifd->ifde[ifd->ntags]);
107     ifde->tag = tag;
108     ifde->typ = typ;
109     ifde->nvals = nvals;
110     ifde->val = val;
111     (ifd->ntags)++;
112 }
113 
114 static void
write_i2(FILE *fptr, int val, int motorola)115 write_i2 (FILE *fptr, int val, int motorola)
116 {
117     if (motorola)
118     {
119         putc ((val >> 8) & 0xff, fptr);
120         putc (val & 0xff, fptr);
121     }
122     else
123     {
124         putc (val & 0xff, fptr);
125         putc ((val >> 8) & 0xff, fptr);
126     }
127 }
128 
129 
130 static void
write_i4(FILE *fptr, int val, int motorola)131 write_i4 (FILE *fptr, int val, int motorola)
132 {
133     if (motorola)
134     {
135         putc ((val >> 24) & 0xff, fptr);
136         putc ((val >> 16) & 0xff, fptr);
137         putc ((val >> 8) & 0xff, fptr);
138         putc (val & 0xff, fptr);
139     }
140     else
141     {
142         putc (val & 0xff, fptr);
143         putc ((val >> 8) & 0xff, fptr);
144         putc ((val >> 16) & 0xff, fptr);
145         putc ((val >> 24) & 0xff, fptr);
146     }
147 }
148 
149 static void
write_ifd(FILE *fptr, IFD *ifd, int motorola)150 write_ifd (FILE *fptr, IFD *ifd, int motorola)
151 {int k;
152     IFD_ENTRY *ifde;
153 
154     if (!ifd) return;
155 
156     if (motorola) putc ('M', fptr), putc ('M', fptr);
157     else putc ('I', fptr), putc ('I', fptr);
158 
159     write_i2 (fptr, 42, motorola);  /* Magic */
160     write_i4 (fptr, 8, motorola);   /* Offset to first IFD */
161     write_i2 (fptr, ifd->ntags, motorola);
162 
163     for (k = 0; k < ifd->ntags; k++)
164     {
165         ifde = &(ifd->ifde[k]);
166         write_i2 (fptr, ifde->tag, motorola);
167         write_i2 (fptr, ifde->typ, motorola);
168         write_i4 (fptr, ifde->nvals, motorola);
169         if ((ifde->typ == IFDE_TYP_SHORT) && (ifde->nvals == 1))
170         {
171             write_i2 (fptr, ifde->val, motorola);
172             write_i2 (fptr, 0, motorola);
173         }
174         else
175         {
176             write_i4 (fptr, ifde->val, motorola);
177         }
178     }
179     write_i4 (fptr, 0, motorola); /* End of IFD chain */
180 }
181 
182 
183 static void
write_tiff_bw_header(FILE *fptr, int width, int height, int resolution)184 write_tiff_bw_header (FILE *fptr, int width, int height, int resolution)
185 {IFD *ifd;
186     int header_size = 8, ifd_size;
187     int strip_offset, data_offset, data_size;
188     int strip_bytecount;
189     int ntags;
190     int motorola;
191 
192     ifd = create_ifd ();
193 
194     strip_bytecount = ((width+7)/8) * height;
195 
196     /* the following values must be known in advance */
197     ntags = 12;
198     data_size = 0;
199     if (resolution > 0)
200     {
201         ntags += 3;
202         data_size += 2*4 + 2*4;
203     }
204 
205     ifd_size = 2 + ntags*12 + 4;
206     data_offset = header_size + ifd_size;
207     strip_offset = data_offset + data_size;
208 
209     /* New subfile type */
210     add_ifd_entry (ifd, 254, IFDE_TYP_LONG, 1, 0);
211     /* image width */
212     add_ifd_entry (ifd, 256, (width > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT,
213                    1, width);
214     /* image length */
215     add_ifd_entry (ifd, 257, (height > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT,
216                    1, height);
217     /* bits per sample */
218     add_ifd_entry (ifd, 258, IFDE_TYP_SHORT, 1, 1);
219     /* compression (uncompressed) */
220     add_ifd_entry (ifd, 259, IFDE_TYP_SHORT, 1, 1);
221     /* photometric interpretation */
222     add_ifd_entry (ifd, 262, IFDE_TYP_SHORT, 1, 0);
223     /* fill order */
224     add_ifd_entry (ifd, 266, IFDE_TYP_SHORT, 1, 1);
225     /* strip offset */
226     add_ifd_entry (ifd, 273, IFDE_TYP_LONG, 1, strip_offset);
227     /* orientation */
228     add_ifd_entry (ifd, 274, IFDE_TYP_SHORT, 1, 1);
229     /* samples per pixel */
230     add_ifd_entry (ifd, 277, IFDE_TYP_SHORT, 1, 1);
231     /* rows per strip */
232     add_ifd_entry (ifd, 278, IFDE_TYP_LONG, 1, height);
233     /* strip bytecount */
234     add_ifd_entry (ifd, 279, IFDE_TYP_LONG, 1, strip_bytecount);
235     if (resolution > 0)
236     {
237         /* x resolution */
238         add_ifd_entry (ifd, 282, IFDE_TYP_RATIONAL, 1, data_offset);
239         data_offset += 2*4;
240         /* y resolution */
241         add_ifd_entry (ifd, 283, IFDE_TYP_RATIONAL, 1, data_offset);
242         data_offset += 2*4;
243     }
244     if (resolution > 0)
245     {
246         /* resolution unit (dpi) */
247         add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2);
248     }
249 
250     /* I prefer motorola format. Its human readable. */
251     motorola = 1;
252     write_ifd (fptr, ifd, motorola);
253 
254     /* Write x/y resolution */
255     if (resolution > 0)
256     {
257         write_i4 (fptr, resolution, motorola);
258         write_i4 (fptr, 1, motorola);
259         write_i4 (fptr, resolution, motorola);
260         write_i4 (fptr, 1, motorola);
261     }
262 
263     free_ifd (ifd);
264 }
265 
266 static void
write_tiff_grey_header(FILE *fptr, int width, int height, int depth, int resolution, const char *icc_profile)267 write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
268                         int resolution, const char *icc_profile)
269 {IFD *ifd;
270     int header_size = 8, ifd_size;
271     int strip_offset, data_offset, data_size;
272     int strip_bytecount;
273     int ntags;
274     int motorola, bps, maxsamplevalue;
275     void *icc_buffer = NULL;
276     size_t icc_size = 0;
277 
278     if (icc_profile)
279     {
280       icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
281     }
282 
283     ifd = create_ifd ();
284 
285     bps = (depth <= 8) ? 1 : 2;  /* Bytes per sample */
286     maxsamplevalue = (depth <= 8) ? 255 : 65535;
287     strip_bytecount = width * height * bps;
288 
289     /* the following values must be known in advance */
290     ntags = 13;
291     data_size = 0;
292     if (resolution > 0)
293     {
294         ntags += 3;
295         data_size += 2*4 + 2*4;
296     }
297 
298     if (icc_size > 0) /* if icc profile exists add memory for tag */
299     {
300         ntags += 1;
301         data_size += icc_size;
302     }
303 
304     ifd_size = 2 + ntags*12 + 4;
305     data_offset = header_size + ifd_size;
306     strip_offset = data_offset + data_size;
307 
308     /* New subfile type */
309     add_ifd_entry (ifd, 254, IFDE_TYP_LONG, 1, 0);
310     /* image width */
311     add_ifd_entry (ifd, 256, (width > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT,
312                    1, width);
313     /* image length */
314     add_ifd_entry (ifd, 257, (height > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT,
315                    1, height);
316     /* bits per sample */
317     add_ifd_entry (ifd, 258, IFDE_TYP_SHORT, 1, depth);
318     /* compression (uncompressed) */
319     add_ifd_entry (ifd, 259, IFDE_TYP_SHORT, 1, 1);
320     /* photometric interpretation */
321     add_ifd_entry (ifd, 262, IFDE_TYP_SHORT, 1, 1);
322     /* strip offset */
323     add_ifd_entry (ifd, 273, IFDE_TYP_LONG, 1, strip_offset);
324     /* orientation */
325     add_ifd_entry (ifd, 274, IFDE_TYP_SHORT, 1, 1);
326     /* samples per pixel */
327     add_ifd_entry (ifd, 277, IFDE_TYP_SHORT, 1, 1);
328     /* rows per strip */
329     add_ifd_entry (ifd, 278, IFDE_TYP_LONG, 1, height);
330     /* strip bytecount */
331     add_ifd_entry (ifd, 279, IFDE_TYP_LONG, 1, strip_bytecount);
332     /* min sample value */
333     add_ifd_entry (ifd, 280, IFDE_TYP_SHORT, 1, 0);
334     /* max sample value */
335     add_ifd_entry (ifd, 281, IFDE_TYP_SHORT, 1, maxsamplevalue);
336     if (resolution > 0)
337     {
338         /* x resolution */
339         add_ifd_entry (ifd, 282, IFDE_TYP_RATIONAL, 1, data_offset);
340         data_offset += 2*4;
341         /* y resolution */
342         add_ifd_entry (ifd, 283, IFDE_TYP_RATIONAL, 1, data_offset);
343         data_offset += 2*4;
344     }
345     if (resolution > 0)
346     {
347         /* resolution unit (dpi) */
348         add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2);
349     }
350 
351     if (icc_size > 0) /* add ICC-profile TAG */
352     {
353       add_ifd_entry(ifd, 34675, 7, (int) icc_size, data_offset);
354       data_offset += icc_size;
355     }
356 
357     /* I prefer motorola format. Its human readable. But for 16 bit, */
358     /* the image format is defined by SANE to be the native byte order */
359     if (bps == 1)
360     {
361         motorola = 1;
362     }
363     else
364     {int check = 1;
365         motorola = ((*((char *)&check)) == 0);
366     }
367 
368     write_ifd (fptr, ifd, motorola);
369 
370     /* Write x/y resolution */
371     if (resolution > 0)
372     {
373         write_i4 (fptr, resolution, motorola);
374         write_i4 (fptr, 1, motorola);
375         write_i4 (fptr, resolution, motorola);
376         write_i4 (fptr, 1, motorola);
377     }
378 
379     if (icc_size > 0)
380     {
381       fwrite(icc_buffer, icc_size, 1, fptr);
382     }
383 
384     free(icc_buffer);
385 
386     free_ifd (ifd);
387 }
388 
389 static void
write_tiff_color_header(FILE *fptr, int width, int height, int depth, int resolution, const char *icc_profile)390 write_tiff_color_header (FILE *fptr, int width, int height, int depth,
391                          int resolution, const char *icc_profile)
392 {IFD *ifd;
393     int header_size = 8, ifd_size;
394     int strip_offset, data_offset, data_size;
395     int strip_bytecount;
396     int ntags;
397     int motorola, bps, maxsamplevalue;
398     void *icc_buffer = NULL;
399     size_t icc_size = 0;
400 
401     if (icc_profile)
402     {
403       icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
404     }
405 
406 
407     ifd = create_ifd ();
408 
409     bps = (depth <= 8) ? 1 : 2;  /* Bytes per sample */
410     maxsamplevalue = (depth <= 8) ? 255 : 65535;
411     strip_bytecount = width * height * 3 * bps;
412 
413     /* the following values must be known in advance */
414     ntags = 13;
415     data_size = 3*2 + 3*2 + 3*2;
416 
417     if (resolution > 0)
418     {
419         ntags += 3;
420         data_size += 2*4 + 2*4;
421     }
422 
423     if (icc_size > 0) /* if icc profile exists add memory for tag */
424     {
425         ntags += 1;
426         data_size += icc_size;
427     }
428 
429 
430     ifd_size = 2 + ntags*12 + 4;
431     data_offset = header_size + ifd_size;
432     strip_offset = data_offset + data_size;
433 
434     /* New subfile type */
435     add_ifd_entry (ifd, 254, IFDE_TYP_LONG, 1, 0);
436     /* image width */
437     add_ifd_entry (ifd, 256, (width > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT,
438                    1, width);
439     /* image length */
440     add_ifd_entry (ifd, 257, (height > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT,
441                    1, height);
442     /* bits per sample */
443     add_ifd_entry (ifd, 258, IFDE_TYP_SHORT, 3, data_offset);
444     data_offset += 3*2;
445     /* compression (uncompressed) */
446     add_ifd_entry (ifd, 259, IFDE_TYP_SHORT, 1, 1);
447     /* photometric interpretation */
448     add_ifd_entry (ifd, 262, IFDE_TYP_SHORT, 1, 2);
449     /* strip offset */
450     add_ifd_entry (ifd, 273, IFDE_TYP_LONG, 1, strip_offset);
451     /* orientation */
452     add_ifd_entry (ifd, 274, IFDE_TYP_SHORT, 1, 1);
453     /* samples per pixel */
454     add_ifd_entry (ifd, 277, IFDE_TYP_SHORT, 1, 3);
455     /* rows per strip */
456     add_ifd_entry (ifd, 278, IFDE_TYP_LONG, 1, height);
457     /* strip bytecount */
458     add_ifd_entry (ifd, 279, IFDE_TYP_LONG, 1, strip_bytecount);
459     /* min sample value */
460     add_ifd_entry (ifd, 280, IFDE_TYP_SHORT, 3, data_offset);
461     data_offset += 3*2;
462     /* max sample value */
463     add_ifd_entry (ifd, 281, IFDE_TYP_SHORT, 3, data_offset);
464     data_offset += 3*2;
465 
466     if (resolution > 0)
467     {
468         /* x resolution */
469         add_ifd_entry (ifd, 282, IFDE_TYP_RATIONAL, 1, data_offset);
470         data_offset += 2*4;
471         /* y resolution */
472         add_ifd_entry (ifd, 283, IFDE_TYP_RATIONAL, 1, data_offset);
473         data_offset += 2*4;
474     }
475 
476     if (resolution > 0)
477     {
478         /* resolution unit (dpi) */
479         add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2);
480     }
481 
482     if (icc_size > 0) /* add ICC-profile TAG */
483     {
484       add_ifd_entry(ifd, 34675, 7, (int) icc_size, data_offset);
485       data_offset += icc_size;
486     }
487 
488 
489     /* I prefer motorola format. Its human readable. But for 16 bit, */
490     /* the image format is defined by SANE to be the native byte order */
491     if (bps == 1)
492     {
493         motorola = 1;
494     }
495     else
496     {int check = 1;
497         motorola = ((*((char *)&check)) == 0);
498     }
499 
500     write_ifd (fptr, ifd, motorola);
501 
502     /* Write bits per sample value values */
503     write_i2 (fptr, depth, motorola);
504     write_i2 (fptr, depth, motorola);
505     write_i2 (fptr, depth, motorola);
506 
507     /* Write min sample value values */
508     write_i2 (fptr, 0, motorola);
509     write_i2 (fptr, 0, motorola);
510     write_i2 (fptr, 0, motorola);
511 
512     /* Write max sample value values */
513     write_i2 (fptr, maxsamplevalue, motorola);
514     write_i2 (fptr, maxsamplevalue, motorola);
515     write_i2 (fptr, maxsamplevalue, motorola);
516 
517     /* Write x/y resolution */
518     if (resolution > 0)
519     {
520         write_i4 (fptr, resolution, motorola);
521         write_i4 (fptr, 1, motorola);
522         write_i4 (fptr, resolution, motorola);
523         write_i4 (fptr, 1, motorola);
524     }
525 
526     /* Write ICC profile */
527     if (icc_size > 0)
528     {
529       fwrite(icc_buffer, icc_size, 1, fptr);
530     }
531 
532     free(icc_buffer);
533 
534     free_ifd (ifd);
535 }
536 
537 
538 void
sanei_write_tiff_header(SANE_Frame format, int width, int height, int depth, int resolution, const char *icc_profile, FILE *ofp)539 sanei_write_tiff_header (SANE_Frame format, int width, int height, int depth,
540 			 int resolution, const char *icc_profile, FILE *ofp)
541 {
542 #ifdef __EMX__	/* OS2 - write in binary mode. */
543     _fsetmode(ofp, "b");
544 #endif
545     switch (format)
546     {
547     case SANE_FRAME_RED:
548     case SANE_FRAME_GREEN:
549     case SANE_FRAME_BLUE:
550     case SANE_FRAME_RGB:
551         write_tiff_color_header (ofp, width, height, depth, resolution, icc_profile);
552         break;
553 
554     default:
555         if (depth == 1)
556             write_tiff_bw_header (ofp, width, height, resolution);
557         else
558             write_tiff_grey_header (ofp, width, height, depth, resolution, icc_profile);
559         break;
560     }
561 }
562