From 5214bcd3d868664bb057f2689c02ec263bbc980b Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 29 Jul 2019 13:33:47 +0200 Subject: Support writing WebP color space profiles Change-Id: I9d9473c2866d9792cd8752816a291be04e39ec19 Reviewed-by: Eirik Aavitsland --- src/imageformats/configure.json | 7 +-- src/plugins/imageformats/webp/qwebphandler.cpp | 62 +++++++++++++++++++++----- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/imageformats/configure.json b/src/imageformats/configure.json index 03d59d3..7c6eaef 100644 --- a/src/imageformats/configure.json +++ b/src/imageformats/configure.json @@ -117,10 +117,11 @@ "include": [ "webp/decode.h", "webp/encode.h", - "webp/demux.h" + "webp/demux.h", + "webp/mux.h" ], "qmake": [ - "LIBS += -lwebp -lwebpdemux" + "LIBS += -lwebp -lwebpdemux -lwebpmux" ], "main": [ "#if WEBP_ABI_IS_INCOMPATIBLE(WEBP_DECODER_ABI_VERSION, 0x0203) || WEBP_ABI_IS_INCOMPATIBLE(WEBP_ENCODER_ABI_VERSION, 0x0202)", @@ -144,7 +145,7 @@ } }, "sources": [ - "-lwebp -lwebpdemux" + "-lwebp -lwebpdemux -lwebpmux" ] } }, diff --git a/src/plugins/imageformats/webp/qwebphandler.cpp b/src/plugins/imageformats/webp/qwebphandler.cpp index d56d28c..3916996 100644 --- a/src/plugins/imageformats/webp/qwebphandler.cpp +++ b/src/plugins/imageformats/webp/qwebphandler.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the WebP plugins in the Qt ImageFormats module. @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qwebphandler_p.h" +#include "webp/mux.h" #include "webp/encode.h" #include #include @@ -220,13 +221,6 @@ bool QWebpHandler::read(QImage *image) return true; } -static int pictureWriter(const quint8 *data, size_t data_size, const WebPPicture *const pic) -{ - QIODevice *io = reinterpret_cast(pic->custom_ptr); - - return data_size ? ((quint64)(io->write((const char*)data, data_size)) == data_size) : 1; -} - bool QWebpHandler::write(const QImage &image) { if (image.isNull()) { @@ -276,8 +270,10 @@ bool QWebpHandler::write(const QImage &image) config.quality = 70; // For lossless, specifies compression effort; 70 is libwebp default } config.alpha_quality = config.quality; - picture.writer = pictureWriter; - picture.custom_ptr = device(); + WebPMemoryWriter writer; + WebPMemoryWriterInit(&writer); + picture.writer = WebPMemoryWrite; + picture.custom_ptr = &writer; if (!WebPEncode(&config, &picture)) { qWarning() << "failed to encode webp picture, error code: " << picture.error_code; @@ -285,9 +281,53 @@ bool QWebpHandler::write(const QImage &image) return false; } + bool res = false; + if (image.colorSpace().isValid()) { + int copy_data = 0; + WebPMux *mux = WebPMuxNew(); + WebPData image_data = { writer.mem, writer.size }; + WebPMuxSetImage(mux, &image_data, copy_data); + uint8_t vp8xChunk[10]; + uint8_t flags = 0x20; // Has ICCP chunk, no XMP, EXIF or animation. + if (image.hasAlphaChannel()) + flags |= 0x10; + vp8xChunk[0] = flags; + vp8xChunk[1] = 0; + vp8xChunk[2] = 0; + vp8xChunk[3] = 0; + const unsigned width = image.width() - 1; + const unsigned height = image.height() - 1; + vp8xChunk[4] = width & 0xff; + vp8xChunk[5] = (width >> 8) & 0xff; + vp8xChunk[6] = (width >> 16) & 0xff; + vp8xChunk[7] = height & 0xff; + vp8xChunk[8] = (height >> 8) & 0xff; + vp8xChunk[9] = (height >> 16) & 0xff; + WebPData vp8x_data = { vp8xChunk, 10 }; + if (WebPMuxSetChunk(mux, "VP8X", &vp8x_data, copy_data) == WEBP_MUX_OK) { + QByteArray iccProfile = image.colorSpace().iccProfile(); + WebPData iccp_data = { + reinterpret_cast(iccProfile.constData()), + static_cast(iccProfile.size()) + }; + if (WebPMuxSetChunk(mux, "ICCP", &iccp_data, copy_data) == WEBP_MUX_OK) { + WebPData output_data; + if (WebPMuxAssemble(mux, &output_data) == WEBP_MUX_OK) { + res = (output_data.size == + static_cast(device()->write(reinterpret_cast(output_data.bytes), output_data.size))); + } + WebPDataClear(&output_data); + } + } + WebPMuxDelete(mux); + } + if (!res) { + res = (writer.size == + static_cast(device()->write(reinterpret_cast(writer.mem), writer.size))); + } WebPPictureFree(&picture); - return true; + return res; } QVariant QWebpHandler::option(ImageOption option) const -- cgit v1.2.1