Step to UEFI (157)UEFI 下 PCX 的解码

很早之前,PCX 图片是Windows 3.1默认支持的图像格式,加之它自带无损压缩算法,所以很长一段时间,这种格式是分享和传播图片的首选。从XP 开始,Microsoft取消了默认的支持,并且随着硬件性能的提升,解码和存储完全不是问题,逐渐JPG和PNG成为了图片的首选。时至今日,想找一个免费的PCX查看软件竟然花费了一番功夫(推荐XnView,免费小巧)。

最近网上找到了一个 PCX 的解码代码【参考1】,在 Shell 下写了一个实例文件。特别注意的是PCX解码之后的格式为 RGBRGB…RGB 这样的形式,但是 GraphicsOutput->Blt 显示的格式要求为 RGB0RGB0…….RGB0【参考2】。因此,还需要一个将RGB 转为 RGB0 的动作,简单的说之前一个点是3Bytes,现在需要扩展为4Bytes。

下面是调用该库的示例代码:

#define DR_PCX_IMPLEMENTATION
#include "dr_pcx.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;
    int components;
    int i,j;
    EFI_STATUS    Status;
    EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
    UINT8* RGB32;
    
    if (Argc<2) {
            printf("Please input file name\n");
            return 0;
    }
    
    uint8_t* pImageData   = drpcx_load_file(Argv[1], FALSE, &width, &height, &components, 0);
    
    if (pImageData == NULL) {
        printf("Open file Error\n");
        return -1;
    }
    printf("width %d height %d",width,height);
    RGB32 = (UINT8*)AllocatePool(width*height*4); 
    for (j=0;j<height;j++) {
            for (i=0;i<width;i++) {
                //RGBARGBARGBA...RGBA
                RGB32[(j*width+i)*4]  = pImageData[(j*width+i)*3+2]; //Blue   
                RGB32[(j*width+i)*4+1]= pImageData[(j*width+i)*3+1]; //Green 
                RGB32[(j*width+i)*4+2]= pImageData[(j*width+i)*3]; //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);                
    
    // At this point pImageData contains the raw decoded image data as tightly
    // packed RGB or RGBA, depending on on the value of "components".
    drpcx_free(pImageData);

    return 0;
}

 

这个代码可以直接在NT32 模拟环境下运行,测试结果:

这里只是简单展示解码库的使用,只测试了几张PCX图片,有兴趣的的朋友可以进行更深入的研究。
完整代码和图片

pcxtest

参考:
1.https://mackron.github.io/dr_pcx.html PCX 解码库
2.具体请参考 UEFI Spec Blt Buffer 章节
3.例子的PCX图片 来源 https://github.com/warpdesign/pcx-js

发表评论

电子邮件地址不会被公开。 必填项已用*标注