LIBTIFF Tutorial

Fall 99 : CS 638 Graphics

Instructor: Dr. Gleicher

TA: Richard Yu Gu

Last modified: 

0. Introduction.

LIBTIFF is a C graphic library provides support for the Tag Image File Format (TIFF), a widely used format for storing image data.  This library provide means to easily access and create TIFF image files.  LIBTIFF will be the supported image manipulating package supported in the class.  Since we will use some TIFF image files as the test samples for the class projects, hopefully you will all use this library to read and write the image files.

This tutorial is intended to get you start using LIBTIFF under MSVC++ 6.0 to simply read and write TIFF image files.  This tutorial is directed toward the needs of the CS638 class only and is not a complete or detailed documentation of the library.  There is not a complete documentation for LIBTIFF in html format, the documentation page is now at http://www.cs.wisc.edu/~cs638-2/libtiff/.  However there are man pages came with this package, and can be access at /p/course/cs638-gleicher/public/man/.  If you have access to a Unix machine, you can do "man functionName" at command prompt.

There is a complete specification on TIFF file format at ftp://ftp.adobe.com/pub/adobe/DeveloperSupport/TechNotes/PDFfiles/TIFF6.pdf .

The libtiff package and documentations can be find at ftp://ftp.sgi.com/graphics/tiff/.

1. Setting Up The VC++ 6.0 Project To Use LIBTIFF

To use LIBTIFF in your existing VC++ 6.0 Project/WorkSpace, you need to do the following setting modifications:

  1. Open your existing Project/WorkSpace file in VC++ 6.0
  2. Choose Project-Settings... menu item.
  3. Click "C/C++" tab in the dialog.
  4. Choose "Preprocessor" item in the "Category:" menu.
  5. Choose "All Configurations" item in the "Settings for:" menu.
  6. ADD (not replacing) the following path to the "Additional Include Directories:" field: P:\course\cs638-gleicher\public\include\libtiff\, this will allow the compiler to find the header files for the library

        The following steps will make the compiler use correct method to generate the machine code:

  1. Choose "Code Generation" item from the "Category" menu
  2. Choose "Win32 Release" item in the "Settings for:" menu
  3. Select "Multithreaded" option in the "Use run-time library:" menu.
  4. Select "Win32 Debug" item in the "Settings for:" menu
  5. Set "Use run-time library" menu to the option "Debug Multithreaded".
  6. Click "Link" tab in the dialog.
  7. Select "Input" item in the "Category:" menu.
  8. Choose "All Configurations" item in the "Settings for:" menu
  9. Add (not replacing) the following path to the "Additional library path:" field: P:\course\cs638-gleicher\public\lib\, this will allow the linker to find the library binary files of LIBTIFF.

        By carrying out the following steps, we tell the linker to link in the correct libtiff library file.

  1. Choose "Win32 Release" item in the "Settings for:" menu
  2. Add (without change original) following text to the "Object/library modules:" field: libtiff.lib
  3. Choose "Win32 Debug" item in the "Settings for:" menu
  4. Add (without change original) following text to the "Object/library modules:" field: dlibtiff.lib.
  5. Click "Ok".

2. Using LIBTIFF in your code.

  1. Add the following line in the beginning of your code file(s) to include the libtiff header file:


     

     

       #include <tiffio.h>
     

  2. Open file and read
    • You must open the file with the following line to read the tiff file:
    •     TIFF *tif=TIFFOpen("input.tif", "r");
    • Then you must get the size of the image from the opened file:
    •  // #define uint32 unsigned long
      TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);           // uint32 width;
      TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);        // uint32 height;
    • You should use the LIBTIFF library memory allocation functions to get space to store the image:
    • uint32 npixels=width*h;
      raster=(uint32 *) _TIFFmalloc(npixels *sizeof(uint32));
       

      [Note: Though it works under Win32, you should not use the C-"malloc/free" and the C++-"new/delete" functions/operators to do the memory management for the reading buffer]

    • Now you are able to read the image from the TIFF file using the following function:
    • TIFFReadRGBAImage(tif, width, height, raster, 0);

      Note: You should always check the return value of the function to make sure that there is no error occurred in the reading process.  Returning 1 means read was successful, and if 0 is returned, some type of error occured.

      What you have now is an array (raster) of pixel values, one for each pixel in the image, and each pixel is a 4-byte value.  Each of the bytes represent a channel of the pixel value (RGBA).  Each channel is represented by an integer value from 0 to 255.

      To get each of the individual channel of a pixel use the function:

      char X=(char )TIFFGetX(raster[i]);  // where X can be the channels R, G, B, and A.
      // i is the index of the pixel in the raster.

      Important: Remember that the origin of the raster is at the lower left corner.  You should be able to figure out the how the image is stored in the raster given that the pixel information is stored a row at a time!

    • After you are finished with the raster you should destroy it and free up the memory:
    • _TIFFfree(raster);
  3. Always Close the File when you are done with it.


     

     

    TIFFClose(tif);
     

  4. Creating a new TIFF image file;
    • You must open the file with the following line to write the tiff file, this will create the file if it does not exist, and replace the file if it does.
    • TIFF *out= TIFFOpen("new.tif", "w");
    • Your image data should be store in some type of array of char's.
    • int sampleperpixel = 4;    // or 3 if there is no alpha channel, you should get a understanding of alpha in class soon.

      char *image=new char [width*height*sampleperpixel];

      Then format of the pixel information is store in the order RGBA, into the array, each channel occupies 1 byte (char).

    • Now we need to set the tags in the new image file, and the essential ones are the following:
    • TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width);  // set the width of the image
      TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);    // set the height of the image
      TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, sampleperpixel);   // set number of channels per pixel
      TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);    // set the size of the channels
      TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);    // set the origin of the image.
      //   Some other essential fields to set that you do not have to understand for now.
      TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
      TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
    • We will use most basic image data storing method provided by the library to write the data into the file, this method uses strips, and we are storing a line (row) of pixel at a time.  This following code writes the data from the char array image into the file:
    • tsize_t linebytes = sampleperpixel * width;     // length in memory of one row of pixel in the image.

      unsigned char *buf = NULL;        // buffer used to store the row of pixel information for writing to file
      //    Allocating memory to store the pixels of current row
      if (TIFFScanlineSize(out)linebytes)
          buf =(unsigned char *)_TIFFmalloc(linebytes);
      else
          buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(out));

      // We set the strip size of the file to be size of one row of pixels
      TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, width*sampleperpixel));

      //Now writing image to the file one strip at a time
      for (uint32 row = 0; row < h; row++)
      {
          memcpy(buf, &image[(h-row-1)*linebytes], linebytes);    // check the index here, and figure out why not using h*linebytes
          if (TIFFWriteScanline(out, buf, row, 0) < 0)
          break;
      }

    • Finally we close the output file, and destroy the buffer
    • (void) TIFFClose(out);

      if (buf)
          _TIFFfree(buf);

    • One suggestion for working with the image data is to convert the raster structure into the char image[] structure for image analysis and manipulations.
    • With the above example you should be able to have the basic way of read and write TIFF image files.


Appendix A. Trouble Shooting.

Appendix B. FAQ.
 


To be updated when more questions come up.
.