增加一个缩放图像功能函数:
/**
缩放图像(双线性插值或最近邻)。
@param[out] DstImg 目标图像(使用前须清零)。
@param[in] SrcImg 源图像。
@param[in] DstWidth 目标宽度(像素,>0)。
@param[in] DstHeight 目标高度(像素,>0)。
@retval EFI_SUCCESS 缩放成功。
@retval EFI_INVALID_PARAMETER 参数非法。
@retval EFI_OUT_OF_RESOURCES 分配失败。
说明:
- 采用双线性插值,质量好但计算量较大(考虑大图像缩放可能较慢)。
- 源图像宽高为 0 时返回错误。
- 目标宽高与源宽高相同则直接复制。
**/
EFI_STATUS
EFIAPI
scaleimage (
OUT IMAGE *DstImg,
IN CONST IMAGE *SrcImg,
IN INT32 DstWidth,
IN INT32 DstHeight
);
重新写了一个Demo,只演示这个功能,代码如下:
/** @file
EasyX UEFI 图形库演示程序:scaleimage 图像缩放演示。
演示 scaleimage 函数的双线性插值缩放能力。
**/
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/PrintLib.h>
#include "easyx.h"
/**
程序入口。
**/
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
INT32 W;
INT32 H;
IMAGE Sprite;
IMAGE Scaled50;
IMAGE Scaled75;
IMAGE Scaled150;
IMAGE Scaled200;
ExMessage Msg;
BOOLEAN Running;
//
// 初始化所有 IMAGE 结构。
//
Sprite.Width = 0;
Sprite.Height = 0;
Sprite.Buffer = NULL;
Scaled50.Width = 0;
Scaled50.Height = 0;
Scaled50.Buffer = NULL;
Scaled75.Width = 0;
Scaled75.Height = 0;
Scaled75.Buffer = NULL;
Scaled150.Width = 0;
Scaled150.Height = 0;
Scaled150.Buffer = NULL;
Scaled200.Width = 0;
Scaled200.Height = 0;
Scaled200.Buffer = NULL;
//
// 初始化绘图设备(1024×768)。
//
Status = initgraph (1024, 768);
if (EFI_ERROR (Status)) {
Print (L"initgraph 失败: %r\n", Status);
return Status;
}
W = getwidth ();
H = getheight ();
//
// 批量绘图。
//
BeginBatchDraw ();
//
// 背景填充深蓝。
//
setbkcolor (RGB (16, 16, 48));
cleardevice ();
//
// 在内存中创建一个 100×100 的测试图像(彩色圆+文字)。
//
if (!EFI_ERROR (CreateImage (&Sprite, 100, 100))) {
SetWorkingImage (&Sprite);
//
// 绘制背景
//
setbkcolor (RGB (20, 30, 60));
cleardevice ();
//
// 绘制彩色圆(中心)
//
setfillcolor (RGB (255, 100, 50));
setlinecolor (WHITE);
fillcircle (50, 40, 30);
//
// 绘制外圆
//
setlinecolor (YELLOW);
setlinestyle (PS_SOLID, 2);
circle (50, 40, 35);
//
// 绘制文字
//
settextcolor (LIGHTGREEN);
settextstyle (20, 10);
setbkmode (TRANSPARENT);
outtextxy (15, 75, "Scale");
//
// 恢复到屏幕
//
SetWorkingImage (NULL);
//
// 标题
//
setbkmode (TRANSPARENT);
settextcolor (WHITE);
settextstyle (32, 16);
outtextxy (300, 30, "Image Scale Demo");
settextcolor (LIGHTCYAN);
settextstyle (16, 8);
outtextxy (300, 80, "Original: 100x100");
putimage (300, 110, &Sprite);
//
// 50% 缩放(50×50)
//
if (!EFI_ERROR (scaleimage (&Scaled50, &Sprite, 50, 50))) {
setlinecolor (LIGHTGREEN);
setlinestyle (PS_DASH, 1);
rectangle (470, 110, 520, 160);
settextcolor (LIGHTGREEN);
outtextxy (450, 85, "50%: 50x50");
putimage (470, 110, &Scaled50);
DeleteImage (&Scaled50);
}
//
// 75% 缩放(75×75)
//
if (!EFI_ERROR (scaleimage (&Scaled75, &Sprite, 75, 75))) {
setlinecolor (YELLOW);
setlinestyle (PS_DASH, 1);
rectangle (640, 110, 715, 185);
settextcolor (YELLOW);
outtextxy (630, 85, "75%: 75x75");
putimage (640, 110, &Scaled75);
DeleteImage (&Scaled75);
}
//
// 150% 缩放(150×150)
//
if (!EFI_ERROR (scaleimage (&Scaled150, &Sprite, 150, 150))) {
setlinecolor (LIGHTMAGENTA);
setlinestyle (PS_DASH, 1);
rectangle (300, 350, 450, 500);
settextcolor (LIGHTMAGENTA);
outtextxy (290, 320, "150%: 150x150");
putimage (300, 350, &Scaled150);
DeleteImage (&Scaled150);
}
//
// 200% 缩放(200×200)
//
if (!EFI_ERROR (scaleimage (&Scaled200, &Sprite, 200, 200))) {
setlinecolor (LIGHTCYAN);
setlinestyle (PS_DASH, 1);
rectangle (550, 280, 750, 480);
settextcolor (LIGHTCYAN);
outtextxy (540, 250, "200%: 200x200");
putimage (550, 280, &Scaled200);
DeleteImage (&Scaled200);
}
DeleteImage (&Sprite);
}
//
// 使用说明
//
setbkmode (TRANSPARENT);
settextcolor (LIGHTGREEN);
settextstyle (14, 7);
outtextxy (50, 680, "Algorithm: Bilinear Interpolation (16.16 fixed-point arithmetic)");
outtextxy (50, 700, "Press ESC to exit");
//
// 一次性刷新。
//
EndBatchDraw ();
//
// 等待 ESC 键退出。
//
Running = TRUE;
while (Running) {
getmessage (&Msg, EX_KEY);
if (Msg.message == WM_KEYDOWN && Msg.vkcode == VK_ESCAPE) {
Running = FALSE;
}
}
//
// 关闭设备。
//
closegraph ();
//
// 恢复文本控制台。
//
gST->ConOut->ClearScreen (gST->ConOut);
Print (L"scaleimage Demo 完成\n");
return EFI_SUCCESS;
}
运行结果如下:

完整的代码和编译后的 EFI 如下: