• [libpng]CMake+VS2015下编译libpng,及使用小例


    编译前的工作

    在编译libpng前,需要把zlib编译好,并加载到编译环境里。

    CMake + VS2015 下编译zlib,及使用小例

    下载与解压

    libpng的官网是 http://www.libpng.org/pub/png/libpng.html ,但它的源码是存在 https://sourceforge.net 上的;具体最新的版本可以先进官网看看,再点连接过去下载

     

    我当前的版本是libpng 1.6.36

    把里面的文件解压出来

    CMake创建工程

    看了一下,CMakeLists.txt就在这个目录下,用CMake加载一下;在Cmake-gui里,设置好source code 和build the binaries,就点击一下【Configure】:

    加载后,别急着【Generate】需要设置一下编译后的lib、dll和头文件的安装路径了,第一次我建议设定源码目录下的路径,方便看一下编译后生成了哪些文件,不然的话可以直接设置为您本机的VC的路径【注意:不是VS的路径,而是VS下VC的路径,这是个人建议,不喜欢的后面给另外一个方法】

    设置好这再【Generate】,基本不会再出什么问题了,就可以点击【Open Project】打开工程:

    不安装到VC路径下

    如果不喜欢把libpng安装到VC路径下时,还是需要设定安装的路径,但在安装后,需要把您设定的安装路径添加到环境变量中的Path里。

    如果是用VS创建工程的, 就需要把头文件、lib和dll这些的路径添加到工程属性里。

    但用CMake可以去掉手动配置的这一步, 但必须把库的安装路径添加到环境变量里,不然CMake是没查找到这个库的。本人做个测试, 如果不对可以评论指正!

    编译与安装

    编译

    使用CMake+VS2015编译的过程很简单,经过前面的配置工作后,打开工程后,就直接右键解决方案,再点击【生成解决方案】:

    之后就是等待了,还好libpng比较小,编译很快的:

    安装

    在编译成功后,这时就需要把编译生成的文件安装到前面设定好的目录下;看【解决方案】下方,有一个项目的名字为【INSTALL】,只要右键【INSTALL】→

    【仅用于项目】→【仅生成INSTALL】

    ok, 已经安装完毕:

    小贴示

    看到编译生成的文件名竟然带有版本号信息,我有点小小强迫症,所以我想去,这就需要修改一下CMake配置文件CMakeLists.txt:

    这个时候回去cmake-gui需要删除之前缓存,再Configure和Generate,并重新编译就好了。

    使用libpng生成图片

    因为用了CMake后,基本很少用VS里的功能来创建工程了:

    生成一个png图片

    CMakeLists.txt

     1 cmake_minimum_required(VERSION 3.0)
     2 
     3 project(PngDemoEx1)
     4 
     5 aux_source_directory(. SRC)
     6 
     7 link_libraries(debug libpngd)    #设置Debug时使用libpngd.lib
     8 link_libraries(optimized libpng)    #设置非Debug时使用libpng.lib
     9 
    10 add_executable(${PROJECT_NAME} ${SRC})
    View Code

    main.cpp

     1 #include <png.h>
     2 #include <stdio.h>
     3 #include <iostream>
     4 using namespace std;
     5 
     6 
     7 int main(int argc, char* argv[])
     8 {
     9 
    10     png_structp ppng = NULL;//libpng的结构体
    11     png_infop   pinfo = NULL;//libpng的信息
    12 
    13     //打开一个保存png的文件流
    14     FILE* fpng = fopen("tt.png", "wb");
    15 
    16     //创建一个png_structp结构体实例ppng
    17     ppng = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    18     if (!ppng) {
    19         printf("png_create_write_struct failed ...
    ");
    20         return -1;
    21     }
    22     png_init_io(ppng, fpng);    //把ppng与文件流绑定起来
    23     if (setjmp(png_jmpbuf(ppng))) {
    24         printf("error during init_io ...
    ");
    25         return -1;
    26     }
    27     //用png_structp结构体创建一个png_infop结构体实例pinfo,个人理解这是png相关头信息的结构体
    28     pinfo = png_create_info_struct(ppng);    
    29     if (!pinfo) {
    30         printf("png_create_info_struct failed ...
    ");
    31         return -1;
    32     }
    33     png_set_IHDR(ppng, pinfo,
    34         10, 10,//尺寸
    35         8,//颜色深度,也就是每个颜色成分占用位数(8表示8位红8位绿8位蓝,如果有透明通道则还会有8位不透明度)
    36         PNG_COLOR_TYPE_RGB,//颜色类型,PNG_COLOR_TYPE_RGB表示24位真彩深色,PNG_COLOR_TYPE_RGBA表示32位带透明通道真彩色
    37         PNG_INTERLACE_NONE,//不交错。PNG_INTERLACE_ADAM7表示这个PNG文件是交错格式。交错格式的PNG文件在网络传输的时候能以最快速度显示出图像的大致样子。
    38         PNG_COMPRESSION_TYPE_BASE,//压缩方式
    39         PNG_FILTER_TYPE_BASE);//这个不知道,总之填写PNG_FILTER_TYPE_BASE即可。
    40     png_write_info(ppng, pinfo);
    41     png_set_packing(ppng);//设置打包信息
    42     png_write_info(ppng, pinfo);//写入文件头
    43 
    44     //定义行数组,是一个指向指针的数组,数组中每一个指向一行的像素数组
    45     png_bytepp data = new png_bytep[10];    
    46     for (size_t i = 0; i < 10; i++)
    47     {
    48         data[i] = new png_byte[30]{0x23,0x32, 0x25, 0x21, 0x89};//定义一行像素数组
    49     }
    50     //把像素数据写入png_structp结构体实例ppng中
    51     png_write_image(ppng, (png_bytepp)data);
    52     //写入png结束信息
    53     png_write_end(ppng, pinfo);
    54 
    55     //后面都是清理,回收内存
    56     for (size_t i = 0; i < 10; i++)
    57     {
    58         delete[]data[i];
    59     }
    60     delete[]data;
    61     png_destroy_write_struct(&ppng, &pinfo);
    62     fclose(fpng);
    63     return 0;
    64 }
    View Code

     总结一下

    之前第一次使用时,遇到一个问题,一开始只编译安装了libpng的Release版,但在使用的时候工程是Debug版的,编译过了,但运行时就一直提示一个异常:

    其解决方法是编译版对应的,在开发中Debug就用debug版的libpng,Release就对应Release版的libpng。

    读取png,生成RGB数据文件

    1. 打开png文件的文件流
    2. 从文件流中读四个字节,做PNG签字验证
    3. 重置流的位置
    4. 定义png_structp指针并创建结构体png_struct实例
    5. 定义png_infop指针并创建结构体png_info实例
    6. png_init_io初始化png_struct实例的文件流
    7. png_read_png读取png图片信息与数据
    8. png_get_color_type
    9. png_get_image_width 与 png_get_image_height
    10. png_get_rows
    11. png_destroy_read_struct 释放png_struct实例和png_info实例
    12. 关闭文件流
     1 #include <stdio.h>
     2 #include <png.h>
     3 #include <iostream>
     4 #include <sstream>
     5 #include <string>
     6 using namespace std;
     7 #define PNG_SIGN_SIZE 4
     8 int main(int argc, char* argv[])
     9 {
    10     int ret = 0;
    11     FILE* fpng = fopen("tt.png", "rb");
    12     if (fpng == NULL)
    13     {
    14         cerr << "open png file error" << endl;
    15         return __LINE__;
    16     }
    17 
    18     char png_sign_buf[PNG_SIGN_SIZE] = {0};
    19     ret = fread(png_sign_buf, sizeof(char), PNG_SIGN_SIZE, fpng);
    20     if (ret < PNG_SIGN_SIZE)
    21     {
    22         cerr << "数据长度不足" << PNG_SIGN_SIZE << "个字节" << endl;
    23         fclose(fpng);
    24         return __LINE__;
    25     }
    26 
    27     ret = png_sig_cmp((png_bytep)png_sign_buf, 0, PNG_SIGN_SIZE);
    28     if (ret != 0)
    29     {
    30         cerr << "lPNG的签名不正确" << endl;
    31         fclose(fpng);
    32         return __LINE__;
    33     }
    34 
    35     rewind(fpng);/* 复位文件指针 */
    36 
    37     png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    38     png_infop  info_ptr = png_create_info_struct(png_ptr);
    39 
    40     png_init_io(png_ptr, fpng);
    41     /* 读取PNG图片信息和像素数据 */
    42     png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, NULL);
    43     /* 获取图像的色彩类型 */
    44     int color_type = png_get_color_type(png_ptr, info_ptr);
    45 
    46     int width = png_get_image_width(png_ptr, info_ptr);
    47     int height = png_get_image_height(png_ptr, info_ptr);
    48 
    49     png_bytepp rows_ptr;
    50     rows_ptr = png_get_rows(png_ptr, info_ptr);
    51 
    52     int channel = color_type == PNG_COLOR_TYPE_RGB ? 3 : 4;
    53 
    54     stringstream ss;
    55     ss << "tt_" << width << "x" << height << ".rgb";
    56 
    57     FILE* frgb = fopen(ss.str().c_str(), "wb");
    58 
    59     if (frgb != NULL)
    60     {
    61         for (int h = 0; h < height; h++)
    62         {
    63             for (int w = 0; w < width; w++)
    64             {
    65                 fwrite((void*)&rows_ptr[h][w*channel], sizeof(char), 3, frgb);
    66             }
    67         }
    68         fclose(frgb);
    69     }
    70 
    71     png_destroy_read_struct(&png_ptr, &info_ptr, 0);
    72     fclose(fpng);
    73 
    74     return 0;
    75 }
    View Code

    这个实例,把png图片文件中的RGB读取出来保存了,如果需要查看RGB数据文件,可以用相关工具看的

  • 相关阅读:
    类和接口对比
    concurrenthasmap
    java中的三大注解
    基本数据类型,注意首字母
    常见ascii码记忆
    Java软件工程师面试题:Java运行时异常与一般异常有什么不一样?
    &和&&的共同点和区别、Java字符含义和Java创建对象的几种方式
    Java面试题中常考的容易混淆的知识点区别
    Java面试题整理:这些Java程序员面试中经常遇见的题目,必须掌握才能有好结果
    Spring Cloud 微服务架构的五脏六腑,统统晒一晒!
  • 原文地址:https://www.cnblogs.com/dilex/p/10732639.html
Copyright © 2020-2023  润新知