一:libpng庫的編譯
環境:windows10 + VS2013
需要下載:libpng, zlib兩個庫
下載地址:
libpng:http://libmng.com/pub/png/libpng.html
zlib:http://www.zlib.net/
注意事項:
libpng, zlib解壓后放到同一目錄,
打開ibpng目錄下的projects\vstudio中的工程文件,編譯運行
在輸出目錄(Debug或Realse)中得到輸出文件libpng16.dll、libpng16.lib、zlib.lib
問題:
libpng, zlib版本問題導致編譯時提示找不到zlib,修改配置文件中zlib信息即可
二,VS2013使用libpng,zlib庫:
1. C/C++常規->附加包含目錄中把包含png.h等頭文件的目錄加進來
2. 鏈接器->輸入->附加依賴項中加zlib.lib;libpng.lib。
3.通用屬性->VC++ 目錄->庫目錄中把放着zlib.lib和libpng.lib的目錄加進來。
三,png圖片格式:
參數較多,其中重要信息:IHDR(文件頭),IDAT(圖像數據塊),IEND(圖像結束數據)
文件頭里最重要的數據信息:
Width:圖像寬度,以像素為單位
Height:圖像高度,以像素為單位
ColorType:RGB格式或RGBA格式
圖像數據塊:
圖片對應的像素點有多個參數,RGB或RGBA,
對某個像素操作需要有3個(RGB)或4個(RGBA)數據
詳細png格式說明:
http://www.360doc.com/content/11/0428/12/1016783_112894280.shtml
四,VS下利用libpng的簡單讀寫操作(代碼稍加改動可執行):
寫png圖片:write_png.c

1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include <stdio.h> 4 #include <math.h> 5 #include <malloc.h> 6 #include <png.h> 7 8 9 // This function actually writes out the PNG image file. The string 'title' is 10 // also written into the image file 11 int writeImage(char* filename, int width, int height, char* title); 12 13 14 /* 15 fun: 根據寬,高,標題將每個像素的RGB值在指定路徑生成png文件 16 return: int型,0表示正確,1表示出錯 17 arg[0]: filename,生成的文件名字 18 arg[1]: width,圖片寬 19 arg[2]: height,圖片高 20 arg[3]: title,標題 21 */ 22 int writeImage(char* filename, int width, int height, char* title) 23 { 24 int code = 0; 25 FILE *fp = NULL; 26 png_structp png_ptr = NULL; 27 png_infop info_ptr = NULL; 28 png_bytep row = NULL; 29 30 // Open file for writing (binary mode) 31 fp = fopen(filename, "wb"); 32 if (fp == NULL) { 33 fprintf(stderr, "Could not open file %s for writing\n", filename); 34 code = 1; 35 goto finalise; 36 } 37 38 // Initialize write structure 39 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 40 if (png_ptr == NULL) { 41 fprintf(stderr, "Could not allocate write struct\n"); 42 code = 1; 43 goto finalise; 44 } 45 46 // Initialize info structure 47 info_ptr = png_create_info_struct(png_ptr); 48 if (info_ptr == NULL) { 49 fprintf(stderr, "Could not allocate info struct\n"); 50 code = 1; 51 goto finalise; 52 } 53 54 // Setup Exception handling 55 if (setjmp(png_jmpbuf(png_ptr))) { 56 fprintf(stderr, "Error during png creation\n"); 57 code = 1; 58 goto finalise; 59 } 60 61 png_init_io(png_ptr, fp); 62 63 // Write header (8 bit colour depth) 64 png_set_IHDR(png_ptr, info_ptr, width, height, 65 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, 66 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 67 68 // Set title 69 if (title != NULL) { 70 png_text title_text; 71 title_text.compression = PNG_TEXT_COMPRESSION_NONE; 72 title_text.key = "Title"; 73 title_text.text = title; 74 png_set_text(png_ptr, info_ptr, &title_text, 1); 75 } 76 77 png_write_info(png_ptr, info_ptr); 78 79 // Allocate memory for one row (3 bytes per pixel - RGB) 80 row = (png_bytep)malloc(3 * width * sizeof(png_byte)); 81 82 // Write image data 83 int x, y; 84 85 for (y = 0; y<height; y++) { 86 for (x = 0; x<width; x++) { 87 if (x == 0 || x == (width - 1) || y == 0 || y == (height - 1)) 88 { 89 row[x * 3 + 0] = 0x00; 90 row[x * 3 + 1] = 0x00; 91 row[x * 3 + 2] = 0x00; 92 } 93 else 94 { 95 row[x * 3 + 0] = 0x00; 96 row[x * 3 + 1] = 0x00; 97 row[x * 3 + 2] = 0xff; 98 } 99 } 100 png_write_row(png_ptr, row); 101 } 102 103 // End write 104 png_write_end(png_ptr, NULL); 105 106 finalise: 107 if (fp != NULL) fclose(fp); 108 if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); 109 if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); 110 if (row != NULL) free(row); 111 112 return code; 113 } 114 115 116 int main(int argc, char *argv[]) 117 { 118 // Make sure that the output filename argument has been provided 119 if (argc != 2) { 120 fprintf(stderr, "Please specify output file\n"); 121 return 1; 122 } 123 124 // Specify an output image size 125 int width = 50; 126 int height = 50; 127 128 // Save the image to a PNG file 129 // The 'title' string is stored as part of the PNG file 130 printf("Saving PNG\n"); 131 int result = writeImage(argv[1], width, height, "This is my test image"); 132 if (result) 133 { 134 printf("Saving err\n"); 135 } 136 137 //// Free up the memorty used to store the image 138 //free(buffer); 139 140 return result; 141 }
生成的一張簡單png圖片,50*50邊緣1像素黑框,中間藍色:
讀png圖片:read_png.cpp

