Fix reading 16bpc grayscale PNGs
They were incorrectly attempted to be read as Indexed8, instead use the RGBA64 formats to read them with full accuracy. Task-number: QTBUG-45858 Change-Id: I14fc3cb0d59fa2fc0e68fd870f3b32352c34161f Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
parent
e0213d1939
commit
5d0ee89132
src/gui/image
tests/auto/gui/image/qimagereader
@ -245,7 +245,7 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
|
||||
png_set_interlace_handling(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
// Black & White or 8-bit grayscale
|
||||
// Black & White or grayscale
|
||||
if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
|
||||
png_set_invert_mono(png_ptr);
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
@ -266,19 +266,22 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
|
||||
else if (g == 1)
|
||||
image.setColor(0, qRgba(255, 255, 255, 0));
|
||||
}
|
||||
} else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
png_set_expand(png_ptr);
|
||||
png_set_strip_16(png_ptr);
|
||||
} else if (bit_depth == 16) {
|
||||
bool hasMask = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
|
||||
if (!hasMask)
|
||||
png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER);
|
||||
else
|
||||
png_set_expand(png_ptr);
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
if (image.size() != QSize(width, height) || image.format() != QImage::Format_ARGB32) {
|
||||
image = QImage(width, height, QImage::Format_ARGB32);
|
||||
QImage::Format format = hasMask ? QImage::Format_RGBA64 : QImage::Format_RGBX64;
|
||||
if (image.size() != QSize(width, height) || image.format() != format) {
|
||||
image = QImage(width, height, format);
|
||||
if (image.isNull())
|
||||
return;
|
||||
}
|
||||
if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
|
||||
png_set_swap_alpha(png_ptr);
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
|
||||
png_set_swap(png_ptr);
|
||||
} else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
png_set_expand(png_ptr);
|
||||
if (image.size() != QSize(width, height) || image.format() != QImage::Format_Grayscale8) {
|
||||
@ -289,9 +292,7 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
} else {
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
else if (bit_depth < 8)
|
||||
if (bit_depth < 8)
|
||||
png_set_packing(png_ptr);
|
||||
int ncols = bit_depth < 8 ? 1 << bit_depth : 256;
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
@ -356,12 +357,14 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
|
||||
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
|
||||
png_set_bgr(png_ptr);
|
||||
}
|
||||
} else if (bit_depth == 16 && (color_type & PNG_COLOR_MASK_COLOR)) {
|
||||
} else if (bit_depth == 16 && !(color_type & PNG_COLOR_MASK_PALETTE)) {
|
||||
QImage::Format format = QImage::Format_RGBA64;
|
||||
if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER);
|
||||
format = QImage::Format_RGBX64;
|
||||
}
|
||||
if (!(color_type & PNG_COLOR_MASK_COLOR))
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
if (image.size() != QSize(width, height) || image.format() != format) {
|
||||
image = QImage(width, height, format);
|
||||
if (image.isNull())
|
||||
@ -680,11 +683,11 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
|
||||
int num_palette;
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
// Black & White or 8-bit grayscale
|
||||
// Black & White or grayscale
|
||||
if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
|
||||
format = QImage::Format_Mono;
|
||||
} else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
format = QImage::Format_ARGB32;
|
||||
} else if (bit_depth == 16) {
|
||||
format = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? QImage::Format_RGBA64 : QImage::Format_RGBX64;
|
||||
} else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
format = QImage::Format_Grayscale8;
|
||||
} else {
|
||||
@ -696,7 +699,7 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
|
||||
{
|
||||
// 1-bit and 8-bit color
|
||||
format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
|
||||
} else if (bit_depth == 16 && (color_type & PNG_COLOR_MASK_COLOR)) {
|
||||
} else if (bit_depth == 16 && !(color_type & PNG_COLOR_MASK_PALETTE)) {
|
||||
format = QImage::Format_RGBA64;
|
||||
if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
format = QImage::Format_RGBX64;
|
||||
|
BIN
tests/auto/gui/image/qimagereader/images/basn0g16.png
Normal file
BIN
tests/auto/gui/image/qimagereader/images/basn0g16.png
Normal file
Binary file not shown.
After (image error) Size: 167 B |
BIN
tests/auto/gui/image/qimagereader/images/basn2c16.png
Normal file
BIN
tests/auto/gui/image/qimagereader/images/basn2c16.png
Normal file
Binary file not shown.
After (image error) Size: 302 B |
BIN
tests/auto/gui/image/qimagereader/images/basn4a16.png
Normal file
BIN
tests/auto/gui/image/qimagereader/images/basn4a16.png
Normal file
Binary file not shown.
After (image error) Size: 2.2 KiB |
BIN
tests/auto/gui/image/qimagereader/images/basn6a16.png
Normal file
BIN
tests/auto/gui/image/qimagereader/images/basn6a16.png
Normal file
Binary file not shown.
After (image error) Size: 3.4 KiB |
BIN
tests/auto/gui/image/qimagereader/images/tbwn0g16.png
Normal file
BIN
tests/auto/gui/image/qimagereader/images/tbwn0g16.png
Normal file
Binary file not shown.
After (image error) Size: 1.3 KiB |
@ -525,6 +525,11 @@ void tst_QImageReader::imageFormat_data()
|
||||
QTest::newRow("png") << QString("kollada.png") << QByteArray("png") << QImage::Format_ARGB32;
|
||||
QTest::newRow("png-2") << QString("YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32;
|
||||
QTest::newRow("png-3") << QString("kollada-16bpc.png") << QByteArray("png") << QImage::Format_RGBA64;
|
||||
QTest::newRow("png-4") << QString("basn0g16.png") << QByteArray("png") << QImage::Format_RGBX64; // Grayscale16
|
||||
QTest::newRow("png-5") << QString("basn2c16.png") << QByteArray("png") << QImage::Format_RGBX64;
|
||||
QTest::newRow("png-6") << QString("basn4a16.png") << QByteArray("png") << QImage::Format_RGBA64; // Grayscale16Alpha16
|
||||
QTest::newRow("png-7") << QString("basn6a16.png") << QByteArray("png") << QImage::Format_RGBA64;
|
||||
QTest::newRow("png-8") << QString("tbwn0g16.png") << QByteArray("png") << QImage::Format_RGBA64; // Grayscale16+tRNS
|
||||
QTest::newRow("svg") << QString("rect.svg") << QByteArray("svg") << QImage::Format_ARGB32_Premultiplied;
|
||||
QTest::newRow("svgz") << QString("rect.svgz") << QByteArray("svgz") << QImage::Format_ARGB32_Premultiplied;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user