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 39typedef struct { 40 int tag, typ, nvals, val; 41} IFD_ENTRY; 42 43 44typedef 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 56static IFD * 57create_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 77static void 78free_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 91static void 92add_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 114static void 115write_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 130static void 131write_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 149static void 150write_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 183static void 184write_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 266static void 267write_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 389static void 390write_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 538void 539sanei_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