Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Encoding an image to webp will distort the colors.
Forum Updated to NodeBB v4.3 + New Features

Encoding an image to webp will distort the colors.

Scheduled Pinned Locked Moved Solved General and Desktop
13 Posts 5 Posters 1.1k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    MyNameIsQt
    wrote on last edited by MyNameIsQt
    #1

    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;
    }
    
    Christian EhrlicherC Pl45m4P 2 Replies Last reply
    0
    • M MyNameIsQt

      @JonB

      qDebug() << unique_img->format();
      

      result:

      QImage::Format_RGB32
      
      SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #10

      @MyNameIsQt said in Encoding an image to webp will distort the colors.:

      @JonB

      qDebug() << unique_img->format();
      

      result:

      QImage::Format_RGB32
      

      Hence your issue. Convert the QImage to the proper format for your encoder.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      M 1 Reply Last reply
      2
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #2

        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

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        M 1 Reply Last reply
        1
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #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.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          M 1 Reply Last reply
          2
          • Christian EhrlicherC Christian Ehrlicher

            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

            M Offline
            M Offline
            MyNameIsQt
            wrote on last edited by
            #4

            @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.

            1 Reply Last reply
            0
            • SGaistS SGaist

              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.

              M Offline
              M Offline
              MyNameIsQt
              wrote on last edited by
              #5

              @SGaist I'm sorry. I don't understand what you're writing.

              JonBJ 1 Reply Last reply
              0
              • M MyNameIsQt

                @SGaist I'm sorry. I don't understand what you're writing.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #6

                @MyNameIsQt
                @SGaist is asking you to put into encodeWebp()

                qDebug() << unique_img->format();
                

                What's that in https://doc.qt.io/qt-6/qimage.html#Format-enum and is it right for WebPEncodeRGBA()?

                M 1 Reply Last reply
                0
                • M MyNameIsQt

                  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;
                  }
                  
                  Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #7

                  @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.

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  M 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @MyNameIsQt
                    @SGaist is asking you to put into encodeWebp()

                    qDebug() << unique_img->format();
                    

                    What's that in https://doc.qt.io/qt-6/qimage.html#Format-enum and is it right for WebPEncodeRGBA()?

                    M Offline
                    M Offline
                    MyNameIsQt
                    wrote on last edited by
                    #8

                    @JonB

                    qDebug() << unique_img->format();
                    

                    result:

                    QImage::Format_RGB32
                    
                    SGaistS 1 Reply Last reply
                    0
                    • Christian EhrlicherC Christian Ehrlicher

                      @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.

                      M Offline
                      M Offline
                      MyNameIsQt
                      wrote on last edited by
                      #9

                      @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.

                      Christian EhrlicherC 1 Reply Last reply
                      0
                      • M MyNameIsQt

                        @JonB

                        qDebug() << unique_img->format();
                        

                        result:

                        QImage::Format_RGB32
                        
                        SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #10

                        @MyNameIsQt said in Encoding an image to webp will distort the colors.:

                        @JonB

                        qDebug() << unique_img->format();
                        

                        result:

                        QImage::Format_RGB32
                        

                        Hence your issue. Convert the QImage to the proper format for your encoder.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        M 1 Reply Last reply
                        2
                        • M MyNameIsQt

                          @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.

                          Christian EhrlicherC Offline
                          Christian EhrlicherC Offline
                          Christian Ehrlicher
                          Lifetime Qt Champion
                          wrote on last edited by Christian Ehrlicher
                          #11

                          @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...

                          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                          Visit the Qt Academy at https://academy.qt.io/catalog

                          1 Reply Last reply
                          0
                          • M MyNameIsQt

                            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;
                            }
                            
                            Pl45m4P Offline
                            Pl45m4P Offline
                            Pl45m4
                            wrote on last edited by Pl45m4
                            #12

                            @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].


                            If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                            ~E. W. Dijkstra

                            1 Reply Last reply
                            2
                            • SGaistS SGaist

                              @MyNameIsQt said in Encoding an image to webp will distort the colors.:

                              @JonB

                              qDebug() << unique_img->format();
                              

                              result:

                              QImage::Format_RGB32
                              

                              Hence your issue. Convert the QImage to the proper format for your encoder.

                              M Offline
                              M Offline
                              MyNameIsQt
                              wrote on last edited by MyNameIsQt
                              #13

                              @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);
                              
                              
                              1 Reply Last reply
                              1
                              • M MyNameIsQt has marked this topic as solved on

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved