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