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);