Click here to Skip to main content
15,887,485 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
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?

You can see an image from the same question in this link.
Qt Forum

What I have tried:

C++
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;
}
Posted
Updated 29-May-23 11:57am
Comments
0x01AA 29-May-23 11:25am    
What happens if you use quality of 100 instead of 80? Or as alternative use directly WebPEncodeLosslessRGBA
Chopin2001 29-May-23 11:30am    
I already tried that. The result was the same, only the file size increased.
Thanks
0x01AA 29-May-23 11:44am    
Sould not be the sequence like this: DecodeJpeg -> WebPEncodeRGBA -> WebPDecodeRGBA?
My wild guess is, that DecodeJpeg adjusts the 'W32 BGRA' to 'WebRGBA' under the hood of 'QImage'.
Dave Kreskowiak 29-May-23 13:41pm    
Not really a C++, or Qt, or WebP expert, but looking at your images, it would seem the image bytes data format is not what is expected by the library. For example, each pixel in your source image could be 4 bytes in RGBA order, and the library may be expecting something like RBGA, or the like.

Or, on the receiving end, when you get the image data back from the library, you're getting it back with the different byte order than your image handling code is expecting.
Chopin2001 29-May-23 17:54pm    
However, it is difficult to see that the colors are distorted because of it.

1 solution

I solve it. I added the following code.
QImage convertedImg = unique_img->convertToFormat(QImage::Format_RGBA8888);

The image format has been converted. And now it works fine.

 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);
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900