前面介绍过 PCX的解码,这次研究一下 PNG 格式的解码,有了前面的经验,这次实现起来简单多了。
首先,找一个C语言的PNG 解码库,经过比较选择了来自【参考1】的 upng。然后根据说明编写一个简单的示例:
#define DR_PCX_IMPLEMENTATION #include "upng.h" #include <stdlib.h> #include <stdio.h> #include <Protocol/GraphicsOutput.h> #include <Library/MemoryAllocationLib.h> #include <Library/BaseMemoryLib.h> extern EFI_BOOT_SERVICES *gBS; extern EFI_SYSTEM_TABLE *gST; extern EFI_RUNTIME_SERVICES *gRT; #define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ { \ 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \ } static EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; int main ( IN int Argc, IN char *Argv[] ) { int width; int height; EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; int i,j; UINT8* RGB32; UINT8* pImageData; if (Argc<2) { printf("Please input file name\n"); return 0; } upng_t* upng = upng_new_from_file(Argv[1]); if (upng == NULL) { printf("Open file Error\n"); return -1; } upng_header(upng); width=upng_get_width(upng); height=upng_get_height(upng); printf("width %d height %d\n",width,height); upng_format f=upng_get_format(upng); printf("format %d\n",f); upng_decode(upng); pImageData=(UINT8 *)upng_get_buffer(upng); RGB32 = (UINT8*)AllocatePool(width*height*4); for (j=0;j<height;j++) { for (i=0;i<width;i++) { RGB32[(j*width+i)*4] = pImageData[(j*width+i)*4+2]; //Blue RGB32[(j*width+i)*4+1]= pImageData[(j*width+i)*4+1]; //Green RGB32[(j*width+i)*4+2]= pImageData[(j*width+i)*4]; //Red RGB32[(j*width+i)*4+3]=0; } } Status = gBS->LocateProtocol(&GraphicsOutputProtocolGuid, NULL, (VOID **) &GraphicsOutput); if (EFI_ERROR(Status)) { GraphicsOutput = NULL; printf("Loading Graphics_Output_Protocol error!\n"); return EFI_SUCCESS;} GraphicsOutput->Blt( GraphicsOutput, (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) RGB32, EfiBltBufferToVideo, 0, 0, 0, 0, width, height, 0); free(RGB32); upng_free(upng); return 0; }
运行结果(可以在NT32模拟环境下运行):
完整代码和实例PNG测试图片:
pngtest
特别需要注意的是:解码之后的数据无法直接使用 BLT 在屏幕上显示,因此,特别重新开辟了一个内存空间进行排列。这样的操作也会导致兼容性上的问题,换其他格式的 PNG (比如:例子用的都是RGBA的,此外还有RGB格式的),会出现错误的情况。如果你发现decode之后结果很奇怪,不妨考虑一下是否是这个原因导致的。
参考:
1. https://github.com/elanthis/upng
Hi 您好,
拜讀了您的Code,處理width*height的地方為什麼都要*4呢?
謝謝您。
BR,
Will
因为一个像素占用4个Byte: R G B各占一个Byte + 空的一个 Byte
感謝解答!