Saving byte array in RAW file format

I have a simple program that reads data from a PNG into a 2D array. I would like to save this data in a .RAW file so that Raw Studio or Irfanview can view the original image that my program outputs to my_out.raw. Currently, if I just write raw binary data to my_out.raw file, no application can actually read the file, i.e. view the image. What do I need to do for the program below so that I can see the image?

Code for reading PNG files:

// MAIN.cpp
#include "pngfilereader.h"
#include <string>
#include <vector>

#include <fstream>

int main (int argc, char *argv[])
{
  PNGFileReader pngfr;
  if (!pngfr.decompress_png_to_raw(std::string("/home/matt6809/Downloads"
    "/City.png"))) {
    std::cout << "File decompression error: " << std::endl;
  } else {
    std::ofstream out;
    out.open("./my_out.raw", std::ios_base::out);
    std::vector<std::vector<unsigned char> > data;
    pngfr.get_image_data(data);
    typedef std::vector<std::vector<unsigned char> >::iterator row_it;
    typedef std::vector<unsigned char>::iterator col_it;

    for(row_it rit= data.begin(); rit != data.end(); ++rit) {
      for(col_it cit = rit->begin(); cit != rit->end(); ++cit) {
        out << (*cit);
      }   
    }   
    out << std::endl;
  }
  return 0;
}


#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <png.h>
#include <iostream>
#include <vector>
#include <string>

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 &path);

    // Getters
    long unsigned int get_image_width();
    long unsigned int get_image_height();
    void get_image_data(std::vector<std::vector<unsigned char> > &data);

  private:
    // Helper functions:
    bool read_png(const std::string &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 <stdexcept>

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 < 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 &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<std::vector<unsigned char> > &data)
{
  for (unsigned long int i = 0; i < m_ImageHeight; ++i) {
    std::vector<unsigned char> v;
    data.push_back(v);
    for (unsigned long int j = 0; j < m_ImageWidth; ++j) {
      std::vector<unsigned char> *vp = &data[i];
      vp->push_back(m_Data[i][j]);
    } 
  }
}

// Private Methods
bool PNGFileReader::read_png(const std::string &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->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(&m_pPNG, &m_pPNGInfo, &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->alloc_data();
  png_read_image(m_pPNG, m_Data);

  png_read_end(m_pPNG, NULL);
  png_destroy_read_struct(&m_pPNG, &m_pPNGInfo, &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(&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(&m_pPNG, &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 < 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->free_data();

  m_Data = new png_bytep[m_ImageHeight]();           
  for (unsigned long int i = 0; i < m_ImageHeight; ++i) {
    m_Data[i] = NULL;
  }
  try {
    for (unsigned long int i = 0; i < m_ImageHeight; ++i) {
      m_Data[i] = new png_byte[m_ImageWidth];
    }
  }
  catch (std::bad_alloc e) {
    for (unsigned long int i = 0; i < 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;
}

      

+3


source to share


1 answer


A "raw" file intended for use with camera imaging software such as Raw Studio and Irfraview is not a raw, headerless, binary dump of image data. Instead, the "raw" nickname refers to the fact that the image has the minimum amount of image processing applied in the camera. For example, the image data may still be a single-channel monochrome image from a CFA master camera, or have no white balance, color matrix, etc. In any case, the image data is still formatted in the standard binary file format, complete with a header, data packing method, etc. Examples include formats such as the Adobe DNG file format (which is based on TIFF), or proprietary formats from the camera manufacturers themselves.such as Canon CR2, Nikon NEF, etc.



So, if you want these raw file processing programs to read your "raw" file image data, you will need to read the information about the binary data specifications supported by the raw file format and then reformat the original PNG images correctly.

+4


source







All Articles