AWARE [SYSTEMS] Imaging expertise for the Delphi developer
AWare Systems, Imaging expertise for the Delphi developer, Home TIFF and LibTiff Mailing List Archive

LibTiff Mailing List

TIFF and LibTiff Mailing List Archive
October 2007

Previous Thread
Next Thread

Previous by Thread
Next by Thread

Previous by Date
Next by Date

Contact

The TIFF Mailing List Homepage
This list is run by Frank Warmerdam
Archive maintained by AWare Systems



Valid HTML 4.01!



2007.10.27 16:40 "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);