title: Saving Byte Array to a RAW file format
body: <p>I have a simple program that reads data from a PNG into a 2D array. I would like to save that data to a .RAW file so that <a href="http://rawstudio.org/" rel="nofollow">Raw Studio</a> or <a href="http://www.irfanview.com/" rel="nofollow">Irfanview</a> can view the raw image that my program outputs to my_out.raw. Currently if I just write the raw binary data to the my_out.raw file, neither application can actually read the file, that is view the image. What do I need to do to the program below so that I can see the image? </p>
  
  <p>The code to read the PNG files is:</p>
  
  <pre><code>// MAIN.cpp
  #include "pngfilereader.h"
  #include &lt;string&gt;
  #include &lt;vector&gt;
  
  #include &lt;fstream&gt;
  
  int main (int argc, char *argv[])
  {
    PNGFileReader pngfr;
    if (!pngfr.decompress_png_to_raw(std::string("/home/matt6809/Downloads"
      "/City.png"))) {
      std::cout &lt;&lt; "File decompression error: " &lt;&lt; std::endl;
    } else {
      std::ofstream out;
      out.open("./my_out.raw", std::ios_base::out);
      std::vector&lt;std::vector&lt;unsigned char&gt; &gt; data;
      pngfr.get_image_data(data);
      typedef std::vector&lt;std::vector&lt;unsigned char&gt; &gt;::iterator row_it;
      typedef std::vector&lt;unsigned char&gt;::iterator col_it;
  
      for(row_it rit= data.begin(); rit != data.end(); ++rit) {
        for(col_it cit = rit-&gt;begin(); cit != rit-&gt;end(); ++cit) {
          out &lt;&lt; (*cit);
        }   
      }   
      out &lt;&lt; std::endl;
    }
    return 0;
  }
  
  
  #include &lt;stdint.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;png.h&gt;
  #include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;string&gt;
  
  class PNGFileReader
  {
    public:
      PNGFileReader();
      ~PNGFileReader();
      // Public exposed API:
      bool compress_raw_to_png(uint8_t data, int size);
      bool decompress_png_to_raw(const std::string &amp;path);
  
      // Getters
      long unsigned int get_image_width();
      long unsigned int get_image_height();
      void get_image_data(std::vector&lt;std::vector&lt;unsigned char&gt; &gt; &amp;data);
  
    private:
      // Helper functions:
      bool read_png(const std::string &amp;path);
      bool create_png_structs(FILE *fp);
      bool free_data();
      bool alloc_data();
  
      // Member variables:
      png_structp m_pPNG;
      png_infop m_pPNGInfo;
      png_infop m_pPNGEndInfo;
      png_bytepp m_Data;
      long unsigned int m_ImageWidth;
      long unsigned int m_ImageHeight;
  
      // Enums
      enum PNGBOOL {NOT_PNG, PNG};
      enum PNGERRORS {ERROR, SUCCESS};
  };
  
  
  #include "pngfilereader.h"
  #include &lt;stdexcept&gt;
  
  PNGFileReader::PNGFileReader() :
    m_pPNG(NULL),
    m_pPNGInfo(NULL),
    m_pPNGEndInfo(NULL),
    m_Data(NULL),
    m_ImageWidth(0),
    m_ImageHeight(0)
  {
  }
  
  PNGFileReader::~PNGFileReader()
  {
    for (unsigned long int i = 0; i &lt; m_ImageHeight; ++i) {
      if (m_Data[i]) {
        delete m_Data[i];
        m_Data[i] = NULL;
      }   
    }
    if (m_Data) {
      delete m_Data;
      m_Data = NULL;
    }
  }
  
  // Public Exposed API
  bool PNGFileReader::compress_raw_to_png(uint8_t m_Data, int size)
  {
    return PNGFileReader::SUCCESS;
  }
  
  bool PNGFileReader::decompress_png_to_raw(const std::string &amp;path)
  {
    return read_png(path);
  }
  
  // Getters
  long unsigned int PNGFileReader::get_image_width()
  {
    return m_ImageWidth;
  }
  
  long unsigned int PNGFileReader::get_image_height()
  {
    return m_ImageHeight;
  }
  
  void PNGFileReader::get_image_data(
    std::vector&lt;std::vector&lt;unsigned char&gt; &gt; &amp;data)
  {
    for (unsigned long int i = 0; i &lt; m_ImageHeight; ++i) {
      std::vector&lt;unsigned char&gt; v;
      data.push_back(v);
      for (unsigned long int j = 0; j &lt; m_ImageWidth; ++j) {
        std::vector&lt;unsigned char&gt; *vp = &amp;data[i];
        vp-&gt;push_back(m_Data[i][j]);
      } 
    }
  }
  
  // Private Methods
  bool PNGFileReader::read_png(const std::string &amp;path)
  {
    /* 
     * Open up the file to read (path) in binary mode
     * first so that if anything goes wrong with libpng
     * we won't have much to undo
     */
    const char *c_path = path.c_str();
    FILE *fp = fopen(c_path, "rb");
    if (!fp)
      return PNGFileReader::ERROR;
  
    /*
     * Read the first BYTES_TO_READ bytes from file
     * then determine if it is a png file or 
     * not. If png_sig_cmp == 0 all is okay
     */
    enum {BYTES_TO_READ = 8};
    unsigned char sig[BYTES_TO_READ];
    if (!fread(sig, 1, BYTES_TO_READ, fp)) {
      fclose(fp);
      return PNGFileReader::ERROR;
    }
  
    bool is_png = !png_sig_cmp(sig, 0, BYTES_TO_READ);
    if (!is_png) {
      fclose(fp);
      return PNGFileReader::ERROR;   
    }
  
    if (!this-&gt;create_png_structs(fp)) {
      fclose(fp);
      return PNGFileReader::ERROR;
    }
  
    /*
     * For error handling purposes. Set a long pointer
     * back to this function to handle all error related
     * to file IO
     */
    if (setjmp(png_jmpbuf(m_pPNG)))
    {
      png_destroy_read_struct(&amp;m_pPNG, &amp;m_pPNGInfo, &amp;m_pPNGEndInfo);
      fclose(fp);
      return PNGFileReader::ERROR;
    }
  
    /* 
     * Set up the input code for FILE openend in binary mode,
     * and tell libpng we have already read BYTES_TO_READ btyes from 
     * signature
     */
    png_init_io(m_pPNG, fp);
    png_set_sig_bytes(m_pPNG, BYTES_TO_READ);
  
    /*
     * Using the lowlevel interface to lib png ...
     */
    png_read_info(m_pPNG, m_pPNGInfo);
    m_ImageHeight = png_get_image_height(m_pPNG, m_pPNGInfo);
    m_ImageWidth = png_get_rowbytes(m_pPNG, m_pPNGInfo);
    this-&gt;alloc_data();
    png_read_image(m_pPNG, m_Data);
  
    png_read_end(m_pPNG, NULL);
    png_destroy_read_struct(&amp;m_pPNG, &amp;m_pPNGInfo, &amp;m_pPNGEndInfo);
    fclose(fp);
  
    return PNGFileReader::SUCCESS;
  }
  
  bool PNGFileReader::create_png_structs(FILE *fp)
  {
    /* 
     * Create the pointer to main libpng struct, as well as
     * two info structs to maintain information after, and
     * prior to all operations on png m_Data. Only necessary
     * to release resource after function succeeds.
     */
    m_pPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
      NULL, NULL);
    if (!m_pPNG)
    {
      fclose(fp);
      return PNGFileReader::ERROR;
    }
    m_pPNGInfo = png_create_info_struct(m_pPNG);
    if (!m_pPNGInfo)
    {
      png_destroy_read_struct(&amp;m_pPNG, (png_infopp)NULL,(png_infopp)NULL);
      fclose(fp);
      return PNGFileReader::ERROR;
    }
    m_pPNGEndInfo = png_create_info_struct(m_pPNG);
    if (!m_pPNGEndInfo)
    {
      png_destroy_read_struct(&amp;m_pPNG, &amp;m_pPNGInfo, (png_infopp)NULL);
      fclose(fp);
      return PNGFileReader::ERROR;
    }
    return PNGFileReader::SUCCESS;
  }
  
  bool PNGFileReader::free_data()
  {
    if (m_ImageHeight == 0 || m_ImageWidth == 0)
      return PNGFileReader::ERROR;
  
    for (unsigned long int i = 0; i &lt; m_ImageHeight; ++i) {
      if (m_Data[i]) {
        delete m_Data[i];
        m_Data[i] = NULL;
      }
    }
    if (m_Data) {
      delete m_Data;
      m_Data = NULL;
    }
    return PNGFileReader::SUCCESS;
  }
  
  bool PNGFileReader::alloc_data()
  {
    if (m_ImageHeight == 0 || m_ImageWidth == 0)
      return PNGFileReader::ERROR;
  
    if (m_Data != NULL)
      this-&gt;free_data();
  
    m_Data = new png_bytep[m_ImageHeight]();           
    for (unsigned long int i = 0; i &lt; m_ImageHeight; ++i) {
      m_Data[i] = NULL;
    }
    try {
      for (unsigned long int i = 0; i &lt; m_ImageHeight; ++i) {
        m_Data[i] = new png_byte[m_ImageWidth];
      }
    }
    catch (std::bad_alloc e) {
      for (unsigned long int i = 0; i &lt; m_ImageHeight; ++i) {
        if (m_Data[i]) {
          delete m_Data[i];
          m_Data[i] = NULL;
        }
      }
      if (m_Data) {
        delete m_Data;
        m_Data = NULL;
      }
      throw e;
    }
  
    return PNGFileReader::SUCCESS;
  }
  </code></pre>