日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

4.使用pnglib读写png图片

發布時間:2024/9/30 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 4.使用pnglib读写png图片 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??4.使用pnglib讀寫png圖片

? 本章前言:

??? 這章就是為了讀取png格式圖像到32位位圖(ARGB)中,逆之則然,廢話少說開始正題。

? 目標要點總結:

1.? 使用pnglib讀寫文件

? 最終效果:

??? 以下操作就能實現加載png圖像到32位圖像中:

??? Image*img_bg=Image::Create(L"data/img/bg.png");

??? 以下操作就能實現導出png圖像:

??? img_bg->Save_To_PNG(L"bin/bg.png");

? 前題簡要:

??? Image類用一個DWORD一維數組儲存每個點,每個點由ARGB組成,例如0x66ff0000是半透明紅色。假設要訪問點(x,y),應該使用下標索引[y *w + x]。Image類還有圖像的大小信息。

? 具體實現:

??? 首先需要配置pnglib,其中還包括zlib。下載相應源碼后,生成靜態鏈接庫鏈接到

項目。在代碼中解析圖片的cpp包含png.h。下面是解析png圖片的具體實現,可結合注釋理解。

??? Image* Image::Create(constString&path)

??? {

??????? //定義空圖像

??????? Image* img =newImage;

??????? System_imp* sys =System_imp::Get_Instance();

??????? //String char字符數組

?

?

??????? char temp[512] ={NULL };

??????? path.Get_Multi_Byte_Str(temp, 512);

??????????? ///從文件加載/

??????????? //打開png文件

??????????? FILE* fp = NULL;

??????????? fopen_s(&fp,temp,"rb");

??????????? if (!fp)

??????????? {

??????????????? Debug::Instance()->Write_Line(String(L"文件打開失敗:")+path);

??????????????? assert(0 &&L"Image加載時文件打開失敗!");

??????????????? return NULL;

??????????? }

??????????? //判斷是否為 png文件(用fread讀取8字節,然后調用png_sig_cmp判斷)

??????????? size_t number = 8;

??????????? png_bytep header = new png_byte[number];

??????????? fread(header, 1,number,fp);

??????????? bool is_png = !png_sig_cmp(header, 0,number);

??????????? if (!is_png)

??????????? {

??????????????? fclose(fp);

??????????????? Debug::Instance()->Write_Line(String(L"只支持png格式的圖像讀取:")+path);

??????????????? assert(0 &&L"Image加載時為非png格式圖像!");

??????????????? return NULL;

??????????? }

??????????? //初始化pnglib

??????????? static png_structppng_ptr =NULL;

??????????? if (!png_ptr)

??????????????? png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,

??????????????????? NULL, NULL, NULL);

??????????? if (!png_ptr)

??????????? {

??????????????? fclose(fp);

??????????????? assert(0 &&L"Image加載時初始化pnglib失敗!");

??????????????? return NULL;

??????????? }

??????????? //創建圖像信息 info

??????????? png_infop info_ptr = png_create_info_struct(png_ptr);

??????????? if (!info_ptr)

??????????? {

??????????????? fclose(fp);

??????????????? assert(0 &&L"Image加載時創建png_info失敗!");

??????????????? return NULL;

??????????? }

??????????? //錯誤處理

??????????? if (setjmp(png_jmpbuf(png_ptr)))

??????????? {

??????????????? fclose(fp);

??????????????? png_destroy_read_struct(&png_ptr, &info_ptr,png_infopp_NULL);

??????????????? assert(0 &&L"Image加載時 pnglib出現錯誤!");

??????????????? return NULL;

??????????? }

??????????? //設置數據源

??????????? png_init_io(png_ptr,fp);

??????????? //表明文件頭已處理

??????????? png_set_sig_bytes(png_ptr, 8);

??????????? //png

??????????? png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);

??????????? //info查詢數據

??????????? unsigned w = png_get_image_width(png_ptr, info_ptr);??????? //獲得圖片寬度

??????????? unsigned h = png_get_image_height(png_ptr, info_ptr);??????? //獲得圖片高度

??????????? int color_type = png_get_color_type(png_ptr,info_ptr);???????//獲得圖片顏色

??????????? //賦值給image

??????????? img->m_size.w =w;

??????????? img->m_size.h =h;

??????????? img->m_buffer =newDWORD[w*h];

??????????? //info復制到 image

??????????? png_bytep *row_point =NULL;

??????????? row_point = png_get_rows(png_ptr,info_ptr);

??????????? //帶透明通道一個點是4字節,否則為3字節

??????????? int block_size = (color_type == 6 ? 4 : 3);

??????????? //(A)RGB

??????????? unsigned pos = 0;

??????????? for (unsignedx = 0;x < h; ++x)

??????????????? for (unsignedy = 0;y < w*block_size;y +=block_size)

