Encoding an image to webp will distort the colors.
-
I've posted the same question before.
Encoding the image as in the title distorts the colors. I used code like this:
This stores binary data to a file.
How to encode original image without distortion?What I tried..
bool CBackground::encodeWebp(QFile& file, fpos_t position, unsigned long newAddress) { QImageReader reader(m_strBkgndImagePath); if (!reader.canRead()) { throw std::runtime_error("Cannot read image"); } std::unique_ptr<QImage> unique_img(new QImage(reader.read())); if (unique_img->isNull()) { throw std::runtime_error("Cannot create image from file"); } int width = unique_img->size().width(); int height = unique_img->size().height(); uint8_t* output; output = nullptr; size_t output_size = WebPEncodeRGBA(reinterpret_cast<uint8_t*>(unique_img->bits()), width, height, width * 4, 80, &output); if (output_size == 0) { throw std::runtime_error("WebPEncodeRGBA failed"); } // Write the compressed image data to file QByteArray byteArray(reinterpret_cast<const char*>(output), output_size); m_bkgndHeader.type = WEBP; m_bkgndHeader.ImageSize = static_cast<unsigned int>(byteArray.size()); setImageAddress(newAddress); position = static_cast<fpos_t>(newAddress); file.seek(position); file.write(byteArray.constData(), m_bkgndHeader.ImageSize); WebPFree(output); return true; } bool CBackground::decodeWebp(QFile *pFile) { long imageSize = m_bkgndHeader.ImageSize; long imageAddress = getImageAddress(); if (!pFile->seek(imageAddress)) { throw std::runtime_error("Failed to seek to image data"); return false; } QByteArray imageData(imageSize, 0); if (pFile->read(imageData.data(), imageSize) != imageSize) { throw std::runtime_error("Failed to read image data"); return false; } int width = 0, height = 0; uchar* decodedData = WebPDecodeRGBA(reinterpret_cast<uchar*>(imageData.data()), imageSize, &width, &height); if (!decodedData) { throw std::runtime_error("Failed to decode WebP image"); } m_pBkgndImage = new QImage(decodedData, width, height, width*4, QImage::Format_RGBA8888); if(m_pBkgndImage != nullptr){ return true; }else{ delete m_pBkgndImage; m_pBkgndImage = nullptr; return false; } return false; }
For reference, the following code encodes and decodes a jpeg, which works fine.
unsigned long CBackground::encodeJpeg(QFile& file, fpos_t position, unsigned long newAddress) { QImageReader reader(m_strBkgndImagePath); if (!reader.canRead()) { throw std::runtime_error("Cannot read image"); } std::unique_ptr<QImage> unique_img(new QImage(reader.read())); QByteArray byteArray; QBuffer buffer(&byteArray); buffer.open(QIODevice::WriteOnly); QImageWriter writer; writer.setQuality(80); // JPEG 품질 설정 writer.setFormat("JPEG"); writer.setDevice(&buffer); writer.write(*unique_img); m_bkgndHeader.type = JPEG; m_bkgndHeader.ImageSize = (long)byteArray.size(); setImageAddress( newAddress ); position = (fpos_t)newAddress; file.seek(position); file.write(byteArray.constData(), m_bkgndHeader.ImageSize); cout << getImageAddress() << "\t" << m_bkgndHeader.ImageSize << endl; return m_bkgndHeader.ImageSize; } bool CBackground::decodeJpeg(QFile *pFile) { long imageSize = m_bkgndHeader.ImageSize; long imageAddress = getImageAddress(); if (!pFile->seek(imageAddress)) { throw std::runtime_error("Failed to seek to image data"); return false; } QByteArray imageData(imageSize, Qt::Uninitialized); if (pFile->read(imageData.data(), imageSize) != imageSize) { throw std::runtime_error("Failed to read image data"); return false; } if (m_pBkgndImage != nullptr) { m_pBkgndImage = nullptr; } m_pBkgndImage = new QImage(QImage::fromData(imageData)); if(m_pBkgndImage != nullptr){ return true; }else{ m_pBkgndImage = nullptr; return false; } return false; }
-
@MyNameIsQt said in Encoding an image to webp will distort the colors.:
qDebug() << unique_img->format();
result:
QImage::Format_RGB32
Hence your issue. Convert the QImage to the proper format for your encoder.
-
We had the exact same discussion aboutt he usage six weeks ago and still the same issues: https://forum.qt.io/topic/144392/saving-webp-images-as-binary/3
-
Hi,
Did you check the format of your QImage object ?
You assume that it is in RGBA the way you use it which it's likely not. -
@Christian-Ehrlicher That's a different issue. The previous article was about memory access errors in the encoding process.
(After reviewing several times, I think there is a bug in the webpencodergba function. Sometimes, this function causes an error for certain images)
And the image color distortion problem was raised before, but it was related to saving .webp files, and it was solved, but the binary data problem remains unsolved. -
@MyNameIsQt
@SGaist is asking you to put intoencodeWebp()
qDebug() << unique_img->format();
What's that in https://doc.qt.io/qt-6/qimage.html#Format-enum and is it right for
WebPEncodeRGBA()
? -
@MyNameIsQt said in Encoding an image to webp will distort the colors.:
decodedData
Now you leak this data... and the pointer stuff for the QImage is still... confusing and error prone.
And I'm unsure if it's really Format_RGBA8888 (and I think it's what @SGaist wanted to tell you). Also you did not convert to the correct format befor doing the webp encoding.
And as already told you - Qt also has a webp image plugin but you rather try to figure out how to do it by yourself for over 6 weeks.
-
@Christian-Ehrlicher Creating webp image files via qt's image plugin is simple and very easy. And it works fine.
But what I need is to write the binary to a file. This file can store multiple webp binary data. The program reads and decodes this data with the address and size of the required webp image. -
@MyNameIsQt said in Encoding an image to webp will distort the colors.:
qDebug() << unique_img->format();
result:
QImage::Format_RGB32
Hence your issue. Convert the QImage to the proper format for your encoder.
-
Christian Ehrlicher Lifetime Qt Championreplied to MyNameIsQt on last edited by Christian Ehrlicher
@MyNameIsQt said in Encoding an image to webp will distort the colors.:
But what I need is to write the binary to a file. This file can store multiple webp binary data. The program reads and decodes this data with the address and size of the required webp image.
And what's the problem? Write them all out (into a file or buffer) and store them in the desired order in a new file...
-
@MyNameIsQt said in Encoding an image to webp will distort the colors.:
Encoding the image as in the title distorts the colors
The image you showed clearly looks like BGR[A].
-
@SGaist
I solved it. you were correct.
thank you.
And thank you everyone.std::unique_ptr<QImage> unique_img(new QImage(reader.read())); if (unique_img->isNull()) { throw std::runtime_error("Cannot create image from file"); } /* new add */ **QImage convertedImg = unique_img->convertToFormat(QImage::Format_RGBA8888);** int width = convertedImg.size().width(); int height = convertedImg.size().height(); // Encode the image data with the configured options uint8_t* output; output = nullptr; size_t output_size = WebPEncodeRGBA(reinterpret_cast<uint8_t*>(convertedImg.bits()), width, height, width * 4, 80, &output);
-