Listing 2 (tiff.c)

/***********************************************
*  file d:\cips\tiff.c
*
*  Functions: This file contains
*  read_tiff_header
*  extract_long_from_buffer
*  extract_short_from_buffer
*
*  Purpose: This file contains the subroutines
*  that read the tiff files header information.
*
*  External Calls:
*   mof.c - my_open_file
*   mrw.c - my_read
*
*   Modifications: created 23 June 1990
***********************************************/

#include "d:\cips\cips.h"

read_tiff_header(file_name, image_header)
   char file_name[];
   struct tiff_header_struct *image_header;
{
   char buffer[12];
   
   int      bytes_read,
      closed,
      file_desc,
      i,
      j,
      lsb,
      not_finished;
   
   long bits_per_pixel,
      image_length,
      image_width,
      length_of_field,
      offset_to_ifd,
      position,
      strip_offset,
      subfile,
      value;
   
   short entry_count,
      field_type,
      s_bits_per_pixel,
      s_image_length,
      s_image_width,
      s_strip_offset,
      tag_type;
   
   file_desc = my_open(file_name);

/*************************************
*   Determine if the file uses MSB
*   first or LSB first
*************************************/
   
   bytes_read = my_read(file_desc, buffer, 8);
   
   if(buffer[0] == 0x49)
      lsb = 1;
   else
      lsb = 0;

/*************************************
*  Read the offset to the IFD
*************************************/
   
   extract_long_from_buffer(buffer, lsb, 4,
        &offset_to_ifd);
   
   not_finished = 1;
   while(not_finished){
   
/************************************
*  Seek to the IFD and read the
*  entry_count, i.e. the number of
*  entries in the IFD.
*************************************/

    position = lseek(file_desc, offset_to_ifd, 0);
    bytes_read = my_read(file_desc, buffer, 2);
    extract_short_from_buffer(buffer, lsb, 0,
         &entry_count);

/***************************************
*  Now loop over the directory entries.
*  Look only for the tags we need. These are:
*    ImageLength
*    ImageWidth
*    BitsPerPixel(BitsPerSample)
*    StripOffset
***************************************/

    for(i=0; i<entry_count; i++){
     bytes_read = my_read(file_desc, buffer, 12);
     extract_short_from_buffer(buffer, lsb, 0,
          &tag_type);
     
     switch(tag_type){
        case 255: /* Subfile Type */
           extract_short_from_buffer(buffer, lsb, 2,
                 &field_type);
           extract_short_from_buffer(buffer, lsb, 4,
                 &length_of_field);
           extract_long_from_buffer(buffer, lsb, 8,
                 &subfile);
           break;
        
        case 256: /* ImageWidth */
           extract_short_from_buffer(buffer, lsb, 2,
                 &field_type);
           extract_short_from_buffer(buffer, lsb, 4,
                 &length_of_field);
           extract_long_from_buffer(buffer, lsb, 8,
                 &subfile);
           break;
        case 256: /* ImageWidth */
           extract_short_from_buffer(buffer, lsb, 2,
                 &field_type);
           extract_short_from_buffer(buffer, lsb, 4,
                 &length_of_field);
           if(field_type == 3){
            extract_short_from_buffer(buffer, lsb, 8,
                  &s_image_width);
           image_width = s_image_width;
           }
           else
            extract_long_from_buffer(buffer, lsb, 8,
                  &image_width);
           break;
        case 257: /* ImageLength */
           extract_short_from_buffer(buffer, lsb, 2,
                 &field_type);
           extract_short_from_buffer(buffer, lsb, 4,
                 &length of_field);
           if(field_type == 3){
            extract_short_from_buffer(buffer, lsb, 8,
                  &s_image_length);
            image_length = s_image_length;
           }
           else
            extract_long_from_buffer(buffer, lsb, 8,
                  &image_length);
           break;
        case 258: /* BitsPerPixel */
           extract_short_from_buffer(buffer, lsb, 2,
                 &field_type);
           extract_short_from_buffer(buffer, lsb, 4,
                 &length_of_field);
           if(field_type == 3){
            extract_short_from_buffer(buffer, lsb, 8,
                 &s_bits_per_pixel);
            bits_per_pixel = s_bits_per_pixel;
           }
           else
            extract_long_from_buffer(buffer, lsb, 8,
                 &bits_per_pixel);
           break;
        
        case 273: /* StripOffset */
           extract_short_from_buffer(buffer, lsb, 2,
                 &field_type);
           extract_short_from_buffer(buffer, lsb, 4,
                 &length_of_field);
           if(field_type == 3){
            extract_short_from_buffer(buffer, lsb, 8,
                 &s_strip_offset);
            strip_offset = s_strip_offset;
           }
           else
            extract_long_from_buffer(buffer, lsb, 8,
                 &strip_offset);
            break;
        
        default:
           break;
      
      } /* ends switch tag_type */
     } /* ends loop over i directory entries */
     
     bytes_read = my_read(file_desc, buffer, 4);
     extract_long_from_buffer(buffer, lsb, 0,
          &offset_to_ifd);
     if(offset_to_ifd == 0) not_finished = 0;
    
    } /* ends while not_finished */
    
   image_header->lsb                = lsb;
   image_header->bits_per_pixel = bits_per_pixel;
   image_header->image_length       = image_length;
   image_header->image_width        = image_width;
   image_header->strip_offset       = strip_offset;
   
   closed = close(file_desc);

}  /* ends read_tiff_header */

/****************************************
*   extract_long_from_buffer(...
*
*   This takes a four byte long out of a
*   buffer of characters. It is important
*   to know the byte order LSB or MSB.
****************************************/

extract_long_from_buffer(buffer, lsb, start, number)
   char buffer[];
   int      lsb, start;
   long *number;
{
   int i;
   union long_char_union lcu;
   
   if(lsb == 1){
      lcu.l_alpha[0] = buffer[start+0];
      lcu.l_alpha[1] = buffer[start+1];
      lcu.l_alpha[2] = buffer[start+2];
      lcu.l_alpha[3] = buffer[start+3];
   }  /* ends if lsb = 1 */
   
   if(lsb == 0){
      lcu.l_alpha[0] = buffer[start+3];
      lcu.l_alpha[1] = buffer[start+2];
      lcu.l_alpha[2] = buffer[start+1];
      lcu.l_alpha[3] = buffer[start+0];
   }  /* ends if lsb = 0    */
   
   *number = lcu.l_num;

}  /* ends extract_long_from_buffer */

/****************************************
*   extract_short_from_buffer(...
*
*   This takes a two byte short out of a
*   buffer of characters. It is important
*   to know the byte order LSB or MSB.
****************************************/

extract_short_from_buffer(buffer, lsb, start, number)
   char   buffer[];
   int        lsb, start;
   short  *number;
{

   int i;
   union short_char_union_lcu;
   
   if(lsb == 1){
      lcu.s_alpha[0] = buffer[start+0];
      lcu.s_alpha[1] = buffer[start+1];
   }   /* ends if lsb = 1 */
   
   if(lsb == 0){
      lcu.s_alpha[0] = buffer[start+1];
      lcu.s_alpha[1] = buffer[start+0];
   }   /* ends if lsb = 0    */
   
   *number = lcu.s_num;

} /* ends extract_short_from_buffer */