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. Convert Webp to 'base64'
Forum Updated to NodeBB v4.3 + New Features

Convert Webp to 'base64'

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 2 Posters 711 Views
  • 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

    The following code reads webp data saved as binary from node.js and draws it on the canvas in js.
    This works perfectly.

    //node.js
    const buffer = Buffer.allic(dataSize);
    fs.readSynd(fd, buffer, 0, dataSize, dataAddress);
    
    // js
    var img = new Image();
            img.src = "data:image/webp;base64," + imageData;
    
    img.onload = function() {
               canvas.width = img.width;
                canvas.height = img.height;
    
                context.fillStyle = "#d4d4d4";
                context.fillRect(0, 0, canvas.width, canvas.height);
    
                context.drawImage(img, 0, 0, img.width, img.height);
            };
    

    I want to run this in a qt desktop application. This is sending data saved in c++ via qtchannel to js for display.

    class CBackground
    {
    private:
    uint8_t* m_decodedData;
     ... 
    }
    
    // cpp
    //encode webp
    unsigned long 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");
        }
    
        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);
    
        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;
        SetType(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);
    
        cout << getImageAddress() << "\t" << m_bkgndHeader.ImageSize << endl;
        return m_bkgndHeader.ImageSize;
    }
    
    //decode webp
    bool CBackgroundr::decodeWebp(QFile *pFile)
    {
        long imageSize = getImageSize();
        long imageAddress = getImageAddress();
    
        if (!pFile->seek(imageAddress)) {
            throw std::runtime_error("Failed to seek to image data");
            return false;
        }
    
        // read webp data from file
        QByteArray imageData(imageSize, 0);
        if (pFile->read(imageData.data(), imageSize) != imageSize) {
            throw std::runtime_error("Failed to read image data");
            return false;
        }
    
        qDebug() << "imageSize: 1 " << imageSize;
        int width = 0, height = 0;
        m_decodedData = WebPDecodeRGBA(reinterpret_cast<uchar*>(imageData.data()), imageSize, &width, &height);
        if (!m_decodedData) {
            throw std::runtime_error("Failed to decode WebP image");
            return false;
        }
      
        m_imageSize = width * height * 4;
        return true; 
    }
    
    QString Wemar::getImgObject()
    {
        if (m_pBkgnd && m_pBkgnd->loadImageData(m_file)){
            const uchar* decodedData = m_pBkgnd->getDecodedData();
            int imageSize = m_pBkgnd->getImageSize();
    
            QByteArray byteArray(reinterpret_cast<const char*>(decodedData), imageSize);
    
            QString base64ImageData = QString::fromLatin1(byteArray.toBase64());
    
            qDebug() << "base64:  " << base64ImageData.sliced(0,50);
    
            return base64ImageData;
        } else {
            qDebug() << "error: m_pBkgnd is null";
            return QString();
        }
    }
    

    This doesn't work. The canvas doesn't display anything.

          var img = new Image();
            imageData = getData();
            img.src = "data:image/webp;base64," + imageData;
    
            img.onerror = function(){
                console.error("Image failed to load");
            };
    
            img.onload = function() {
               canvas.width = img.width;
                canvas.height = img.height;
    
                context.fillStyle = "#d4d4d4";
                context.fillRect(0, 0, canvas.width, canvas.height);
    
                context.drawImage(img, 0, 0, img.width, img.height);
            };
    

    Result is "Image failed to load";
    The output of the next line is:

            qDebug() << "base64  " << base64ImageData.sliced(0,50);
    

    result is (data name: test01)

    string:  "ExEP/wcFBP8CAAD/AwEA/wMBAP8DAQD/AwEA/wQAAP8NAQP/EQ"
    

    The following is the first part of base64 when the data sent from node.js to the client is normally displayed on the canvas.
    (same image. )

    UklGRv6TAABXRUJQVlA4IPKTAACwDAKdASpYAosBPm0wk0ckIyGmqdbrcNANiWNtGcADeCFZFvD6PaAggNNkUsW/HcD3vl6ce+HP1T8ZyqVw+du9x/2/XD5kPQl86fmi9Iv/PerU9HLzXPWxxw6Xn559zPDX84+z/1/+F/0H/R/yfza/wmW/4r/S8zP6D+Sf6X+Q9wX+B+1PkL86NQv80/p3+y/vvtifpduFcT/yeoR7zfdv+5/mvZM/Q84P5L/eewF+wnGE+wewL/VP
    
    

    another one (different image) normal output

    UklGRuoOAQBXRUJQVlA4IN4OAQCQtQSdASqEA4QDPm0ylUikIqcoItGboQANiWltNAiIevQvxsFxL2/0xWeQzx5CeGdieeDYlwaDorO40GY3g3l1fxm8mfxX/R9gDjk6CPm10jv+nyhCa6rf/X4DzGZX/t/ovXy5L/NI7+gh1lml8z3kn3B+o//f+oB+jH+Q/l/ZB8xnm79IB/M/7h64P/L9p7+uf9L2Ff169bb/3/uB8SH9s/0f7Ee0b/988u8qvzv+1/535W/vD7P/n/ui+4H+O/8n1iYb
    

    I am converting data from c++ to another format to send it to js. During this process, I am not getting an accurate base64 string. I would like to know how I can get an uncorrupted Base64 string. What went wrong?

    1 Reply Last reply
    0
    • M Offline
      M Offline
      MyNameIsQt
      wrote on last edited by
      #4

      Solved.
      After looking for the answer, the code became really simple.

      bool CBackground::decodeWebp(QFile *pFile)
      {
          long imageSize = getImageSize();
          long imageAddress = getImageAddress();
      
          if (!pFile->seek(imageAddress)) {
              throw std::runtime_error("Failed to seek to image data");
              return false;
          }
      
          QByteArray decodedArray(imageSize, 0);
          if (pFile->read(decodedArray.data(), imageSize) != imageSize) {
              throw std::runtime_error("Failed to read image data");
              return false;
          }
      
          m_base64ImageData = decodedArray.toBase64();
          return true;
      }
      
      / 
      QString Wemar::getImgObject()
      {
          if (m_pBkgnd && m_pBkgnd->loadImageData(m_file)){
              qDebug() << "m_pBkgnd is good";
              return m_pBkgnd->getBase64ImageData();
          } else {
              qDebug() << "error: m_pBkgnd is null";
              return QString();
          }
      }
      
      1 Reply Last reply
      0
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #2

        What's the difference to https://forum.qt.io/topic/159059 ?
        Why do you use webp decoding stuff instead simply letting QImage read/write the webp images? Why do you need webp in the first place? And why the same question again??

        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
        • Christian EhrlicherC Christian Ehrlicher

          What's the difference to https://forum.qt.io/topic/159059 ?
          Why do you use webp decoding stuff instead simply letting QImage read/write the webp images? Why do you need webp in the first place? And why the same question again??

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

          @Christian-Ehrlicher
          (As you know, English is not my language. Please understand this even if the language is difficult.)
          First of all, this is the same question as the link you provided, but I'm looking for a different way to solve the problem. I'm approaching the problem in a new way. This makes a big difference.

          It's been a while since I posted the question, so editing it seemed pointless. So I made a new one.

          The reason I use webp is because the compression rate is 1/3 better than when compressed with jpeg.
          Users create files through this program and upload them to the server for use. Then file size becomes an important issue.

          So I used webp.
          For example, if you upload 10,000 files, there is quite a bit of space available for storage. The same applies to the amount of transfers sent to the server.

          When operating a server, you know that both physical space and transmission volume are expensive.

          Thanks

          1 Reply Last reply
          0
          • M Offline
            M Offline
            MyNameIsQt
            wrote on last edited by
            #4

            Solved.
            After looking for the answer, the code became really simple.

            bool CBackground::decodeWebp(QFile *pFile)
            {
                long imageSize = getImageSize();
                long imageAddress = getImageAddress();
            
                if (!pFile->seek(imageAddress)) {
                    throw std::runtime_error("Failed to seek to image data");
                    return false;
                }
            
                QByteArray decodedArray(imageSize, 0);
                if (pFile->read(decodedArray.data(), imageSize) != imageSize) {
                    throw std::runtime_error("Failed to read image data");
                    return false;
                }
            
                m_base64ImageData = decodedArray.toBase64();
                return true;
            }
            
            / 
            QString Wemar::getImgObject()
            {
                if (m_pBkgnd && m_pBkgnd->loadImageData(m_file)){
                    qDebug() << "m_pBkgnd is good";
                    return m_pBkgnd->getBase64ImageData();
                } else {
                    qDebug() << "error: m_pBkgnd is null";
                    return QString();
                }
            }
            
            1 Reply Last reply
            0
            • 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