0

I want to read 16-bit grayscale images using C++, Qt and libtiff. I've created the readTiff function (below) that reads data from tiff to QImage. However, there is a problem that QImage 5.5 doesn't support 16-bit grayscale. And if I use RGB16, I'll get only noise.

How can I hack QImage to support Format_Grayscale16 or convert data to Format_Grayscale8 ?

/**
 * @brief Reads TIFF image
 * @param path
 * @return QImage
 */
QImage EdsImporter::readTiff(const QString &path) const {

  // Loads tiff file
  TIFF* tiff = TIFFOpen(path.toStdString().c_str(), "r");
  if (!tiff) {
    QString msg = "Failed to open TIFF: '" + path + "'";
    throw new Exception(NULL, msg, this, __FUNCTION__, __LINE__);
  }

  // Temporary variables
  uint32 width, height;
  tsize_t scanlength;

  // Read dimensions of image
  if (TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width) != 1) {
    QString msg = "Failed to read width of TIFF: '" + path + "'";
    throw new Exception(NULL, msg, this, __FUNCTION__, __LINE__);
  }
  if (TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height) != 1) {
    QString msg = "Failed to read height of TIFF: '" + path + "'";
    throw new Exception(NULL, msg, this, __FUNCTION__, __LINE__);
  }

  // Number of bytes in a decoded scanline
  scanlength = TIFFScanlineSize(tiff);

  QImage image(width, height, QImage::Format_RGB16);

  // TEMPORARY: Save to PNG for preview
  image.save("tiff/" + StringUtils::random() + ".png", "PNG");

  if (image.isNull() || scanlength != image.bytesPerLine()) {
    TIFFClose(tiff);
    QString msg = "Failed to create QImage from TIFF: '" + path + "'";
    throw new Exception(NULL, msg, this, __FUNCTION__, __LINE__);
  }

  // Read image data
  for (uint32 y = 0; y < height; y++) {
    TIFFReadScanline(tiff, image.scanLine(y), y);
  }
  TIFFClose(tiff);
  return image;
}
Michal
  • 1,955
  • 5
  • 33
  • 56
  • Have you tried [this](http://stackoverflow.com/questions/11239203/with-c-and-qt-how-do-i-display-a-16-bit-raw-file-as-an-image) or [this](http://stackoverflow.com/questions/15672743/convert-16-bit-grayscale-to-qimage)? – Bowdzone Aug 17 '15 at 07:12
  • I saw both questions. The first one is about C++; nevertheless, the correct answer doesn't seem straightforward to me. – Michal Aug 17 '15 at 07:21
  • Even with the second being python the logic behind it should be easily translatable into c++ – Bowdzone Aug 17 '15 at 07:36

1 Answers1

2

Try this it should work (I didn't test it, just write from scratch)

QImage convertGray16TifToQImage(TIFF *tif) {
    // Temporary variables
    uint32 width, height;

    // Read dimensions of image
    if (TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width) != 1) {
        QString msg = "Failed to read width of TIFF: '" + path + "'";
        throw new Exception(NULL, msg, this, __FUNCTION__, __LINE__);
    }
    if (TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height) != 1) {
        QString msg = "Failed to read height of TIFF: '" + path + "'";
        throw new Exception(NULL, msg, this, __FUNCTION__, __LINE__);
    }
    QImage result(width, height, QImage::Format_Grayscale8);

    QVarLengthArray<quint16, 1024> src(width);
    for (uint32 y=0; y<height; ++y) {
         TIFFReadScanline(tiff, src.data(), y, 0);
         quint8 *dst = (quint8 *)result.scanLine(y);
         for (uint32 x=0; x<width; ++x) {
              dst[x] = src[x]>>8; // here you have a room for tweaking color range usage
         }
    }
    return result;
}
mpromonet
  • 11,326
  • 43
  • 62
  • 91
Marek R
  • 32,568
  • 6
  • 55
  • 140