[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 ...\n");
20         return -1;
21     }
22     png_init_io(ppng, fpng);    //把ppng與文件流綁定起來
23     if (setjmp(png_jmpbuf(ppng))) {
24         printf("error during init_io ...\n");
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 ...\n");
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數據文件,可以用相關工具看的

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM