2007.10.27 16:40 "[Tiff] tiff reading with libtiff: problems with certain image files", by Tobias Eberle
Hello,
the code below reads tiff files and saves the grey scaled pixels into an array. The code works well except for certain images. You can find an example image at: http://stuff.tobiaseberle.de/F2-1.tif
The problem arises in the for loop iterating over the pixels: for (unsigned int ii = 0; ii < uiBufferSize; ii+=usSamplesPerPixel)
uiBufferSize is too large and my voxel class raises an exception telling that we are out of range.
I don't know what is different between this image and other images. Why is the buffer size wrong or lets say different than expected?
Thank you for your help,
Tobias
TIFF *file = TIFFOpen(iter->c_str(), "r");
if (!file)
{
m_pVoxelField->clear();
throw EFileReaderFileNotFound(*iter);
}
//get image size
unsigned int uiWidth;
unsigned int uiHeight;
TIFFGetField(file, TIFFTAG_IMAGEWIDTH, &uiWidth);
TIFFGetField(file, TIFFTAG_IMAGELENGTH, &uiHeight);
if (bFirst)
{
uiDimX = uiWidth;
uiDimY = uiHeight;
m_pVoxelField->setDim(uiWidth, uiHeight, uiDimZ);
bFirst = false;
}
if (uiWidth != uiDimX || uiHeight != uiDimY)
{
m_pVoxelField->clear();
TIFFClose(file);
throw EFileReaderTiffFilesDoNotHaveSameImageSize(*iter);
}
//get bits per sample
unsigned short usBitsPerSample;
if (TIFFGetField(file, TIFFTAG_BITSPERSAMPLE, &usBitsPerSample) ==
0)
{
m_pVoxelField->clear();
TIFFClose(file);
throw EFileReaderTiffUndefinedBitsPerSample(*iter);
}
unsigned short usExtraSamples;
if (TIFFGetField(file, TIFFTAG_EXTRASAMPLES, &usExtraSamples) == 0)
{
...
}
//8bit greyscale or 24bit true color
if (usBitsPerSample != 8)
{
m_pVoxelField->clear();
TIFFClose(file);
throw EFileReaderTiffUnsupportedBitsPerSample(*iter);
}
//get samples per pixel
unsigned short usSamplesPerPixel;
if (TIFFGetField(file, TIFFTAG_SAMPLESPERPIXEL, &usSamplesPerPixel)
== 0)
{
m_pVoxelField->clear();
TIFFClose(file);
throw EFileReaderTiffUndefinedSamplesPerPixel(*iter);
}
//1 for greyscale, 3 for rgb
if (usSamplesPerPixel != 1 && usSamplesPerPixel != 3)
{
m_pVoxelField->clear();
TIFFClose(file);
throw EFileReaderTiffUnsupportedSamplesPerPixel(iter->c_str());
}
//get planar config
unsigned short usPlanarConfig;
if (TIFFGetField(file, TIFFTAG_PLANARCONFIG, &usPlanarConfig) != 0)
{
if (usPlanarConfig != PLANARCONFIG_CONTIG)
{
throw EFileReaderTiffUnsupportedPlanarConfig(*iter);
}
}
//get photometric
unsigned short usPhotometric;
if (TIFFGetField(file, TIFFTAG_PHOTOMETRIC, &usPhotometric) == 0)
{
m_pVoxelField->clear();
TIFFClose(file);
throw EFileReaderTiffUndefinedPhotometricInterpretation(*iter);
}
if (usPhotometric != PHOTOMETRIC_RGB &&
usPhotometric != PHOTOMETRIC_MINISBLACK &&
usPhotometric != PHOTOMETRIC_MINISWHITE)
{
m_pVoxelField->clear();
TIFFClose(file);
throw EFileReaderTiffUnsupportedPhotometricInterpretation(*iter);
}
//get fill order
unsigned short usFillOrder;
if (TIFFGetField(file, TIFFTAG_FILLORDER, &usFillOrder) == 0)
{
//assume correct fill order
usFillOrder = FILLORDER_MSB2LSB;
}
//read in the possible multiple strips
int iStripSize = TIFFStripSize(file);
int iStripMax = TIFFNumberOfStrips(file);
unsigned int uiOffset = 0;
unsigned char *pucBuf;
//calculate buffer size for the image.
unsigned int uiBufferSize = iStripMax*iStripSize;
//unsigned int uiBufferSize = uiDimX * uiDimY * usSamplesPerPixel;
pucBuf = new unsigned char[sizeof(unsigned char)*uiBufferSize];
if (pucBuf == NULL)
{
m_pVoxelField->clear();
TIFFClose(file);
throw EOutOfMemory();
}
for(int iStripCounter = 0; iStripCounter < iStripMax; iStripCounter
++)
{
//read one strip
int iRead = TIFFReadEncodedStrip(file, iStripCounter, pucBuf +
uiOffset,
iStripSize);
if (iRead == -1)
{
delete[] pucBuf;
m_pVoxelField->clear();
TIFFClose(file);
throw EFileReaderBadFile(*iter);
}
uiOffset += iRead;
}
unsigned int uiX = 0;
unsigned int uiY = 0;
for (unsigned int ii = 0; ii < uiBufferSize; ii+=usSamplesPerPixel)
{
unsigned char ucVoxel = pucBuf[ii];
//fillorder
if (usFillOrder != FILLORDER_MSB2LSB)
{
//swap bits: AB -> BA
for (unsigned char jj = 0; jj < usSamplesPerPixel; jj++)
{
unsigned char ucTemp = pucBuf[ii+jj];
pucBuf[ii+jj] <<= 4;
ucTemp >>= 4;
pucBuf[ii+jj] += ucTemp;
}
}
//photometric interpretation
if (usPhotometric != PHOTOMETRIC_RGB)
{
if (usPhotometric == PHOTOMETRIC_MINISWHITE)
{
//wrong interpretation, we need 0 = black
//-> flip bits
ucVoxel = ~ucVoxel;
}
}
else
{
//greyscale
ucVoxel = (pucBuf[ii] + pucBuf[ii+1] + pucBuf[ii+2])/3;
}
//set voxel
m_pVoxelField->setVoxel(uiX, uiY, zz, ucVoxel);
//count x and y position
uiY = uiY + 1;
if (uiY >= uiDimY)
{
uiY = 0;
uiX++;
}
}
delete[] pucBuf;
TIFFClose(file);