极简的 PNG 编码函数 svpng(),用来学习C语言,真的很爽
這個是在知乎上看到的大神寫的文章,如果是學習C語言入門的,我覺得可以從這個入手,特別是對圖像感興趣的。
文章中提到的「我」,指的是「Milo Yip」大神。
1. ?? 什么是png格式圖片?
相對地,PNG(Portable Network Graphics)就是一個廣為人知的圖片格式。如果可以把影像直接儲存成 PNG,不是更理想么?
然而,在 C/C++ 中寫入 PNG 一般需要鏈接一些程序庫,例如 PNG 的標準參考程序庫是 libpng。它很強大,支持 PNG 所有功能,但對于初學者而言,配置、編譯并學習如何使用這些程序庫,可能已足夠打消動手的念頭。
可以簡單一點么?
2.? ? svpng
為此,我在周末嘗試寫一個極簡的 C 函數 Github miloyip/svpng(save PNG 的縮寫),它僅能寫入 24-bit RGB 或 32-bit RGBA、無壓縮的 PNG。它只有一個 32 行代碼的函數。
github地址:
https://github.com/miloyip/svpng
用法如下:
#include?"svpng.inc"void?test_rgb(void)?{unsigned?char?rgb[256?*?256?*?3],?*p?=?rgb;unsigned?x,?y;FILE?*fp?=?fopen("rgb.png",?"wb");for?(y?=?0;?y?<?256;?y++)for?(x?=?0;?x?<?256;?x++)?{*p++?=?(unsigned?char)x;????/*?R?*/*p++?=?(unsigned?char)y;????/*?G?*/*p++?=?128;?????????????????/*?B?*/}svpng(fp,?256,?256,?rgb,?0);fclose(fp); }就會輸出這個 rgb.png 文件:
這個函數的聲明很簡單,缺省配置下是這樣的:
/*!\brief?以?PNG?格式存儲?RGB/RGBA?影像\param out 輸出流(缺省使用 FILE*)。\param w 影像寬度。(<16383)\param h 影像高度。\param img 影像像素數據,內容為 24 位 RGB 或 32 位 ARGB 格式。\param alpha 影像是否含有 alpha 通道。 */ void?svpng(FILE*?out,?unsigned?w,?unsigned?h,?const?unsigned?char*?img,?int?alpha);相信這樣的函數時使對初學者而言,也極易使用。也不需要另外生成程序庫,只要復制到項目便可使用。
3.? ? 代碼實現
這里簡單介紹實現要點,對此沒興趣的讀者也可略過。
根據 Portable Network Graphics (PNG) Specification (Second Edition) 「www.w3.org」,PNG 文件由多個 chunk 組成。每個 chunk 的類型以 4 個字符表示。最基本的 PNG 文件內容是:
8 字節 magic number:用于識別 PNG 格式
IHDR(Image Header) chunk:描述影像的維度、色彩深度、色彩格式、壓縮類型等
IDAT(Image Data)chunk:存儲影像的像素數據
IEND(Image End)chunk:PNG數據流結束
每個 chunk 的結構是:
chunk 內容長度(4 字節)
chunk 類型(4 字節)
chunk 內容
chunk 的 CRC(包括類型和內容)
PNG 里的數據是以大端(big endian)編碼的,但在 IDAT 中,每個 block 的長度則以小端存儲。另外,實現的難點之一,是要同時實現 CRC-32 及 Adler-32 校驗和(checksum)的生成。
編碼實現如下(文字版請移玉步至 svpng.inc):
為了減少代碼大小,使用宏去避免加入多個函數。另外,為了簡化實現,把每一行像素寫成一個 block,這樣可能會浪費一點空間,但對于這函數而言也不是問題。
4.? ? ?結語
本文介紹了一個極簡的 C 函數 svpng,方便在 C/C++ 中把圖像存儲成 PNG 文件,并簡介了當中的實現。希望讀者能利用此函數,進入計算機圖形學之門。
===
文中的 inc 而不是.h,是因為inc 是對方法的實現,而不是簡單的聲明。
unsigned char rgb[256 * 256 * 3]?,可能有的人不明白為什么數組要這樣聲明,一個像素點是通過{R,G,B}三色值表示的,所以后面有一個3,但是一張圖片,是包含有長和寬的,也就是前面的256*256,就是這張圖片的長和寬。實際上的圖片是這樣排列的?{ R, G, B, R, G, B, ... } 的形式,從上至下,左至右。
#推薦閱讀#
專輯|Linux文章匯總
專輯|程序人生
專輯|C語言
我的知識小密圈
關注公眾號,后臺回復「1024」獲取學習資料網盤鏈接。
歡迎點贊,關注,轉發,在看,您的每一次鼓勵,我都將銘記于心~
嵌入式Linux
微信掃描二維碼,關注我的公眾號
總結
以上是生活随笔為你收集整理的极简的 PNG 编码函数 svpng(),用来学习C语言,真的很爽的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: U盘病毒 hypertrm.exe 修复
- 下一篇: 没有什么能难倒程序员,教你如何下载付费歌