• libpng处理png图片(一)


    一:libpng库的编译

      环境:windows10 + VS2013

      需要下载:libpng, zlib两个库

      下载地址:

        libpng:http://libmng.com/pub/png/libpng.html

        zlib:http://www.zlib.net/

      注意事项:

        libpng, zlib解压后放到同一目录,

        打开ibpng目录下的projectsvstudio中的工程文件,编译运行

        在输出目录(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
    ", 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
    ");
     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
    ");
     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
    ");
     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
    ");
    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
    ");
    131     int result = writeImage(argv[1], width, height, "This is my test image");
    132     if (result)
    133     {
    134         printf("Saving err
    ");
    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
    ");
     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
    ");*/
    106             }
    107             printf("
    ");
    108         }
    109         printf("
    ");
    110         break;
    111         /* 其它色彩类型的图像就不读了 */
    112     default:
    113         fclose(fp);
    114         png_destroy_read_struct(&png_ptr, &info_ptr, 0);
    115         printf("default color_type:close
    ");
    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("%d, height:%d
    ", 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("
    ");
    144     }*/
    145 
    146     system("pause");
    147 
    148     return 0;
    149 }
    View Code

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

        

      

      

        

  • 相关阅读:
    协同过滤算法
    redis雪崩,击穿,穿透
    scentos7安装redis,以及redis的主从配置
    centos7安装python3
    vm虚拟机安装centos7。克隆镜像以及快照
    全文检索django-haystack+jieba+whoosh
    drf的权限扩充
    redis分布式锁解决超卖问题
    Django结合Websocket进行WebSSH的实现
    vue-父子组件传参以及无限级评论
  • 原文地址:https://www.cnblogs.com/weiyikang/p/6828647.html
Copyright © 2020-2023  润新知