libpng庫解析圖片主要用的函數(shù)大致有: png_sig_cmp(sig, 0, 8); png_create_read_struct(png_get_libpng_ver(NULL), NULL, NULL, NULL); png_create_info_struct(png_ptr); setjmp(png_jmpbuf(png_ptr)); png_init_io(png_ptr, trfile); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_get_rowbytes(png_ptr,info_ptr); png_read_image(png_ptr, row_pointers);
加載png圖片
png_structp png_ptr;png_infop info_ptr;FILE * trfile;void Load(char * fileName){ trfile = fopen(name,"rb"); BYTE sig[9] = {0}; fread(sig, 1, 8, trfile); int result ; result = png_sig_cmp(sig, 0, 8); png_ptr = png_create_read_struct(png_get_libpng_ver(NULL), NULL, NULL, NULL); info_ptr = png_create_info_struct(png_ptr); esult = setjmp(png_jmpbuf(png_ptr)); png_init_io(png_ptr, trfile); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr);}png_sig_cmp(sig, 0, 8): it will return 0 (false) if the bytes match the corresponding bytes of the PNG signature; 驗證PNG文件的正確性完整性; 如果你已經(jīng)使用png_sig_cmp函數(shù)來檢查了png數(shù)據(jù),需要調(diào)用png_set_sig_bytes函數(shù)來告訴libpng庫,這樣庫處理數(shù)據(jù)的時候?qū)^相應(yīng)的數(shù)據(jù)
png_set_sig_bytes(png_ptr, 8); Tell lib we have already handled the first “8” magic bytes. Handling more than 8 bytes from the beginning of the file is an error. 設(shè)置讀取PNG文件的指針偏移量,不能超過8位(用于配置png_sig_cmp的使用);
setjmp(png_jmpbuf(png_ptr)) When libpng encounters an error, it expects to longjmp back to your routine; 設(shè)置發(fā)生錯誤時返回錯誤時調(diào)用的位置; 用setjmp/longjmp函數(shù)來處理異常。libpng庫默認(rèn)集成這種機制來完成異常處理; 如果設(shè)置了用戶自定義的錯誤處理函數(shù),libpng將會調(diào)用用戶自定義錯誤處理函數(shù),而不會返回到這個設(shè)置了默認(rèn)返回點的調(diào)用點上;
經(jīng)過上面的Load后可以打印相關(guān)的png數(shù)據(jù),這里定義一個結(jié)構(gòu)體存放更清晰
typedef struct { int pixelDepth; int imageWidth; int imageHeight;}PngImageInfo;void GetImageInfo(PngImageInfo* pInfo){ pInfo->pixelDepth = info_ptr->pixel_depth; pInfo->imageWidth = info_ptr->width; pInfo->imageHeight = info_ptr->height;}下面開始解碼png數(shù)據(jù)到一個數(shù)組中,用于進行繪制到顯存下
unsigned long* GetPngData(int dstW, int dstH){ unsigned long pDst[dstW * dstH * 4]; // 解析后的數(shù)據(jù),24位和32位的圖每個像素占空間ARGB個1byte png_bytep row_pointers[dstH]; for (int row = 0; row < dstH; row++){ row_pointers[row] = NULL; } for (int row = 0; row < dstH; row++){ //png_get_rowbytes(png_ptr,info_ptr)==834==278*3(本例程使用的是24位深度的PNG圖片) row_pointers[row] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr,info_ptr)); } png_read_image(png_ptr, row_pointers); if(info_ptr->pixel_depth == 24) { int pixelR,pixelG,pixelB; unsigned char * pSrc; int i, j; int top = 0; //畫布y軸上偏移量 int left = 0; //畫布x軸上偏移量 for(j=0;j<dstH;j++){ pSrc = row_pointers[top+j] + left * 3; for(i=0;i<dstW;i++){ pixelR = *pSrc++; pixelG = *pSrc++; pixelB = *pSrc++; pDst[i] = 0xFF000000 | (pixelR << 16) | (pixelG << 8) | pixelB; } pDst += dstW;// 加上圖片的橫向像素點(即縱向下移一個像素單位) } } for (int row = 0; row < info_ptr->height; row++){ png_free(png_ptr,row_pointers[row]); } return pDst; // 返回指針是不科學(xué)的 但是這里僅僅是舉例說明}這里插播一下關(guān)于32位的位深度的PNG圖片的解析:
if(info_ptr->pixel_depth == 32){ unsigned long pixelR,pixelG,pixelB,pixelA; unsigned char * pSrc; int i, j; for(j=0;j<dstH;j++){ pSrc = row_pointers[top+j] + left * 4; for(i=0;i<dstW;i++) { pixelR = *pSrc++; pixelG = *pSrc++; pixelB = *pSrc++; pixelA = *pSrc++; pDst[i] = (pixelA<< 24) | (pixelR << 16) | (pixelG << 8) | pixelB; } pDst += dstW; }}上面的Draw函數(shù)已經(jīng)獲取到解碼后的png數(shù)據(jù),接下來只需要把數(shù)據(jù)放入到內(nèi)存對應(yīng)的區(qū)域就能把圖片顯示出來了:
// 硬件地址unsigned long* GetDisplayMemoryAddr(){ int* h_hsPR = open("/dev/frame", O_RDWR, 0); unsigned long* pDst = (unsigned long*)mmap(0, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED,h_hspr, 0); return pDst;}// 圖片大小 278*182// 畫布大小(屏幕大小) 800*480void CopyPngDataToDisplayDriver(){ unsigned long*pDst = GetDisplayMemoryAddr(); unsigned long*pSrc = GetPngData(278, 182); for(int i=0; i<182; i++) { memcpy(pDst,pSrc,278 * 4); //pDst[dstW*dstH*4] pDst += 800; pSrc += 278; } ioctl(h_hspr,IOCTL_Y,NULL); ioctl(h_hspr,IOCTL_X,NULL);}效果為: 
本次例程使用的是交叉編譯到全志的開發(fā)板中進行測試 PNG圖片文件數(shù)據(jù):278*182,位深度24
新聞熱點
疑難解答