QImage: 读取 16 位灰度 TIFF (Qt, C++)
QImage: Read 16-bit grayscale TIFF (Qt, C++)
我想使用 C++、Qt 和 libtiff 读取 16 位灰度图像。我已经创建了 readTiff 函数(如下),用于将数据从 tiff 读取到 QImage。但是,有个问题就是QImage 5.5 doesn't support 16-bit grayscale。如果我使用 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;
}
试一下它应该可以工作(我没有测试它,只是从头开始写)
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;
}
我想使用 C++、Qt 和 libtiff 读取 16 位灰度图像。我已经创建了 readTiff 函数(如下),用于将数据从 tiff 读取到 QImage。但是,有个问题就是QImage 5.5 doesn't support 16-bit grayscale。如果我使用 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;
}
试一下它应该可以工作(我没有测试它,只是从头开始写)
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;
}