试用 LVGL Pro,一套完整的工具包,助您高效构建、测试、分享和交付 UI!
LVGL
教程

在 LVGL 中捕获屏幕快照

学习如何使用二进制文件导出和 ImageMagick 捕获 LVGL 屏幕快照,用于像素级分析和自动化 GUI 测试。

Mario Rubio GomezMario Rubio Gomez5 分钟阅读

什么是屏幕快照?#

屏幕快照允许你将 LVGL 在显示器上渲染的内容精确捕获为二进制文件。可以将其视为嵌入式 GUI 的"打印屏幕"按钮,将每个像素保存到磁盘。

本教程向你展示如何在 LVGL 项目中实现快照捕获。虽然具体实现可能需要适应你的代码库,但核心概念普遍适用。

为什么捕获屏幕快照?#

屏幕快照有两个主要用例:

**像素级分析:**在 GIMP 等工具中打开捕获的图像有助于你分析精确的颜色、测量元素位置并微调 GUI 布局。这在完善主题或调试视觉问题时非常宝贵。

**自动化 GUI 测试:**通过将当前输出与参考图像进行比较,你可以自动检测意外的视觉回归。这对于在项目演进时保持 GUI 质量至关重要。

捕获显示缓冲区#

第一步是将整个显示缓冲区 flush 到二进制文件。以下是实现:

全局变量#

static FILE* pFileOut;
static BOOL_E bSnapshot;
c

快照触发函数#

创建一个函数来启动快照捕获:

/** Flush 缓冲区。
 *
 * 将缓冲区 flush 到二进制文件。
 *
 * @note: 数据像素应格式化为 uint32_t RGBA。Imagemagick 要求。
 *
 * @param[in] pFileName   输出二进制文件名。
 *
 */
void DISP_IMPL_flushBuffer (const char_t* pFileName)
{
  pFileOut = fopen(pFileName, "w");
 
  if (pFileOut == NULL) {
    printf(("[Display] error: %s cannot be opened", pFileName));
    return;
  }
 
  bSnapshot = BOOL_TRUE;
  lv_obj_invalidate(lv_scr_act());
  lv_refr_now();                    /* 将调用我们的 disp_drv.disp_flush 函数 */
  bSnapshot = BOOL_FALSE;
 
  fclose(pFileOut);
  printf(("[Display] data flushed to %s", pFileName));
}
c

将像素写入文件#

修改显示 flush 回调函数,在快照模式激活时写入像素数据:

void APP_DISP_lvgl_flush (const lv_color_t* pData, const DISPLAY_BOUNDS_T* const pPxBounds)
{
  uint32_t data;
  if (bSnapshot == BOOL_TRUE) {
    for (uint32_t i = 0; i < (pPxBounds->dimension.width * pPxBounds->dimension.height); i++) {
      data = DISP_IMPL_lvgl_formatPixel(pData[i]);  /* 将 LittlevGL 像素格式转换为 RGB888 的函数 */
      fwrite(&data,
             sizeof(uint32_t),
             1,
             pFileOut);
    }
  }
}
c

像素格式转换#

将像素转换为所需的输出格式。此示例将 RGB565 转换为 RGB888 并校正灰度颜色:

/** 将 lvgl RGB565 像素转换为 RGB888 像素
 *
 * @note: 将潜在的灰色转换为真正的灰色。
 *
 */
static uint32_t DISP_IMPL_lvgl_formatPixel (lv_color_t color){
 
  lv_color32_t data = (lv_color32_t) lv_color_to32(color);
  uint8_t aux;
 
  /* 将潜在的灰色转换为真正的灰色 */
  if (color.red == color.blue) {
    uint32_t dif = data.green - data.red;
    if (dif <= 8) {
      data.red += dif;
      data.blue += dif;
    }
  }
 
  /* BGR 转 RGB */
  aux = data.blue;
  data.blue = data.red;
  data.red = aux;
 
  return data.full;
}
c
适应你的色深

像素格式转换取决于你的 LV_COLOR_DEPTH 设置。调整 DISP_IMPL_lvgl_formatPixel 函数以匹配你的显示配置。

将二进制文件转换为图像#

捕获二进制数据后,使用 ImageMagick 将其转换为标准图像格式:

#!/bin/bash
# convert_bin_images.bash
OUT_BIN_LIST="${IMAGES_DIR}/*.bin"
for BIN_FILE in $OUT_BIN_LIST
do
  convert -size 320x240 -depth 8 rgba:${BIN_FILE} ${BIN_FILE}.bmp
done
bash

调整 -size 参数以匹配你的显示分辨率。

自动化 GUI 测试#

将捕获的快照与参考图像进行比较以检测视觉回归:

#!/bin/bash
#run_test.bash
 
for i in ${BIN_LIST[@]}
do
  diff -q ${IMAGES_DIR_OUT}/$i ${IMAGES_DIR_REF}/$i
  if [ $? != 0 ]; then
    $SCRIPT_DIR/convert_bin_images.bash ${IMAGES_DIR_REF}/$i
    compare ${IMAGES_DIR_OUT}/$i.bmp ${IMAGES_DIR_REF}/$i.bmp -compose src ${IMAGES_DIR_OUT}/diff_$i.png
    TEST_SUITE_OK=0
  fi
done
 
if [ $TEST_SUITE_OK -eq 0 ]; then
  exit 1
fi
bash

当检测到差异时,ImageMagick 的 compare 命令会生成一个差异图像,突出显示视觉差异发生的确切位置。

示例输出#

以下是展示快照比较在实践中如何工作的示例:

测试运行的输出快照
当前测试输出
用于比较的参考快照
用于比较的参考图像
突出显示更改像素的视觉差异
显示图像差异位置的差异可视化

差异图像清楚地显示了参考和当前输出之间哪些像素发生了变化,使得很容易识别意外的视觉变化或验证有意的更新。

关于作者

Mario Rubio Gomez
Mario Rubio Gomez

社区贡献者

嵌入式开发者和 LVGL 社区贡献者,专注于显示驱动开发和 MicroPython 集成。

认识博客背后的作者们

了解那些分享 LVGL 知识的优秀作者们

查看作者

订阅我们的通讯 不错过任何关于 LVGL 的新闻。我们每月最多发送 2 封邮件。

LVGL

LVGL 是最受欢迎的免费开源嵌入式图形库,支持任何 MCU、MPU 和显示类型,助您构建精美的用户界面。

我们还提供 UI 设计、实现和咨询等服务。

© 2026 LVGL。保留所有权利。
YouTubeGitHubLinkedIn