1 #define _CRT_SECURE_NO_WARNINGS 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string> 6 7 #include <png.h> 8 #define PNG_BYTES_TO_CHECK 4 9 10 /* 11 fun: 讀取文件名為filepath的png文件 12 return: png_bytep類型的buff,即數據域 13 arg[0]: filepath,文件名 14 arg[1]: width,圖像寬度 15 arg[2]: height,圖像高度 16 */ 17 png_bytep load_png_image(const char *filepath, int *width, int *height) 18 { 19 FILE *fp; 20 png_structp png_ptr; 21 png_infop info_ptr; 22 png_bytep* row_pointers; 23 char buf[PNG_BYTES_TO_CHECK]; 24 int w, h, x, y, temp, color_type; 25 26 fp = fopen(filepath, "rb"); 27 if (fp == NULL) { 28 printf("load_png_image err:fp == NULL"); 29 return 0; 30 } 31 32 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); 33 info_ptr = png_create_info_struct(png_ptr); 34 35 setjmp(png_jmpbuf(png_ptr)); 36 /* 讀取PNG_BYTES_TO_CHECK個字節的數據 */ 37 temp = fread(buf, 1, PNG_BYTES_TO_CHECK, fp); 38 /* 若讀到的數據並沒有PNG_BYTES_TO_CHECK個字節 */ 39 if (temp < PNG_BYTES_TO_CHECK) { 40 fclose(fp); 41 png_destroy_read_struct(&png_ptr, &info_ptr, 0); 42 printf("load_png_image err:讀到的數據並沒有PNG_BYTES_TO_CHECK個字節"); 43 return 0; 44 } 45 /* 檢測數據是否為PNG的簽名 */ 46 temp = png_sig_cmp((png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK); 47 /* 如果不是PNG的簽名,則說明該文件不是PNG文件 */ 48 if (temp != 0) { 49 fclose(fp); 50 png_destroy_read_struct(&png_ptr, &info_ptr, 0); 51 printf("load_png_image err:不是PNG的簽名"); 52 return 0; 53 } 54 55 /* 復位文件指針 */ 56 rewind(fp); 57 /* 開始讀文件 */ 58 png_init_io(png_ptr, fp); 59 /* 讀取PNG圖片信息和像素數據 */ 60 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0); 61 /* 獲取圖像的色彩類型 */ 62 color_type = png_get_color_type(png_ptr, info_ptr); 63 64 /* 獲取圖像的寬高 */ 65 w = png_get_image_width(png_ptr, info_ptr); 66 h = png_get_image_height(png_ptr, info_ptr); 67 *width = w; 68 *height = h; 69 70 /* 分配空間buff,保存像素數據 */ 71 png_bytep buff = (png_bytep)malloc(h * w * 3 * sizeof(png_byte)); 72 memset(buff, 0, (h * w * 3 * sizeof(png_byte))); 73 74 /* 獲取圖像的所有行像素數據,row_pointers里邊就是rgba數據 */ 75 row_pointers = png_get_rows(png_ptr, info_ptr); 76 77 /* 根據不同的色彩類型進行相應處理 */ 78 switch (color_type) { 79 case PNG_COLOR_TYPE_RGB_ALPHA: 80 for (y = 0; y<h; ++y) 81 { 82 for (x = 0; x<w * 4;) 83 { 84 ///* 以下是RGBA數據,需要自己補充代碼,保存RGBA數據 */ 85 ///* 目標內存 */ = row_pointers[y][x++]; // red 86 ///* 目標內存 */ = row_pointers[y][x++]; // green 87 ///* 目標內存 */ = row_pointers[y][x++]; // blue 88 ///* 目標內存 */ = row_pointers[y][x++]; // alpha 89 printf("處理RGBA\n"); 90 } 91 } 92 93 break; 94 95 case PNG_COLOR_TYPE_RGB: 96 for (y = 0; y<h; y++) 97 { 98 for (x = 0; x<w; x++) 99 { 100 buff[y*w + 3 * x + 0] = row_pointers[y][3 * x + 0]; 101 buff[y*w + 3 * x + 1] = row_pointers[y][3 * x + 1]; 102 buff[y*w + 3 * x + 2] = row_pointers[y][3 * x + 2]; 103 printf("%x,%x,%x ", buff[y*w + 3 * x + 0], buff[y*w + 3 * x + 1], buff[y*w + 3 * x + 2]); 104 //printf("%x,%x,%x ", buff[y*w + 3 * x + 0], buff[y*w + 3 * x + 1], buff[y*w + 3 * x + 2]); 105 /*printf("處理RGB\n");*/ 106 } 107 printf("\n"); 108 } 109 printf("\n"); 110 break; 111 /* 其它色彩類型的圖像就不讀了 */ 112 default: 113 fclose(fp); 114 png_destroy_read_struct(&png_ptr, &info_ptr, 0); 115 printf("default color_type:close\n"); 116 return 0; 117 } 118 png_destroy_read_struct(&png_ptr, &info_ptr, 0); 119 return buff; 120 } 121 122 123 124 int main() 125 { 126 char *path = "F://1.png"; 127 int width = 0; 128 int height = 0; 129 png_bytep buff = load_png_image(path, &width, &height); 130 if (!buff) 131 { 132 printf("load_png_image(filepath) erro"); 133 } 134 printf("width:%d, height:%d\n", width, height); 135 136 /*int i = 0, j = 0; 137 for (i = 0; i < height; i++) 138 { 139 for (j = 0; j < width; j++) 140 { 141 printf("%x,%x,%x ", buff[i*width + 3 * j + 0], buff[i*width + 3 * j + 1], buff[i*width + 3 * j + 2]); 142 } 143 printf("\n"); 144 }*/ 145 146 system("pause"); 147 148 return 0; 149 }
讀取6*6藍底黑邊框png圖片數據域控制台效果: