Fall 99 : CS 638 Graphics
Instructor: Dr. Gleicher
TA: Richard Yu Gu
Last modified: 15:52 Aug 15, 2000
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:
The following steps will make the compiler use correct method to generate the machine code:
By carrying out the following steps, we tell the linker to link in the correct libtiff library file.
2. Using LIBTIFF in your code.
- TIFF *tif=TIFFOpen("input.tif", "r");
- // #define uint32 unsigned long
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); // uint32 width;
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); // uint32 height;
- 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]
- 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!
- TIFF *out= TIFFOpen("new.tif", "w");
- 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).
- 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);
- 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
buf =(unsigned char *)_TIFFmalloc(linebytes);
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)
- (void) TIFFClose(out);
Appendix A. Trouble Shooting.
Appendix B. FAQ.
To be updated when more questions come up.