做一个 UEFI 下的 EasyX 图形库(12)

增加一个缩放图像功能函数:

/**
  缩放图像(双线性插值或最近邻)。

  @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 如下:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注