webp handler: support alpha-less reading and writing
Webp files can be with or without alpha channel. The handler would ignore this and read all as Format_ARGB32 images, and write all as having alpha, in both cases losing that important bit of information. As a driveby, simplify the endianness handling in write(). By always converting the source image to an endianness-independent QImage format, no special handling is required. Task-number: QTBUG-48628 Change-Id: I624ed72b18a8b59a542979efcb4e8ff81214e0d7 Reviewed-by: Liang Qi <liang.qi@qt.io>
This commit is contained in:
parent
aa33202648
commit
b9ba221756
|
@ -174,7 +174,8 @@ bool QWebpHandler::read(QImage *image)
|
||||||
if (status != VP8_STATUS_OK)
|
if (status != VP8_STATUS_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QImage frame(m_iter.width, m_iter.height, QImage::Format_ARGB32);
|
QImage::Format format = m_features.has_alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32;
|
||||||
|
QImage frame(m_iter.width, m_iter.height, format);
|
||||||
uint8_t *output = frame.bits();
|
uint8_t *output = frame.bits();
|
||||||
size_t output_size = frame.sizeInBytes();
|
size_t output_size = frame.sizeInBytes();
|
||||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||||
|
@ -219,13 +220,10 @@ bool QWebpHandler::write(const QImage &image)
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage srcImage = image;
|
QImage srcImage = image;
|
||||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
bool alpha = srcImage.hasAlphaChannel();
|
||||||
if (srcImage.format() != QImage::Format_ARGB32)
|
QImage::Format newFormat = alpha ? QImage::Format_RGBA8888 : QImage::Format_RGB888;
|
||||||
srcImage = srcImage.convertToFormat(QImage::Format_ARGB32);
|
if (srcImage.format() != newFormat)
|
||||||
#else /* Q_BIG_ENDIAN */
|
srcImage = srcImage.convertToFormat(newFormat);
|
||||||
if (srcImage.format() != QImage::Format_RGBA8888)
|
|
||||||
srcImage = srcImage.convertToFormat(QImage::Format_RGBA8888);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WebPPicture picture;
|
WebPPicture picture;
|
||||||
WebPConfig config;
|
WebPConfig config;
|
||||||
|
@ -238,13 +236,14 @@ bool QWebpHandler::write(const QImage &image)
|
||||||
picture.width = srcImage.width();
|
picture.width = srcImage.width();
|
||||||
picture.height = srcImage.height();
|
picture.height = srcImage.height();
|
||||||
picture.use_argb = 1;
|
picture.use_argb = 1;
|
||||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
bool failed = false;
|
||||||
if (!WebPPictureImportBGRA(&picture, srcImage.bits(), srcImage.bytesPerLine())) {
|
if (alpha)
|
||||||
#else /* Q_BIG_ENDIAN */
|
failed = !WebPPictureImportRGBA(&picture, srcImage.bits(), srcImage.bytesPerLine());
|
||||||
if (!WebPPictureImportRGBA(&picture, srcImage.bits(), srcImage.bytesPerLine())) {
|
else
|
||||||
#endif
|
failed = !WebPPictureImportRGB(&picture, srcImage.bits(), srcImage.bytesPerLine());
|
||||||
qWarning() << "failed to import image data to webp picture.";
|
|
||||||
|
|
||||||
|
if (failed) {
|
||||||
|
qWarning() << "failed to import image data to webp picture.";
|
||||||
WebPPictureFree(&picture);
|
WebPPictureFree(&picture);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
|
@ -53,15 +53,18 @@ void tst_qwebp::readImage_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("fileName");
|
QTest::addColumn<QString>("fileName");
|
||||||
QTest::addColumn<QSize>("size");
|
QTest::addColumn<QSize>("size");
|
||||||
|
QTest::addColumn<bool>("alpha");
|
||||||
|
|
||||||
QTest::newRow("kollada") << QString("kollada") << QSize(436, 160);
|
QTest::newRow("kollada") << QString("kollada") << QSize(436, 160) << true;
|
||||||
QTest::newRow("kollada_lossless") << QString("kollada_lossless") << QSize(436, 160);
|
QTest::newRow("kollada_lossless") << QString("kollada_lossless") << QSize(436, 160) << true;
|
||||||
|
QTest::newRow("kollada_noalpha") << QString("kollada_noalpha") << QSize(436, 160) << false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_qwebp::readImage()
|
void tst_qwebp::readImage()
|
||||||
{
|
{
|
||||||
QFETCH(QString, fileName);
|
QFETCH(QString, fileName);
|
||||||
QFETCH(QSize, size);
|
QFETCH(QSize, size);
|
||||||
|
QFETCH(bool, alpha);
|
||||||
|
|
||||||
const QString path = QStringLiteral(":/images/") + fileName + QStringLiteral(".webp");
|
const QString path = QStringLiteral(":/images/") + fileName + QStringLiteral(".webp");
|
||||||
QImageReader reader(path);
|
QImageReader reader(path);
|
||||||
|
@ -69,6 +72,7 @@ void tst_qwebp::readImage()
|
||||||
QImage image = reader.read();
|
QImage image = reader.read();
|
||||||
QVERIFY2(!image.isNull(), qPrintable(reader.errorString()));
|
QVERIFY2(!image.isNull(), qPrintable(reader.errorString()));
|
||||||
QCOMPARE(image.size(), size);
|
QCOMPARE(image.size(), size);
|
||||||
|
QCOMPARE(image.hasAlphaChannel(), alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_qwebp::readAnimation_data()
|
void tst_qwebp::readAnimation_data()
|
||||||
|
@ -136,10 +140,13 @@ void tst_qwebp::writeImage_data()
|
||||||
QTest::addColumn<QString>("postfix");
|
QTest::addColumn<QString>("postfix");
|
||||||
QTest::addColumn<int>("quality");
|
QTest::addColumn<int>("quality");
|
||||||
QTest::addColumn<QSize>("size");
|
QTest::addColumn<QSize>("size");
|
||||||
|
QTest::addColumn<bool>("alpha");
|
||||||
QTest::addColumn<bool>("needcheck");
|
QTest::addColumn<bool>("needcheck");
|
||||||
|
|
||||||
QTest::newRow("kollada-75") << QString("kollada") << QString(".png") << 75 << QSize(436, 160) << false;
|
QTest::newRow("kollada-75") << QString("kollada") << QString(".png") << 75 << QSize(436, 160) << true << false;
|
||||||
QTest::newRow("kollada-100") << QString("kollada") << QString(".png") << 100 << QSize(436, 160) << true;
|
QTest::newRow("kollada-100") << QString("kollada") << QString(".png") << 100 << QSize(436, 160) << true << true;
|
||||||
|
QTest::newRow("kollada_noalpha-75") << QString("kollada_noalpha") << QString(".webp") << 75 << QSize(436, 160) << false << false;
|
||||||
|
QTest::newRow("kollada_noalpha-100") << QString("kollada_noalpha") << QString(".webp") << 100 << QSize(436, 160) << false << true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_qwebp::writeImage()
|
void tst_qwebp::writeImage()
|
||||||
|
@ -148,6 +155,7 @@ void tst_qwebp::writeImage()
|
||||||
QFETCH(QString, postfix);
|
QFETCH(QString, postfix);
|
||||||
QFETCH(int, quality);
|
QFETCH(int, quality);
|
||||||
QFETCH(QSize, size);
|
QFETCH(QSize, size);
|
||||||
|
QFETCH(bool, alpha);
|
||||||
QFETCH(bool, needcheck);
|
QFETCH(bool, needcheck);
|
||||||
|
|
||||||
const QString path = QString("%1-%2.webp").arg(fileName).arg(quality);
|
const QString path = QString("%1-%2.webp").arg(fileName).arg(quality);
|
||||||
|
@ -162,8 +170,13 @@ void tst_qwebp::writeImage()
|
||||||
writer.setQuality(quality);
|
writer.setQuality(quality);
|
||||||
QVERIFY2(writer.write(image), qPrintable(writer.errorString()));
|
QVERIFY2(writer.write(image), qPrintable(writer.errorString()));
|
||||||
|
|
||||||
|
QImage reread(path);
|
||||||
|
QVERIFY(!reread.isNull());
|
||||||
|
QVERIFY(reread.size() == size);
|
||||||
|
QVERIFY(reread.hasAlphaChannel() == alpha);
|
||||||
|
|
||||||
if (needcheck)
|
if (needcheck)
|
||||||
QVERIFY(image == QImage(path));
|
QVERIFY(image == reread);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_qwebp)
|
QTEST_MAIN(tst_qwebp)
|
||||||
|
|
|
@ -4,5 +4,6 @@
|
||||||
<file>images/kollada.webp</file>
|
<file>images/kollada.webp</file>
|
||||||
<file>images/kollada_lossless.webp</file>
|
<file>images/kollada_lossless.webp</file>
|
||||||
<file>images/kollada_animation.webp</file>
|
<file>images/kollada_animation.webp</file>
|
||||||
|
<file>images/kollada_noalpha.webp</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
Loading…
Reference in New Issue