home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / rexx / library2 / gbmrexx / gbm / gbmtifh.c < prev    next >
C/C++ Source or Header  |  1993-08-27  |  17KB  |  795 lines

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