2012-03-30 2 views
3

PNG의 데이터를 2D 배열로 읽는 간단한 프로그램이 있습니다. 그 데이터를 .RAW 파일에 저장하여 Raw Studio 또는 Irfanview이 내 프로그램에서 my_out.raw로 출력하는 원시 이미지를 볼 수 있습니다. 현재 원시 이진 데이터를 my_out.raw 파일에 쓰는 경우 두 응용 프로그램 모두 실제로 파일을 읽을 수는 있지만 이미지를 볼 수는 없습니다. 이미지를 볼 수 있도록하기 위해 아래 프로그램에서해야 할 일은 무엇입니까?바이트 배열을 RAW 파일 형식으로 저장

코드 PNG 파일을 읽을 수는 다음과 같습니다

// 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

귀하의 질문에 대한 명확한 답변을 드릴 수 있습니까? –

+0

@ George Skoptsov 편집이 완료되면 추가 설명이 필요하면 알려주세요. –

답변

4

원시 스튜디오와 Irfraview 같은 카메라 이미지 처리 프로그램을 사용하기위한 것입니다 A "원시"파일이 원시 이진 덤프하지 않습니다 헤더가없는 이미지 데이터의 대신 "원시"모니 커는 이미지에 최소한의 양의 이미지 처리가 적용된 카메라를 말합니다. 예를 들어, 이미지 데이터는 여전히 카메라의 베이어 패턴 CFA로부터의 단일 채널 단색 이미지이거나, 화이트 밸런스, 컬러 매트릭스 등이 적용되지 않았을 수 있습니다. 어느 쪽이든, 이미지 데이터는 데이터 포장 방법 등이 포함 된 표준 바이너리 이미지 파일 형식으로 포맷됩니다. Adobe의 DNG 파일 형식 (TIFF 기반) 또는 Canon의 CR2와 같은 카메라 제조업체의 독점 형식과 같은 형식이 포함됩니다. 니콘의 NEF 등

이러한 원시 파일 처리 프로그램에서 원시 파일 이미지 데이터를 읽으려면 바이너리 데이터 사양에서 지원하는 원시 파일 형식을 읽어야합니다. 원본 PNG 이미지 데이터를 올바르게 다시 포맷하십시오.

관련 문제