2012-03-30 14 views
3

Ich habe ein einfaches Programm, das Daten von einem PNG in ein 2D-Array liest. Ich möchte diese Daten in einer .RAW-Datei speichern, so dass Raw Studio oder Irfanview das unbearbeitete Bild anzeigen kann, das mein Programm an my_out.raw ausgibt. Derzeit, wenn ich nur die rohen Binärdaten in die Datei my_out.raw schreibe, kann keine Anwendung die Datei tatsächlich lesen, dh das Bild anzeigen. Was muss ich mit dem Programm unten tun, damit ich das Bild sehen kann?Byte-Array in ein RAW-Dateiformat speichern

Der Code, um die PNG-Dateien zu lesen ist:

// 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; 
} 
+0

Können Sie Ihren Beitrag so umschreiben, dass klar ist, was Ihre Frage ist? –

+0

@George Skoptsov Bearbeitungen erfolgen, bitte lassen Sie mich wissen, wenn es weitere Erläuterungen benötigt. –

Antwort

4

A "raw" Datei, die mit einer Kamera-Bildverarbeitungsprogramm wie Raw Studio und Irfraview werden soll, verwendet wird, ist kein Roh-Binär-Dump der Bilddaten ohne Header. Stattdessen bezieht sich der "rohe" Moniker auf die Tatsache, dass das Bild eine minimale Menge an Bildverarbeitung aufweist, die in der Kamera angewendet wird. Zum Beispiel können die Bilddaten immer noch ein einkanaliges monochromes Bild aus dem Bayer-Muster CFA der Kamera sein, oder es wurde kein Weißabgleich, keine Farbmatrix usw. angewendet. In jedem Fall sind die Bilddaten weiterhin formatiert in einem Standard-Binärbild-Dateiformat, komplett mit einer Kopfzeile, Datenpackungsmethode usw. Beispiele umfassen Formate wie das DNG-Dateiformat von Adobe (das auf TIFF basiert) oder proprietäre Formate von Kameraherstellern wie CR2 von Canon, Nikon's NEF, etc.

Wenn Sie also wollen, dass diese Rohdatenverarbeitungsprogramme Ihre "rohen" Dateiabbilddaten lesen, müssen Sie die binären Datenspezifikationen über die Rohdateiformate, die sie unterstützen, lesen. und formatieren Sie dann die ursprünglichen PNG-Bilddaten korrekt neu.