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.2k 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.
  • 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