Search code examples
imageboostboost-gil

Boost GIL: Write an image into a memory buffer


In my application I periodically receive an 8 bit gray scale image as array of uint8_t. I need to convert it in a jpeg (or png) format and send the result to another library. Unfortunately I cannot continuously write a file on the hard drive so I need to handle the jpeg (or png) as a memory buffer.

I'm using Boost library v1.74 and Boost.GIL should fit my case: reading this docs at the section "Reading And Writing In-Memory Buffers" seems boost::gil::write_view(...) can also write into a memory buffer but unfortunately the buffer returns empty. What am I doing wrong? (Please see the code below)

#include <iostream>
#include <fstream>
#include <vector>
#include <array>
#include <boost/gil/extension/io/jpeg.hpp>

//[...]

uint8_t img[]; // conteins an image formatted as gray8_pixel_t 
int width;     // image width
int height;    // image height

//[...]

  boost::gil::gray8c_view_t src = interleaved_view(
                                      width, 
                                      height, 
                                      (const boost::gil::gray8_pixel_t *) vis_img, 
                                      width);  
  // Write the grayscale view in a file: it works like a charm :)
  boost::gil::write_view("out.jpg", src, boost::gil::jpeg_tag());

  // Write the grayscale view in a memory buffer: out_buffer seems empty :| 
  std::stringstream out_buffer(std::ios::in | std::ios::binary);
  boost::gil::write_view(out_buffer, src, boost::gil::jpeg_tag());

  /******  check out_buffer ******/

  // check the size of out_buffer 
  out_buffer.seekg(0, std::ios::end);
  int size = out_buffer.tellg();
  out_buffer.seekg(0, out_buffer.beg);
  
  // try to write out_buffer in a file
  std::ofstream output("myfile.jpg", std::ios::binary);
  output << out_buffer.rdbuf();  
  output.close();

Solution

  • Your stream is not an output stream:

    std::stringstream out_buffer(std::ios::in | std::ios::binary);
    

    Fix it, e.g.

    #include <boost/gil/extension/io/jpeg.hpp>
    #include <fstream>
    #include <iostream>
    #include <sstream>
    
    namespace gil = boost::gil;
    
    int main() {
        uint8_t img[300 * 200]{}; // contains an image formatted as gray8_pixel_t
        int     width  = 300;     // image width
        int     height = 200;     // image height
    
        gil::gray8c_view_t src =
            interleaved_view(width, height, reinterpret_cast<gil::gray8_pixel_t const*>(img), width);
    
        std::stringstream ss;
        write_view(ss, src, gil::jpeg_tag());
    
        //std::cout << "out_buffer size :" << ss.str().size() << "\n";
    
        std::ofstream("myfile.jpg", std::ios::binary) << ss.rdbuf();
    }