??????????????? {

??????????????????? ((unsigned char*)img->m_buffer)[pos + 0] =row_point[x][y + 2];//b;

??????????????????? ((unsigned char*)img->m_buffer)[pos + 1] =row_point[x][y + 1];//g

??????????????????? ((unsigned char*)img->m_buffer)[pos + 2] =row_point[x][y + 0];//r

??????????????????? if(color_type == 6)//不帶透明通道就填充 0xff表示不透明

??????????????????????? ((unsigned char*)img->m_buffer)[pos + 3] =row_point[x][y + 3];//a

??????????????????? else

??????????????????????? ((unsigned char*)img->m_buffer)[pos + 3] = 0xff;???????????????????pos += 4;

??????????????? }

??????????? //關閉文件

??????????? fclose(fp);

??????????? //釋放png內存

??????????? png_destroy_read_struct(&png_ptr, &info_ptr,png_infopp_NULL);

??????????? return img;

??? }

?

??? 保存到png圖像,如下調用:

canvas->Get_Image()->Save_To_PNG(L"bin/layer_image.png");

??? 上面的語句將畫布(一個DrawCall)的圖像導出到指定文件中。畫布Canvas會拼接Sprite使用的Image成大圖,從下面的圖片可以看到拼接并導出后的效果(這是導出的layer_image.png的一部分,不是程序截圖哈!):


? 保存圖像數據到PNG的實現如下:

??? void Image::Save_To_PNG(constString&path)

??? {

??????? FILE* fp;

??????? png_infop info_ptr;

???????

??????? char cpath[MAX_PATH] = {NULL };

??????? path.Get_Multi_Byte_Str(cpath,MAX_PATH);

??????? //創建或覆蓋文件

??????? fopen_s(&fp,cpath,"wb");

??????? if (fp ==NULL)

??????? {

??????????? assert(0 && L"Save_To_PNG 創建文件失敗!");

??????????? return;

??????? }

??????? //初始化pnglib(注意相關的函數名read都變成了write

??????? static png_structppng_ptr =NULL;

??????? if (!png_ptr)

??????????? png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,

??????????????? NULL, NULL,NULL);

??????? if (!png_ptr)

??????? {

??????????? assert(0 && L"Save_To_PNG 創建文件時初始化pnglib失敗!");

??????????? return;

??????? }

??????? info_ptr = png_create_info_struct(png_ptr);

??????? if (info_ptr ==NULL)

??????? {

??????????? fclose(fp);

??????????? assert(0 && L"Save_To_PNGpng_create_info_struct失敗!");

??????????? return;

??????? }

??????? //錯誤處理

??????? if (setjmp(png_jmpbuf(png_ptr)))

??????? {

??????????? fclose(fp);

??????????? png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

??????????? assert(0 && L"Save_To_PNGpnglib出現錯誤!");

??????????? return;

??????? }

??????? //顏色深度8,像素大小(ARGB 4字節),行字節寬度

??????? unsigned bit_depth = 8;

??????? unsigned pixel_byte = 4;

??????? unsigned row_byte =m_size.w *pixel_byte;

??????? //設置輸出文件

??????? png_init_io(png_ptr,fp);

??????? //設置圖像屬性

??????? png_set_IHDR(png_ptr, info_ptr, m_size.w,m_size.h,bit_depth,

??????????? PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE,//交錯無

??????????? PNG_COMPRESSION_TYPE_BASE,PNG_FILTER_TYPE_BASE);

??????? //寫頭部

??????? png_write_info(png_ptr, info_ptr);

??????? //行指針

??????? png_bytepp row_pointers = (png_bytep*)malloc(m_size.h*sizeof(png_bytep));

??????? //填充數據

??????? for (unsignedx = 0;x < m_size.h; ++x)

??????? {//分配一行

??????????? row_pointers[x] = (png_bytep)malloc(row_byte);

??????????? for (unsignedy = 0;y < row_byte; y += pixel_byte)

??????????? {

??????????????? row_pointers[x][y + 2] = ((unsignedchar*)m_buffer)[x *row_byte + y + 0];

??????????????? row_pointers[x][y + 1] = ((unsignedchar*)m_buffer)[x *row_byte + y + 1];

??????????????? row_pointers[x][y + 0] = ((unsignedchar*)m_buffer)[x *row_byte + y + 2];

??????????????? row_pointers[x][y + 3] = ((unsignedchar*)m_buffer)[x *row_byte + y + 3];

???????????????

??????????? }

??????? }

??????? //寫入全部行

??????? png_write_image(png_ptr, row_pointers);

??????? //寫尾部

??????? png_write_end(png_ptr, info_ptr);

??????? //釋放png內存

??????? png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

?

??? ??? for (unsignedx = 0;x < m_size.h; ++x)

??????? {//釋放每行

??????????? free(row_pointers[x]);

??????? }

??????? free(row_pointers);????

??????? fclose(fp);

??? }

?

作者:略游

日期:17-06-20

QQ:1339484752

總結

以上是生活随笔為你收集整理的4.使用pnglib读写png图片的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。