libpng是一個跨平台的png解碼庫,方便易用。我這裡不說它怎麼移植,基本上如果是支持fopen之類函數的平台都可以支持。其實他的移植非常簡單,zlib可能麻煩一點,但相信一般人都能搞定。主要是文件讀寫和錯誤處理的試配。
這裡只提供一個使用libpng得到文件RGB(A)數據的例子,沒加任何的錯誤處理:
void readpng__001(char* name)
{
// 前邊幾句是扯淡,初始化各種結構
FILE* file = fopen(name, "rb");
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
png_infop info_ptr = png_create_info_struct(png_ptr);
setjmp(png_jmpbuf(png_ptr));
// 這句很重要
png_init_io(png_ptr, file);
// 讀文件了
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);
// 得到文件的寬高色深
int m_width = png_get_image_width(PngPtr, InfoPtr);
int m_height = png_get_image_height(PngPtr, InfoPtr);
int color_type = png_get_color_type(PngPtr, InfoPtr);
// 申請個內存玩玩,這裡用的是c++語法,甭想再c上編過
int size = m_height * m_width * 4;
unsigned char* bgra = new unsigned char[size];
int pos = 0;
// row_pointers裡邊就是傳說中的rgba數據了
png_bytep* row_pointers = png_get_rows(PngPtr, InfoPtr);
// 拷貝!!注意,如果你讀取的png沒有A通道,就要3位3位的讀。還有就是注意字節對其的問題,最簡單的就是別用不能被4整除的寬度就行了。讀過你實在想用,就要在這裡加上相關的對齊處理。
for(int i = 0; i < m_height; i++)
{
for(int j = 0; j < (4 * m_width); j += 4)
{
bgra[pos++] = row_pointers[i][j + 2]; // blue
bgra[pos++] = row_pointers[i][j + 1]; // green
bgra[pos++] = row_pointers[i][j]; // red
bgra[pos++] = row_pointers[i][j + 3]; // alpha
}
}
// 好了,你可以用這個數據作任何的事情了。。。把它顯示出來或者打印出來都行。
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
fclose(file);
return;
}
libpng 的詳細介紹:請點這裡
libpng 的下載地址:請點這裡