source: trunk/JPGPROC/source/gbmsrc/gbmtifh.c@ 57

Last change on this file since 57 was 57, checked in by gyoung, 2 years ago

Fix errors reported by CPPCheck

File size: 16.0 KB
Line 
1
2/*
3
4gbmtifh.c - Routines to handle TIFF file headers
5
6*/
7
8/*...sincludes:0:*/
9#include <stdio.h>
10#include <stdlib.h>
11#include <stddef.h>
12#include <string.h>
13#include "gbm.h"
14#include "gbmhelp.h"
15#define _GBMTIFH_
16#include "gbmtifh.h"
17
18/*...vgbm\46\h:0:*/
19/*...vgbmhelp\46\h:0:*/
20/*...vgbmtifh\46\h:0:*/
21/*...e*/
22
23/*...susefull:0:*/
24#define ifd_malloc() ((IFD *) malloc((size_t) sizeof(IFD)))
25#define ifd_free(ifd) free((char *) ifd)
26
27#define ifh_malloc() ((IFH *) malloc((size_t) sizeof(IFH)))
28#define ifh_free(ifh) free((char *) ifh)
29
30static int sizeof_data_type(short data_type)
31 {
32 switch ( data_type )
33 {
34 case D_BYTE:
35 case D_SBYTE:
36 case D_ASCII:
37 case D_UNDEFINED:
38 return 1;
39 case D_SHORT:
40 case D_SSHORT:
41 return sizeof(short);
42 case D_LONG:
43 case D_SLONG:
44 return sizeof(long);
45 case D_RATIONAL:
46 case D_SRATIONAL:
47 return sizeof(rational);
48 case D_FLOAT:
49 return 4;
50 case D_DOUBLE:
51 return 8;
52 }
53 return 1;
54 }
55
56static void tag_free(TAG *tag)
57 {
58 free(tag->value);
59 }
60
61/*
62This finds the slot for the new tag. It returns NULL if the limit of
63MAX_TAGS tags is curruntly defined.
64*/
65
66static TAG *get_tag_slot(short type, IFD *ifd)
67 {
68 int i;
69
70 if ( ifd->n_tags == MAX_TAGS )
71 return NULL;
72
73 for ( i = ifd->n_tags;
74 i > 0 && ifd->tags[i - 1].type >= type;
75 i-- )
76 memcpy(ifd->tags + i,
77 ifd->tags + i - 1,
78 sizeof(TAG));
79
80 ifd->n_tags++;
81
82 /* now i == slot, with greater than elements moved up */
83
84 return &(ifd->tags[i]);
85 }
86/*...e*/
87
88/*...sread_ifh_and_ifd:0:*/
89/*...sread_long:0:*/
90#define make_long(b1,b2,b3,b4) ( ((long)(b1)<<24) | ((long)(b2)<<16) | ((long)(b3)<<8) | (long)(b4) )
91
92static long read_long(int fd, BOOLEAN motorola)
93 {
94 byte b[4];
95
96 gbm_file_read(fd, b, 4);
97 return ( motorola ) ?
98 make_long(b[0], b[1], b[2], b[3]) :
99 make_long(b[3], b[2], b[1], b[0]) ;
100 }
101/*...e*/
102/*...sread_short:0:*/
103#define make_short(b1,b2) ( ((short)(b1)<<8) | (short)(b2) )
104
105static short read_short(int fd, BOOLEAN motorola)
106 {
107 byte b[2];
108
109 gbm_file_read(fd, b, 2);
110 return ( motorola ) ?
111 make_short(b[0], b[1]) :
112 make_short(b[1], b[0]) ;
113 }
114/*...e*/
115/*...sread_rational:0:*/
116static void read_rational(int fd, BOOLEAN motorola, rational *r)
117 {
118 r->numerator = read_long(fd, motorola);
119 r->denominator = read_long(fd, motorola);
120 }
121/*...e*/
122/*...sread_tag:0:*/
123static int read_tag(int fd, BOOLEAN motorola, TAG *tag)
124 {
125 int i, s, n;
126 long len;
127 long seek_to, old_pos;
128
129 tag->type = read_short(fd, motorola);
130 tag->data_type = read_short(fd, motorola);
131 tag->length = read_long(fd, motorola);
132
133 if ( tag->type & 0x8000 )
134 /* proprietry tag */
135 {
136 gbm_file_lseek(fd, 4L, SEEK_CUR); /* skip data */
137 return TE_OK; /* assumed ok */
138 }
139
140 n = (int) tag->length;
141
142/*...sbugfix for UBU\39\s writing of ColorMap tag:8:*/
143/* UBU writes out a length feild of 256 when it should write 768 */
144
145if ( tag->type == T_COLORMAP && (n / 3) * 3 != n )
146 n *= 3;
147/*...e*/
148
149 s = sizeof_data_type(tag->data_type);
150 len = s * n;
151
152 if ( len > 4 )
153 /* will have to seek for data */
154 {
155 seek_to = read_long(fd, motorola);
156 old_pos = gbm_file_lseek(fd, 0L, SEEK_CUR);
157 gbm_file_lseek(fd, seek_to, SEEK_SET);
158 }
159
160 if ( (tag->value = malloc((size_t) len)) == NULL )
161 return TE_MEM;
162
163 switch ( tag->data_type )
164 {
165 case D_BYTE:
166 case D_SBYTE:
167 gbm_file_read(fd, tag->value, n);
168 break;
169 case D_ASCII:
170 gbm_file_read(fd, tag->value, n);
171 break;
172 case D_SHORT:
173 case D_SSHORT:
174 {
175 short *short_ptr = (short *) tag->value;
176
177 for ( i = 0; i < n; i++ )
178 *short_ptr++ = read_short(fd, motorola);
179 }
180 break;
181 case D_LONG:
182 case D_SLONG:
183 {
184 long *long_ptr = (long *) tag->value;
185
186 for ( i = 0; i < n; i++ )
187 *long_ptr++ = read_long(fd, motorola);
188 }
189 break;
190 case D_RATIONAL:
191 case D_SRATIONAL:
192 {
193 rational *rational_ptr = (rational *) tag->value;
194
195 for ( i = 0; i < n; i++ )
196 read_rational(fd, motorola, rational_ptr++);
197 }
198 break;
199 case D_FLOAT:
200 /* Skip 4 byte IEEE floating point */
201 gbm_file_lseek(fd, 4 * len, SEEK_CUR);
202 break;
203 case D_DOUBLE:
204 /* Skip 8 byte IEEE double precision floating point */
205 gbm_file_lseek(fd, 8 * len, SEEK_CUR);
206 break;
207 default:
208 gbm_file_read(fd, tag->value, (int) len);
209 break;
210 }
211
212 if ( len > 4 )
213 gbm_file_lseek(fd, old_pos, SEEK_SET);
214 else if ( len < 4 )
215 gbm_file_lseek(fd, 4L - len, SEEK_CUR); /* advance past gap */
216
217 return TE_OK;
218 }
219/*...e*/
220/*...sread_ifd:0:*/
221/*
222For the time being we will assume there is only one IFD in
223a given TIFF file. When this code was written, the author
224knew of no software packages that support multiple IFDs.
225*/
226
227/*...sclean_up_ifd:0:*/
228static void clean_up_ifd(IFD *ifd, int n)
229 {
230 int i;
231 TAG *tag;
232
233 for ( i = 0; i < n; i++ )
234 {
235 tag = &(ifd->tags[i]);
236 if ( !(tag->type & 0x8000) ) /* its not read in */
237 tag_free(tag);
238 }
239 ifd_free(ifd);
240 }
241/*...e*/
242
243static int read_ifd(int fd, BOOLEAN motorola, IFD **ifd_return)
244 {
245 IFD *ifd;
246 int i, ecode;
247
248 if ( (ifd = ifd_malloc()) == NULL )
249 return TE_MEM;
250
251 /* ensure we can handle all the tags */
252
253 if ( (ifd->n_tags = read_short(fd, motorola)) > MAX_TAGS )
254 {
255 ifd_free(ifd); return TE_N_TAGS;
256 }
257
258 /* get the tags */
259
260 for ( i = 0; i < ifd->n_tags; i++ )
261 if ( (ecode = read_tag(fd, motorola, &(ifd->tags[i]))) != TE_OK )
262 {
263 clean_up_ifd(ifd, i);
264 return ecode;
265 }
266
267 *ifd_return = ifd;
268
269 return TE_OK;
270 }
271/*...e*/
272/*...sskip_ifd:0:*/
273/* Returns TRUE if there is another IFD afterwards */
274
275static BOOLEAN skip_ifd(int fd, BOOLEAN motorola)
276 {
277 short n_tags = read_short(fd, motorola);
278 long offset_ifd;
279 gbm_file_lseek(fd, 12L * n_tags, SEEK_CUR);
280 offset_ifd = read_long(fd, motorola);
281 if ( offset_ifd == 0L )
282 return FALSE;
283 gbm_file_lseek(fd, offset_ifd, SEEK_SET);
284 return TRUE;
285 }
286/*...e*/
287
288int read_ifh_and_ifd(int fd, int n_ifds_to_skip, IFH **ifh_return)
289 {
290 IFH *ifh;
291 long offset_ifd;
292 BOOLEAN motorola;
293 int ecode;
294
295 if ( (ifh = ifh_malloc()) == NULL )
296 return TE_MEM;
297
298 gbm_file_read(fd, (char *) &(ifh->byte_order), sizeof(short));
299 motorola = ( ifh->byte_order == ('M' << 8) + 'M' );
300
301 /* Apparently, the following number has great univeral significance! */
302 /* See the TIFF 5.0 spec. for details! */
303
304 if ( (ifh->version_no = read_short(fd, motorola)) != 42 )
305 {
306 ifh_free(ifh); return TE_VERSION;
307 }
308
309 offset_ifd = read_long(fd, motorola);
310 gbm_file_lseek(fd, offset_ifd, SEEK_SET);
311 while ( n_ifds_to_skip-- > 0 )
312 if ( !skip_ifd(fd, motorola) ) {
313 ifh_free(ifh);
314 return TE_N_IFD;
315 }
316
317 if ( (ecode = read_ifd(fd, motorola, &(ifh->ifd))) != TE_OK )
318 {
319 ifh_free(ifh); return ecode;
320 }
321
322 *ifh_return = ifh;
323
324 return TE_OK;
325 }
326/*...e*/
327/*...slocate_tag:0:*/
328TAG *locate_tag(IFD *ifd, short type)
329 {
330 int i;
331
332 for ( i = 0; i < ifd->n_tags; i++ )
333 if ( ifd->tags[i].type == type )
334 return &(ifd->tags[i]);
335 return NULL;
336 }
337/*...e*/
338/*...snumeric_tag:0:*/
339BOOLEAN numeric_tag(TAG *tag)
340 {
341 short t = tag->data_type;
342 return t == D_BYTE ||
343 t == D_SHORT || t == D_SSHORT ||
344 t == D_LONG || t == D_SLONG ;
345 }
346/*...e*/
347/*...svalue_of_tag_n:0:*/
348/*
349For a numeric tag, return the value of the nth item in it.
350Upto the caller to know that tag is signed or unsigned.
351*/
352
353long value_of_tag_n(TAG *tag, int n)
354 {
355 switch ( tag->data_type )
356 {
357 case D_BYTE:
358 {
359 unsigned char *p = (unsigned char *) tag->value;
360 return (long) (unsigned long) p[n];
361 }
362 case D_SBYTE:
363 {
364 signed char *p = (signed char *) tag->value;
365 return (long) p[n];
366 }
367 case D_SHORT:
368 {
369 unsigned short *p = (unsigned short *) tag->value;
370 return (long) (unsigned long) p[n];
371 }
372 case D_SSHORT:
373 {
374 signed short *p = (signed short *) tag->value;
375 return (long) p[n];
376 }
377 case D_LONG:
378 {
379 unsigned long *p = (unsigned long *) tag->value;
380 return (long) p[n];
381 }
382 case D_SLONG:
383 {
384 signed long *p = (signed long *) tag->value;
385 return (long) p[n];
386 }
387 }
388 return 0L;
389 }
390/*...e*/
391/*...svalue_of_tag:0:*/
392/*
393For a numeric tag, return the value of the 1st value in it.
394This is usefull for tags that typically only have 1 value anyway.
395*/
396
397long value_of_tag(TAG *tag)
398 {
399 return value_of_tag_n(tag, 0);
400 }
401/*...e*/
402/*...sfree_ifh:0:*/
403void free_ifh(IFH *ifh)
404 {
405 IFD *ifd = ifh->ifd;
406 clean_up_ifd(ifd, ifd->n_tags);
407 ifh_free(ifh);
408 }
409/*...e*/
410/*...smake_ifh:0:*/
411/*
412Creates an empty IFH set up for the image.
413Also creates an IFD as part of the IFH.
414Use add_?_tag() routines to add tags to IFH's IFD.
415*/
416
417IFH *make_ifh(void)
418 {
419 IFH *ifh;
420 IFD *ifd;
421
422 if ( (ifh = ifh_malloc()) == NULL )
423 return NULL;
424
425 if ( (ifh->ifd = ifd = ifd_malloc()) == NULL )
426 {
427 ifh_free(ifh);
428 return NULL;
429 }
430
431 ifh->byte_order = ('I' << 8) + 'I';
432 ifh->version_no = 42;
433
434 ifd->n_tags = 0;
435
436 return ifh;
437 }
438/*...e*/
439/*...sadd_byte_tag:0:*/
440BOOLEAN add_byte_tag(IFD *ifd, short type, byte *value, int n)
441 {
442 byte *byte_ptr;
443 TAG *tag;
444
445 if ( (byte_ptr = (byte *) malloc((size_t) (n * sizeof(byte)))) == NULL )
446 return FALSE;
447 if ( (tag = get_tag_slot(type, ifd)) == NULL ) {
448 free(byte_ptr);
449 return FALSE;
450 }
451 tag->type = type;
452 tag->data_type = D_BYTE;
453 tag->length = (long) n;
454 if ( value != NULL )
455 memcpy(tag->value = (char *) byte_ptr,
456 value,
457 n * sizeof(byte));
458 free(byte_ptr);
459 return TRUE;
460 }
461/*...e*/
462/*...sadd_ascii_tag:0:*/
463BOOLEAN add_ascii_tag(IFD *ifd, short type, char *value)
464 {
465 char *ascii_ptr;
466 TAG *tag;
467 int n;
468
469 n = strlen(value) + 1;
470 if ( (ascii_ptr = (char *) malloc((size_t) n)) == NULL )
471 return FALSE;
472 if ( (tag = get_tag_slot(type, ifd)) == NULL ) {
473 free(ascii_ptr);
474 return FALSE;
475 }
476 tag->type = type;
477 tag->data_type = D_ASCII;
478 tag->length = (long) n;
479 strcpy(tag->value = ascii_ptr, value);
480 free(ascii_ptr);
481 return TRUE;
482 }
483/*...e*/
484/*...sadd_short_tag:0:*/
485BOOLEAN add_short_tag(IFD *ifd, short type, short *value, int n)
486 {
487 short *short_ptr;
488 TAG *tag;
489
490 if ( (short_ptr = (short *) malloc((size_t) (n * sizeof(short)))) == NULL )
491 return FALSE;
492 if ( (tag = get_tag_slot(type, ifd)) == NULL ) {
493 free(short_ptr);
494 return FALSE;
495 }
496 tag->type = type;
497 tag->data_type = D_SHORT;
498 tag->length = (long) n;
499 if ( value != NULL )
500 memcpy(tag->value = (char *) short_ptr,
501 value,
502 n * sizeof(short));
503 free(short_ptr);
504 return TRUE;
505 }
506/*...e*/
507/*...sadd_long_tag:0:*/
508BOOLEAN add_long_tag(IFD *ifd, short type, long *value, int n)
509 {
510 long *long_ptr;
511 TAG *tag;
512
513 if ( (long_ptr = (long *) malloc((size_t) (n * sizeof(long)))) == NULL )
514 return FALSE;
515 if ( (tag = get_tag_slot(type, ifd)) == NULL ) {
516 free(long_ptr);
517 return FALSE;
518 }
519 tag->type = type;
520 tag->data_type = D_LONG;
521 tag->length = (long) n;
522 if ( value != NULL )
523 memcpy(tag->value = (char *) long_ptr,
524 value,
525 n * sizeof(long));
526 free(long_ptr);
527 return TRUE;
528 }
529/*...e*/
530/*...sadd_rational_tag:0:*/
531BOOLEAN add_rational_tag(IFD *ifd, short type, rational *value, int n)
532 {
533 rational *rational_ptr;
534 TAG *tag;
535
536 if ( (rational_ptr = (rational *) malloc((size_t) (n * sizeof(rational)))) == NULL )
537 return FALSE;
538 if ( (tag = get_tag_slot(type, ifd)) == NULL ) {
539 free(rational_ptr);
540 return FALSE;
541 }
542 tag->type = type;
543 tag->data_type = D_RATIONAL;
544 tag->length = (long) n;
545 if ( value != NULL )
546 memcpy(tag->value = (char *) rational_ptr,
547 value,
548 n * sizeof(rational));
549 free(rational_ptr);
550 return TRUE;
551 }
552/*...e*/
553/*...swrite_ifh_and_ifd:0:*/
554/*...spad:0:*/
555static BOOLEAN pad(int fd, int n)
556 {
557 static char padding[] = { 0, 0, 0, 0 };
558
559 return gbm_file_write(fd, padding, n) == n;
560 }
561/*...e*/
562/*...swrite_short:0:*/
563static BOOLEAN write_short(int fd, short s)
564 {
565 byte b[2];
566
567 b[0] = (byte) (s & 0x00ffU) ;
568 b[1] = (byte) ((unsigned short) (s & 0xff00U) >> 8);
569
570 return gbm_file_write(fd, b, 2) == 2;
571 }
572/*...e*/
573/*...swrite_long:0:*/
574static BOOLEAN write_long(int fd, long l)
575 {
576 byte b[4];
577
578 b[0] = (byte) (l & 0x000000ffUL);
579 b[1] = (byte) ((l & 0x0000ff00UL) >> 8);
580 b[2] = (byte) ((l & 0x00ff0000UL) >> 16);
581 b[3] = (byte) ((l & 0xff000000UL) >> 24);
582
583 return gbm_file_write(fd, b, 4) == 4;
584 }
585/*...e*/
586/*...swrite_rational:0:*/
587static BOOLEAN write_rational(int fd, rational *rational)
588 {
589 return write_long(fd, rational->numerator ) &&
590 write_long(fd, rational->denominator) ;
591 }
592/*...e*/
593/*...swrite_tag:0:*/
594static BOOLEAN write_tag(int fd, TAG *tag, long *offset_upto)
595 {
596 BOOLEAN ok;
597 int s, i, n, len;
598 long offset_return_to;
599
600 ok = write_short(fd, tag->type) &&
601 write_short(fd, tag->data_type) &&
602 write_long(fd, tag->length);
603
604 if ( !ok )
605 return FALSE;
606
607 /* if we can fit the tag into 4 bytes, do so */
608 /* else we will have to allocate some disc space */
609
610 s = sizeof_data_type(tag->data_type);
611 n = (int) tag->length;
612 len = s * n;
613
614 if ( len > 4 )
615 {
616 if ( !write_long(fd, *offset_upto) )
617 return FALSE;
618 offset_return_to = gbm_file_lseek(fd, 0L, SEEK_CUR);
619 gbm_file_lseek(fd, *offset_upto, SEEK_SET);
620 }
621
622 /* actually write the tag */
623
624 switch ( tag->data_type )
625 {
626 case D_BYTE:
627 case D_ASCII:
628 if ( gbm_file_write(fd, tag->value, n) != n )
629 return FALSE;
630 break;
631 case D_SHORT:
632 {
633 short *short_ptr = (short *) tag->value;
634
635 for ( i = 0; i < n; i++ )
636 if ( !write_short(fd, *short_ptr++) )
637 return FALSE;
638 }
639 break;
640 case D_LONG:
641 {
642 long *long_ptr = (long *) tag->value;
643
644 for ( i = 0; i < n; i++ )
645 if ( !write_long(fd, *long_ptr++) )
646 return FALSE;
647 }
648 break;
649 case D_RATIONAL:
650 {
651 rational *rational_ptr = (rational *) tag->value;
652
653 for ( i = 0; i < n; i++ )
654 if ( !write_rational(fd, rational_ptr++) )
655 return FALSE;
656 }
657 break;
658 }
659
660 if ( len > 4 )
661 {
662 if ( (*offset_upto = gbm_file_lseek(fd, 0L, SEEK_CUR)) & 1L )
663 /* pad to make next offset even */
664 {
665 if ( !pad(fd, 1) )
666 return FALSE;
667 (*offset_upto)++;
668 }
669 gbm_file_lseek(fd, offset_return_to, SEEK_SET);
670 }
671 else if ( len < 4 )
672 if ( !pad(fd, 4 - len) )
673 return FALSE;
674 return TRUE;
675 }
676/*...e*/
677/*...swrite_ifd:0:*/
678/*
679Given an IFD, write it out to disc.
680Also patch the IFH (which we know will be at the start of the file).
681In writing out a tag we may need some more disc space other than
682that for the IFD table. This occurs when a field is larger than
6834 bytes. What we do is to keep a pointer to the next free space
684(after the table) and write_tag() will advance it if it uses any
685extra space.
686*/
687
688BOOLEAN write_ifd(int fd, IFD *ifd)
689 {
690 int i, n;
691 long offset_upto;
692
693 if ( !write_short(fd, (short) (n = ifd->n_tags)) )
694 return FALSE;
695
696 /* write out tags */
697
698 offset_upto = gbm_file_lseek(fd, 0L, SEEK_CUR) + n * 12L + 4L;
699 /* leave space for each tag plus next IFD ptr */
700
701 for ( i = 0; i < n; i++ )
702 if ( !write_tag(fd, &(ifd->tags[i]), &offset_upto) )
703 return FALSE;
704
705 /* done writing out the IFD, now put null next IFD pointer */
706
707 if ( !write_long(fd, 0L) )
708 return FALSE;
709
710 gbm_file_lseek(fd, offset_upto, SEEK_SET);
711
712 return TRUE;
713 }
714/*...e*/
715
716BOOLEAN write_ifh_and_ifd(IFH *ifh, int fd)
717 {
718 return write_short(fd, ifh->byte_order) &&
719 write_short(fd, ifh->version_no) &&
720 write_long(fd, 8L) &&
721 write_ifd(fd, ifh->ifd);
722 }
723/*...e*/
724/*...supdate_byte_tag:0:*/
725void update_byte_tag(IFD *ifd, short type, byte *value)
726 {
727 TAG *tag;
728 int n;
729
730 tag = locate_tag(ifd, type);
731 n = (int) tag->length;
732 memcpy(tag->value, value, n * sizeof(byte));
733 }
734/*...e*/
735/*...supdate_ascii_tag:0:*/
736void update_ascii_tag(IFD *ifd, short type, char *value)
737 {
738 TAG *tag;
739 int n;
740
741 tag = locate_tag(ifd, type);
742 n = (int) tag->length;
743 memcpy(tag->value, value, n);
744 }
745/*...e*/
746/*...supdate_short_tag:0:*/
747void update_short_tag(IFD *ifd, short type, short *value)
748 {
749 TAG *tag;
750 int n;
751
752 tag = locate_tag(ifd, type);
753 n = (int) tag->length;
754 memcpy(tag->value, value, n * sizeof(short));
755 }
756/*...e*/
757/*...supdate_long_tag:0:*/
758void update_long_tag(IFD *ifd, short type, long *value)
759 {
760 TAG *tag;
761 int n;
762
763 tag = locate_tag(ifd, type);
764 n = (int) tag->length;
765 memcpy(tag->value, value, n * sizeof(long));
766 }
767/*...e*/
768/*...supdate_rational_tag:0:*/
769void update_rational_tag(IFD *ifd, short type, rational *value)
770 {
771 TAG *tag;
772 int n;
773
774 tag = locate_tag(ifd, type);
775 n = (int) tag->length;
776 memcpy(tag->value, value, n * sizeof(rational));
777 }
778/*...e*/
779/*...supdate_ifd:0:*/
780/*
781Go back to the IFD, and rewrite it.
782*/
783
784BOOLEAN update_ifd(IFD *ifd, int fd)
785 {
786 gbm_file_lseek(fd, 8L, SEEK_SET);
787 return write_ifd(fd, ifd);
788 }
789/*...e*/
Note: See TracBrowser for help on using the repository browser.