QImage: Чтение 16-битного TIFF в оттенках серого (Qt, C++)

Я хочу читать 16-битные изображения в градациях серого, используя C++, Qt и libtiff. Я создал функцию readTiff (ниже), которая считывает данные из tiff в QImage. Однако существует проблема, заключающаяся в том, что QImage 5.5 не поддерживает 16-битные оттенки серого. . И если я использую RGB16, я получу только шум.

Как я могу взломать QImage для поддержки Format_Grayscale16 или преобразовать данные в 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;
}

person Michal    schedule 17.08.2015    source источник
comment
Вы пробовали это или это?   -  person Bowdzone    schedule 17.08.2015
comment
Я видел оба вопроса. Первый посвящен C++; тем не менее, правильный ответ не кажется мне простым.   -  person Michal    schedule 17.08.2015
comment
Даже если вторым является python, логика, стоящая за ним, должна быть легко переведена на С++.   -  person Bowdzone    schedule 17.08.2015


Ответы (1)


Попробуйте это, должно сработать (я не проверял, просто пишу с нуля)

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;
}
person Marek R    schedule 17.08.2015
comment
Это рабочее решение... очистить код Qt... спасибо Марек - person Michal; 17.08.2015