Hi,
Does anyone here have any experience of using libtiff in c++? I have been trying to do some simple image processing using it and I don't seem to be able to write images. I can make files that have roughly the right size, but they're not correct as they don't open with any image viewers that I have. A test example of my code is shown below. The code is supposed to read in a colour image to an array (raster), convert it to monochrome by averaging the pixel values and storing them in an int array (image_mono), then convert the int array back into a char array (monoFile) and output this array as a tiff. Anyway, it compiles and runs, but the tiff is not readable :-( Any tips would be greatly appreciated.
#include <iostream>
using std::cout;
using std::endl;
using std::cerr;
#include <cmath>
#include <tiffio.h>
int main(int argc, char* argv[])
{
uint32 width = 0;
uint32 height = 0;
float xres;
float yres;
uint16 resUnit;
uint32 *raster = NULL;
uint32 numberOfPixels = 0;
unsigned pixel = 0;
// Open the input file, as given via the command line
TIFF* tif = TIFFOpen(argv[1], "r");
if (!tif){
cerr << "Unable to open image!" << endl;
return 1;
}
// Get the dimensions of the image
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres);
TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres);
TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &resUnit);
// Now use the libtiff malloc functions to allocate memory to store the image data
numberOfPixels=width*height;
if(numberOfPixels)
raster = (uint32 *)_TIFFmalloc(numberOfPixels*sizeof(uint32));
// Now actually read the data from the image...
if(!TIFFReadRGBAImage(tif,width,height,raster,0)){
// Print an error and exit if it doesn't read properly
cerr << "Error occured when reading image data!" << endl;
return 1;
}
else // Close the file if the info is read OK
TIFFClose(tif);
// Now the pixel values are in memory, so get the pixel values into the form
// that I want; that is monochromatic, by averaging the R, G & B channels...
int *image_mono = (int*)malloc(numberOfPixels*sizeof(int));
for(pixel = 0; pixel < numberOfPixels; pixel++)
image_mono[pixel] = ( (static_cast<int>(static_cast<char>(TIFFGetR(raster[pixel]))) & 0xFF) +
(static_cast<int>(static_cast<char>(TIFFGetG(raster[pixel]))) & 0xFF) +
(static_cast<int>(static_cast<char>(TIFFGetB(raster[pixel]))) & 0xFF))/3;
// The reason for the bitwise AND (&) in the above is that I found that
// if I just do static_cast<int>(static_cast<char>(TIFFGetX(raster[pixel])))
// then I get the result (in hex) FFFFFF00 + the actual pixel value. By doing
// 0xFF & on it then I get the answer I am looking for.
char *monoFile = (char *)malloc(numberOfPixels);
for(pixel = 0; pixel < numberOfPixels; pixel++)
monoFile[pixel] = (char)(image_mono[pixel] | 0xFFFFFF00);
// The bitwise OR (|) here undoes the AND that I used above.
// Open a new TIFF file for the output...
if((tif = TIFFOpen("output.tif", "w")) == NULL){
cerr << "Could not open output.tif for writing" << endl;
return 1;
}
// Set some tags in the output file. To be honest, I don't know much about
// what I'm doing here, I've just tried a bunch of different things...
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 8*width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, height);
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, 2);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tif, TIFFTAG_XRESOLUTION, xres);
TIFFSetField(tif, TIFFTAG_YRESOLUTION, yres);
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, resUnit);
// Write the information to the file
TIFFWriteEncodedStrip(tif, 0, monoFile, width*height);
return 0;
}
I'm all out of ideas about what to do to get this to work. The documentation for libtiff seems to be a lot more sparse than I expected. Alternatively, if there is some other tiff library that I should be using then certainly let me know that as well!
Cheers,
Ravenous