2014-03-31 47 views
3

我想在vs2013中使用libpng 1.2.10讀取png文件。我下載了最新的zlib並編譯了pnglib,它運行良好。現在,我試圖加載文件:libpng在png_read_info()上崩潰

int *w = &width; 
int *h = &height; 
const char* name = file.c_str(); 
FILE *png_file = fopen(name, "rb"); 
if (!png_file) 
{ 
    std::cerr << "Could not open " + file << std::endl; 
    return; 
} 

unsigned char header[PNG_SIG_BYTES]; 

fread(header, 1, PNG_SIG_BYTES, png_file); 
if (png_sig_cmp(header, 0, PNG_SIG_BYTES)) 
{ 
    std::cerr << "PNG signature fail " + file << std::endl; 
    return; 
} 

png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 
if(png_ptr == NULL) 
{ 
    std::cerr << "PNG read fail " + file << std::endl; 
    return; 
} 
png_infop info_ptr = png_create_info_struct(png_ptr); 
if(!info_ptr) 
{ 
    std::cerr << "PNG info fail " + file << std::endl; 
    return; 
} 
png_infop end_info = png_create_info_struct(png_ptr); 
if(!end_info) 
{ 
    std::cerr << "PNG info end fail " + file << std::endl; 
    return; 
} 
if (setjmp(png_jmpbuf(png_ptr))) 
{ 
    std::cerr << "PNG setjmp fail " + file << std::endl; 
    return; 
} 
png_init_io(png_ptr, png_file); 
png_set_sig_bytes(png_ptr, PNG_SIG_BYTES); 
png_read_info(png_ptr, info_ptr); 

*w = png_get_image_width(png_ptr, info_ptr); 
*h = png_get_image_height(png_ptr, info_ptr); 

png_uint_32 bit_depth, color_type; 
bit_depth = png_get_bit_depth(png_ptr, info_ptr); 
color_type = png_get_color_type(png_ptr, info_ptr); 

if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) 
{ 
    std::cerr << "Grayscale PNG not supported " + file << std::endl; 
    return; 
} 

if (bit_depth == 16) 
    png_set_strip_16(png_ptr); 

if (color_type == PNG_COLOR_TYPE_PALETTE) 
    png_set_palette_to_rgb(png_ptr); 
else if (color_type == PNG_COLOR_TYPE_GRAY || 
    color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 
{ 
    png_set_gray_to_rgb(png_ptr); 
} 

if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 
    png_set_tRNS_to_alpha(png_ptr); 
else 
    png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); 

png_read_update_info(png_ptr, info_ptr); 

png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr); 
png_uint_32 numbytes = rowbytes*(height); 
png_byte* pixels = (png_byte*)malloc(numbytes); 
png_byte** row_ptrs = (png_byte**)malloc((height)* sizeof(png_byte*)); 

int i; 
for (i = 0; i<height; i++) 
    row_ptrs[i] = pixels + (height - 1 - i)*rowbytes; 

png_read_image(png_ptr, row_ptrs); 

free(row_ptrs); 
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 
fclose(png_file); 

//return (char *)pixels; 

Create(*w, *h, 4, pixels, GL_UNSIGNED_BYTE); 

不幸的是,我得到

未處理的異常在0x77D78E19(ntdll.dll中)在SimpleShader.exe:0000005:訪問衝突寫入位置0x00000014。

上線

png_read_info(png_ptr, info_ptr); 

具體發生錯誤的位置:

#ifdef PNG_STDIO_SUPPORTED 
/* This is the function that does the actual reading of data. If you are 
* not reading from a standard C stream, you should create a replacement 
* read_data function and use it at run time with png_set_read_fn(), rather 
* than changing the library. 
*/ 
void PNGCBAPI 
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) 
{ 
    png_size_t check; 

    if (png_ptr == NULL) 
     return; 

    /* fread() returns 0 on error, so it is OK to store this in a png_size_t 
    * instead of an int, which is what fread() actually returns. 
    */ 
    check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); // <---------- ERROR HERE 

    if (check != length) 
     png_error(png_ptr, "Read Error"); 
} 
#endif 

可能是什麼問題呢?

編輯:好的,它不會崩潰當我編譯libpng和我的項目在發佈模式。我需要運行我的項目在調試模式,雖然...

+0

libpng-1.2.10?哇,那是古老的(2006年4月)。傳統libpng-1.2分支中的當前版本是1.2.51。你可以試試1.2.51或1.6.10版本嗎? –

+0

裝飾「PNGCBAPI」直到libpng-1.5.0纔出現,所以你不能在看libpng-1.2.10。 –

回答

4

這是由libpng和您的項目之間的編譯器設置不匹配造成的。特別是,運行時庫設置,那必須是libpng和你的項目中的多線程DLL(/ MD)。自述狀態:

如果不使用Visual Studio的默認應用程序仍必須建立 使用默認運行選項(/ MD)。如果由於某種原因,它是不那麼你的應用程序 會盡快裏面崩潰libpng16.dll作爲的libpng試圖從你在傳遞一個文件句柄讀 。

的simpliest方式,以避免崩潰,並保留調試的可能性是複製項目中的「發佈」配置並更改一些屬性,以便在Visual Studio中輕鬆進行調試。以下是如何操作:

  1. 單擊項目 - >屬性 - >配置管理器 - >展開活動解決方案配置並單擊RMB。從發佈中選擇一個新名稱並複製設置。
  2. 現在,在項目設置中,挑選新創建的配置和更改以下屬性:
    • C/C++ - >常規 - >調試信息格式:用於編輯和程序數據庫繼續(/ ZI)
    • C/C++ - >優化 - >優化:禁用(/ OD),全程序優化:沒有
    • 這纔是最必要的。您還可以禁用鏈接器優化(引用和COMDAT摺疊),啓用最少的重建等。

就是這樣,祝你好運!