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