6#include "webp/encode.h"
18 m_scanState(ScanNotScanned),
26 memset(&m_iter, 0,
sizeof(m_iter));
31 WebPDemuxReleaseIterator(&m_iter);
32 WebPDemuxDelete(m_demuxer);
41 if (m_scanState != ScanError) {
44 if (m_features.has_animation && m_iter.frame_num >= m_frameCount)
55 qWarning(
"QWebpHandler::canRead() called with no device");
63bool QWebpHandler::ensureScanned()
const
65 if (m_scanState != ScanNotScanned)
66 return m_scanState == ScanSuccess;
68 m_scanState = ScanError;
71 const int headerBytesNeeded =
sizeof(WebPBitstreamFeatures);
80 if (
device()->isSequential() &&
device()->bytesAvailable() < byteSize + 8) {
81 qWarning() <<
"QWebpHandler: Insufficient data available in sequential device";
85 if (m_features.has_animation) {
87 if (that->ensureDemuxer()) {
88 that->m_loop = WebPDemuxGetI(m_demuxer, WEBP_FF_LOOP_COUNT);
89 that->m_frameCount = WebPDemuxGetI(m_demuxer, WEBP_FF_FRAME_COUNT);
92 QSize sz(that->m_features.width, that->m_features.height);
93 that->m_composited =
new QImage;
96 if (that->m_features.has_alpha)
99 m_scanState = ScanSuccess;
102 m_scanState = ScanSuccess;
106 return m_scanState == ScanSuccess;
109bool QWebpHandler::ensureDemuxer()
115 m_webpData.bytes =
reinterpret_cast<const uint8_t *
>(m_rawData.
constData());
116 m_webpData.size = m_rawData.
size();
118 m_demuxer = WebPDemux(&m_webpData);
119 if (m_demuxer == NULL)
122 m_formatFlags = WebPDemuxGetI(m_demuxer, WEBP_FF_FORMAT_FLAGS);
128 if (!ensureScanned() || !ensureDemuxer())
132 if (m_iter.frame_num == 0) {
134 WebPChunkIterator metaDataIter;
135 if ((m_formatFlags & ICCP_FLAG) && WebPDemuxGetChunk(m_demuxer,
"ICCP", 1, &metaDataIter)) {
137 metaDataIter.chunk.size);
143 WebPDemuxReleaseChunkIterator(&metaDataIter);
147 if (!WebPDemuxGetFrame(m_demuxer, 1, &m_iter))
150 if (m_iter.has_alpha && m_iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND)
154 if (!WebPDemuxNextFrame(&m_iter))
158 WebPBitstreamFeatures features;
159 VP8StatusCode status = WebPGetFeatures(m_iter.fragment.bytes, m_iter.fragment.size, &features);
160 if (status != VP8_STATUS_OK)
168 size_t output_size =
frame.sizeInBytes();
169#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
170 if (!WebPDecodeBGRAInto(
171 reinterpret_cast<const uint8_t*
>(m_iter.fragment.bytes), m_iter.fragment.size,
174 if (!WebPDecodeARGBInto(
175 reinterpret_cast<const uint8_t*
>(m_iter.fragment.bytes), m_iter.fragment.size,
180 if (!m_features.has_animation) {
186 if (!prevFrameRect.
isEmpty()) {
190 if (m_features.has_alpha) {
191 if (m_iter.blend_method == WEBP_MUX_NO_BLEND)
198 *
image = *m_composited;
200 image->setColorSpace(m_colorSpace);
207 if (
image.isNull()) {
208 qWarning() <<
"source image is null.";
211 if (std::max(
image.width(),
image.height()) > WEBP_MAX_DIMENSION) {
212 qWarning() <<
"QWebpHandler::write() source image too large for WebP: " <<
image.size();
219 if (srcImage.
format() != newFormat)
225 if (!WebPPictureInit(&
picture) || !WebPConfigInit(&
config)) {
226 qWarning() <<
"failed to init webp picture and config";
240 qWarning() <<
"failed to import image data to webp picture.";
245 int reqQuality = m_quality < 0 ? 75 :
qMin(m_quality, 100);
246 if (reqQuality < 100) {
248 config.quality = reqQuality;
254 WebPMemoryWriter writer;
255 WebPMemoryWriterInit(&writer);
256 picture.writer = WebPMemoryWrite;
260 qWarning() <<
"failed to encode webp picture, error code: " <<
picture.error_code;
262 WebPMemoryWriterClear(&writer);
267 if (
image.colorSpace().isValid()) {
269 WebPMux *mux = WebPMuxNew();
270 WebPData image_data = { writer.mem, writer.size };
271 WebPMuxSetImage(mux, &image_data, copy_data);
272 uint8_t vp8xChunk[10];
273 uint8_t
flags = 0x20;
274 if (
image.hasAlphaChannel())
276 vp8xChunk[0] =
flags;
282 vp8xChunk[4] =
width & 0xff;
283 vp8xChunk[5] = (
width >> 8) & 0xff;
284 vp8xChunk[6] = (
width >> 16) & 0xff;
285 vp8xChunk[7] =
height & 0xff;
286 vp8xChunk[8] = (
height >> 8) & 0xff;
287 vp8xChunk[9] = (
height >> 16) & 0xff;
288 WebPData vp8x_data = { vp8xChunk, 10 };
289 if (WebPMuxSetChunk(mux,
"VP8X", &vp8x_data, copy_data) == WEBP_MUX_OK) {
291 WebPData iccp_data = {
292 reinterpret_cast<const uint8_t *
>(iccProfile.
constData()),
293 static_cast<size_t>(iccProfile.
size())
295 if (WebPMuxSetChunk(mux,
"ICCP", &iccp_data, copy_data) == WEBP_MUX_OK) {
296 WebPData output_data;
297 if (WebPMuxAssemble(mux, &output_data) == WEBP_MUX_OK) {
298 res = (output_data.size ==
299 static_cast<size_t>(
device()->
write(
reinterpret_cast<const char *
>(output_data.bytes), output_data.size)));
301 WebPDataClear(&output_data);
307 res = (writer.size ==
308 static_cast<size_t>(
device()->
write(
reinterpret_cast<const char *
>(writer.mem), writer.size)));
311 WebPMemoryWriterClear(&writer);
325 return QSize(m_features.width, m_features.height);
327 return m_features.has_animation;
339 m_quality =
value.toInt();
357 if (!ensureScanned())
360 if (!m_features.has_animation)
368 if (!ensureScanned() || !m_features.has_animation)
372 return m_iter.frame_num - 1;
377 if (!ensureScanned())
380 return QRect(m_iter.x_offset, m_iter.y_offset, m_iter.width, m_iter.height);
385 if (!ensureScanned() || !m_features.has_animation)
394 if (!ensureScanned() || !m_features.has_animation)
397 return m_iter.duration;
IOBluetoothDevice * device
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
static QColorSpace fromIccProfile(const QByteArray &iccProfile)
Creates a QColorSpace from ICC profile iccProfile.
static QColor fromRgba(QRgb rgba) noexcept
Static convenience function that returns a QColor constructed from the given QRgb value rgba.
\inmodule QtCore \reentrant
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
qint64 peek(char *data, qint64 maxlen)
ImageOption
This enum describes the different options supported by QImageIOHandler.
static bool allocateImage(QSize size, QImage::Format format, QImage *image)
virtual void setOption(ImageOption option, const QVariant &value)
Sets the option option with the value value.
QIODevice * device() const
Returns the device currently assigned to the QImageIOHandler.
void setFormat(const QByteArray &format)
Sets the format of the QImageIOHandler to format.
bool hasAlphaChannel() const
Returns true if the image has a format that respects the alpha channel, otherwise returns false.
qsizetype bytesPerLine() const
Returns the number of bytes per image scanline.
int width() const
Returns the width of the image.
uchar * bits()
Returns a pointer to the first pixel data.
int height() const
Returns the height of the image.
Format
The following image formats are available in Qt.
void fill(uint pixel)
Fills the entire image with the given pixelValue.
Format format() const
Returns the format of the image.
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const &
The QPainter class performs low-level painting on widgets and other paint devices.
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Draws the rectangular portion source of the given image into the target rectangle in the paint device...
@ CompositionMode_SourceOver
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
\inmodule QtCore\reentrant
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
const QChar * constData() const
Returns a pointer to the data stored in the QString.
qsizetype size() const
Returns the number of characters in this string.
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
bool write(const QImage &image) override
Writes the image image to the assigned device.
bool supportsOption(ImageOption option) const override
Returns true if the QImageIOHandler supports the option option; otherwise returns false.
bool read(QImage *image) override
Read an image from the device, and stores it in image.
QRect currentImageRect() const override
Returns the rect of the current image.
int currentImageNumber() const override
For image formats that support animation, this function returns the sequence number of the current im...
int imageCount() const override
For image formats that support animation, this function returns the number of images in the animation...
bool canRead() const override
Returns true if an image can be read from the device (i.e., the image format is supported,...
QVariant option(ImageOption option) const override
Returns the value assigned to option as a QVariant.
int loopCount() const override
For image formats that support animation, this function returns the number of times the animation sho...
int nextImageDelay() const override
For image formats that support animation, this function returns the number of milliseconds to wait un...
void setOption(ImageOption option, const QVariant &value) override
Sets the option option with the value value.
#define QByteArrayLiteral(str)
static QString header(const QString &name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr const T & qMin(const T &a, const T &b)
GLint GLsizei GLsizei height
GLint GLsizei GLsizei GLenum format
GLfloat GLfloat GLfloat alpha
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
QT_BEGIN_NAMESPACE typedef uchar * output
static const int riffHeaderSize