前面介绍过 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
感謝解答!