libpng处理png图片(一)

一: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 }
View Code

  生成的一张简单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 }
View Code

  读取6*6蓝底黑边框png图片数据域控制台效果:

    

  

  

    

转载于:https://www.cnblogs.com/weiyikang/p/6828647.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值