跳转到主要内容

图像压缩

TouchGFX从4.22版开始支持图像压缩。 4.22版到4.23版仅支持L8图像压缩。 4.24版开始,支持RGB565、RGB888和ARGB8888图像格式压缩。 From version 4.27 hardware accelerated decompression with the Chrom-DEC decoder is supported.

图像压缩是降低图像存储需求的过程。如果使用较小的闪存,缩减项目中的图像存储空间可以降低成本。缩减还意味着可以在项目中使用更多的图像,从而获得更丰富的UI。

图像压缩通常有两种风格:无损或有损。有损图像压缩通过去除图像的微小细节来实现。这样通常会得到最大的缩减,但原始图像无法准确再现。无损压缩总是无任何差异地再现原始图像。无损压缩的尺寸缩减通常较小。

对于图形,通常要求UI元素完全按照其设计来绘制。因此,TouchGFX只支持无损压缩。

图像压缩的优点是存储空间减少,但也有缺点,因为图像在绘制到帧缓存时必须解压缩。与绘制未压缩的图像相比,这种解压缩在许多情况下需要CPU做更多的工作。结果可能是性能下降。

这意味着必须将闪存减少带来的优势与CPU使用率增加带来的劣势进行比较。

Be aware that the graphics accelerators DMA2D and GPU2D (Chrom-ART and NeoChrom GPU) present in many STM32 micro controllers cannot draw a compressed image directly. 压缩图像采用软、硬件混合渲染绘制,即:压缩数据由软件按块解压缩,再适时将这些数据块委托给DMA2D。

Some STM32 micro controllers contain the Chrom-DEC (GFXPAND) compressed graphics decoder. On these platforms L8 RLE and RGB compressed images are decompressed by hardware, which significantly improves the performance and lowers the CPU load. See the section below about hardware accelerated decompression.

许多应用中,不建议压缩所有图像,而是只压缩那些性能不受影响且与减少闪存相关的图像。另请参阅以下关于解压缩到位图缓存的部分,以获得更低的存储要求和良好的性能。

L8压缩​

如上所述,TouchGFX 4.22支持L8图像压缩。回想一下,L8位图格式仅适用于高达256色的图像。每个像素只是一个8位数字,表示与图像一起存储的颜色表中的一种颜色。 L8压缩仅压缩像素数。颜色表保持不变。

以下图为例。其在计量应用中用作背景。

L8-ARGB8888

图像为184 x 184像素。因此,像素数据的大小为184×184=33,856字节。

如果我们压缩图像,像素数据将减少到5,735字节。包括颜色表在内的压缩图像数据总尺寸小于原始图像的20%。因此,压缩可以让我们在同一Flash空间中拥有5个不同的背景,或者将Flash需求减少28,121字节。

压缩的L8图像像普通的未压缩位图一样使用。 You can for example show the image using the Image widget without any modification to the project in TouchGFX Designer or in code. 这样一来,就能轻松地使用压缩L8图像。

三种算法​

TouchGFX对于L8格式采用了三种不同的压缩算法。图像转换器选择提供最佳压缩的算法,除非用户在配置中强制使用特定算法。算法包括:

  • L4,对每个像素进行4比特编码。仅适用于最多16种颜色的图像。
  • RLE,像素的游程编码。仅适用于最多64种颜色的图像。
  • LZW9,基于词典的编码。适用于所有L8图像。

RLE算法的解压缩速度比LZW9快得多,因此如果LZW9仅压缩图像,转换器将选择RLE稍微好一点。

On platforms with the Chrom-DEC decoder, the RLE algorithm is decompressed by hardware. Select "RLE" instead of "Auto" to make sure that your L8 images are hardware accelerated. See Hardware Accelerated Decompression.

RGB压缩​

如前所述,TouchGFX 4.24支持RGB565、RGB888和ARGB8888图像格式的压缩。包含超过256种纯色的图像不能以紧凑L8图像格式存储,而必须以上述格式之一存储。 RGB565、RGB888或ARGB8888图像压缩采用16位、24位或32位像素直接压缩。

以下图为例。其背景较上文示例更为复杂且丰富,拥有超过256种纯色。因此,不能以L8存储,而必须采用ARGB8888格式存储,因其具有透明像素(位于角落)。

ARGB8888

图像为240 x 240像素。那么,像素数据的大小为240 x 240 x 4=230.400字节,因为我们用4个字节以ARGB8888图像格式存储每个像素。

压缩图像会将大小降至32.347字节。压缩图像的大小要小得多,只有原始图像的14%。压缩允许我们在同一个Flash空间中拥有多个复杂的背景,或大量减少Flash需求。压缩还能使限制Flash使用率的设备采用比L8格式更复杂、更丰富的图形。

压缩的RGB图像可像普通的未压缩位图一样使用。 You can for example show the image using the Image widget without any modification to the project in TouchGFX Designer or in code. 这样一来,就能轻松地使用压缩RGB图像。

Caution
某些情况下,对RGB图像应用任何抖动算法都会损害RGB压缩的效果。

两种算法​

TouchGFX使用两种略有差别的压缩算法,根据要压缩的图像格式自动选择。算法包括:

  • QOI使用Quite OK图像格式压缩算法的变体对RGB888和ARGB8888像素进行编码。
  • QOI565使用为16位像素值定制的QOI变体对RGB565像素进行编码。

RGB压缩算法的两种变体均针对快速解压缩速度进行了优化,以限制渲染压缩RGB图像时的运行时性能损失。 On platforms with the Chrom-DEC decoder, both variants are decompressed by hardware.

Hardware Accelerated Decompression​

The Chrom-DEC compressed graphics decoder, known as GFXPAND in code and in STM32CubeMX, is a hardware accelerator that decompresses compressed images. It is currently available in the STM32U3A6 microcontrollers.

Chrom-DEC accelerates the following compression algorithms:

Compression algorithmImage formatsAccelerated by Chrom-DEC
L4L8_RGB565, L8_RGB888, L8_ARGB8888No
RLEL8_RGB565, L8_RGB888, L8_ARGB8888Yes
LZW9L8_RGB565, L8_RGB888, L8_ARGB8888No
QOI565RGB565Yes
QOIRGB888, ARGB8888Yes

When Chrom-DEC is enabled in the TouchGFX Generator, TouchGFX automatically uses it to draw L8 RLE and RGB compressed images. The decompressed pixels are written to the framebuffer by DMA, and Chrom-ART (DMA2D) is used when the pixels must be blended with the background. This gives a performance improvement compared to decompressing the images in software, and the CPU is free to do other tasks while the image is drawn.

Further reading
Read more about Chrom-DEC in the Image compression on Chrom-DEC article, and how to enable it in the TouchGFX Generator.

使用压缩图像​

启用图像压缩功能​

图像压缩需要目标应用程序中的额外代码。为了避免较高的空间需求,某些平台可选择压缩代码。您可以为项目启用该功能。

Click "Config" on the left of TouchGFX Designer, then click "Framework Features"

启用图像压缩

图像压缩功能在底部显示。您可以启用您需要的特定功能集。

目标具有不同的框架功能选项,某些情况下,目标没有可选功能,如下所示:

无可选框架功能

这种情况下,所有功能始终启用。

On platforms with the Chrom-DEC decoder, L8 RLE and RGB compressed images are decompressed by hardware on target. It is therefore recommended to disable the RLE feature (under L8 Image Compression) and the RGB Image Compression feature to save code size. The L4 and LZW9 features must still be enabled if you use these algorithms, as they are always decompressed by software.

Caution
Be aware that TouchGFX Designer does not show an error or warning if you use a feature that is not enabled. 如使用图像压缩,但未启用该功能,则不会绘制图像。

L8压缩​

压缩图像和普通图像用法相同。 You either configure widgets to use the bitmaps in TouchGFX Designer, or you assign the Bitmaps in code.

配置L8-ARGB888图像压缩

唯一需要的配置是将“压缩”值设置为“自动”。然后,图像转换器将自动选择最合适的压缩,或者如果图像不可压缩则不选择。

选择控件的压缩图像

现在,我们可以正常选择控件的图像。与未压缩的图像相比,没有什么区别。

使用代码中的图像也没有区别。通常用压缩位图的BitmapID来进行引用:

    image1.setXY(148, 148);
image1.setBitmap(touchgfx::Bitmap(BITMAP_GAUGE_BACKGROUND_ID));

在此阅读有关压缩L8图像的更多信息

RGB压缩​

在TouchGFX设计器中RGB565、RGB888或ARGB8888图像的压缩过程与L8压缩相同。

配置L8-ARGB888图像压缩

如选择“是”,图像转换器将使用与图像格式匹配的算法压缩图像。

与L8压缩一样,我们通常可以为控件选择图像,并在代码中引用位图。

压缩等级​

图像转换器选择的压缩算法会写入生成的文件中。在这里我们还可以找到压缩等级。

我们在上文L8压缩示例中使用的图像生成到文件generated/images/src/image_gauge_background.cpp中。此文件的标题为:

image_gauge_background.cpp (extract)
// 4.22 D0 AN R0 FL8_ARGB8888 U888 N0 SExtFlashSection EExtFlashSection CL8_LZW9

LOCATION_PRAGMA("ExtFlashSection")
KEEP extern const unsigned char image_gauge_background[] LOCATION_ATTRIBUTE("ExtFlashSection") = {
// 184x184 L8_ARGB8888 pixels. 压缩[输出/输入x 100]:5735/33856 x 100 = 16.9% 0x00, 0x26, 0x50, 0xa8, 0x60, 0xe1, 0x02, 0x86, 0x0c, 0x1a, 0x36, 0x70, ....

第一行注释的末尾显示了压缩算法。这里,我们看到图像转换器已经选择了LZW9算法。第5行的末尾显示,我们现有5735字节的像素数据,而原来是33856字节。结果压缩到16.9%(压缩级别越小越好)。注意!压缩率不包括颜色表。

压缩失败​

某些情况下,图像转换器在压缩图像时会出现警告或错误。这是因为图像与所选算法不兼容,或者压缩图像的大小未低于原始图像的90%。这种情况仅在极少数的巧合下才会发生。例如,一个5 x 5的小图像使用25种不同的色彩。由于图像中无重复或冗余,所以压缩不可能减少数据。

L8图像​

对于L8图像,其中的原因是选择了与给定图像不匹配的特定算法。例如,当图像包含17种或更多颜色,并且选择了L4压缩,则不能使用所选算法来压缩图像。 The Image Converter will print an error message when you generate code, and TouchGFX Designer will show an error message:

特定算法的压缩误差

解决该问题的方法是使用另一种算法。首选方式是为L8图像选择“自动”。然后,图像转换器将尝试所有算法,并选择适用的最佳算法。

某些罕见情况下,图像不会压缩到原始大小的90%以下。此时,图像转换器不会压缩图像并发出警告文本,如下所示:

压缩警告

不压缩的原因是节省的Flash大小不会对渲染性能有所改善。可以不使用“自动”,而是选择一种算法(L4、RLE或LZW)来强制压缩。

警告消息仅为提供信息。代码生成仍在继续,项目将按预期进行。

RGB图像​

对于RGB图像格式,您不能选择“自动”,因为只有一种压缩算法。如果您选择“是”,且图像无法压缩到原始大小的90%以下,则图像转换器将生成错误:

RGB图像压缩错误

解决方案是针对图像压缩选择“无”。

将图像解压缩到位图缓存​

大多数情况下,绘制压缩图像的性能比绘制未压缩图像差。此外,如引言中所述,STM32微控制器(DMA2D和GPU2D)中的图形加速器无法直接绘制压缩图像。因此,压缩图像由软件和硬件混合绘制,导致性能较低,cpu负载较高。 Even on platforms with the Chrom-DEC decoder, compressed images cannot be used with widgets that scale or rotate the image (see Limitations).

出于这些原因,TouchGFX还包含在运行时将压缩图像解压缩到RAM中位图缓存的功能。

当图像被解压缩到RAM时,绘制性能类似于使用未压缩的图像,加速器可以绘制图像。

要解压缩,我们首先需要设置位图缓存。在此阅读有关使用位图缓存的更多信息。

设置位图缓存后,我们可以使用函数Bitmap::decompress来解压缩图像。完整代码如下所示:

// Define an array for the bitmap cache
uint16_t cache[20*1024]; //40 KB cache
// Define an array for the decompression temporary buffer
uint16_t lzwBuffer[1024];

void TemplateView::setupScreen()
{
...
Bitmap::setCache(cache, sizeof(cache)); // Register the bitmap cache
bool r = Bitmap::decompress(BITMAP_GAUGE_BACKGROUND_ID, lzwBuffer); // Decompress the bitmap
image1.setBitmap(touchgfx::Bitmap(BITMAP_GAUGE_BACKGROUND_ID)); // Use the bitmap as normal
image1.setXY(148, 148); // Position Image widget
}

此例中,我们想将上文L8压缩示例中的184 x 184图像解压缩到位图缓存中。位图缓存必须足够大才能容纳未压缩的图像。 184 x 184像素加上包含207种ARGB8888色的颜色表。因此,总大小为34,688字节。

此例中,我们使用LZW9算法。在LZW9压缩图像的解压缩期,解压缩器使用2048字节的缓冲区(用于构建字典)。解压缩后不再需要缓冲区,可以重新用于其他目的。 L4、RLE、QOI或QOI565压缩图像的解压缩不需要缓冲区。

当不再使用解压缩图像时,可以使用Bitmap::cacheRemoveBitmap将其从位图缓存中移除。

限制程序大小​

如果使用位图缓存解压缩,则可通过一些选项来限制程序的大小。如上所述,有两种图像压缩;L8和RGB。使用Bitmap::decompress时,您的程序将包含解压缩L8和RGB图像的代码。如果只使用RGB图像压缩,则可用专用方法将RGB图像解压缩到位图缓存中,即Bitma::depressRGB,这样您的程序将只包含解压缩RGB图像所需的代码。如果只使用L8压缩,也同样适用,这里的方法称为Bitmap::decompressL8。参见以下示例。

void TemplateView::setupScreen()
{
...
// Decompress the bitmap (RGB using QOI)
bool r = Bitmap::decompressRGB(BITMAP_GAUGE_BACKGROUND_ID);
...
}
void TemplateView::setupScreen()
{
...
// Decompress the bitmap (L8 using RLE, no buffer required)
bool r = Bitmap::decompressL8(BITMAP_GAUGE_BACKGROUND_ID);
...
}

Hardware accelerated decompression to the bitmap cache​

On platforms with the Chrom-DEC decoder, RGB compressed images can be decompressed into the bitmap cache by hardware using the method Bitmap::decompressHW. This is much faster than decompressing the image in software, and your program will not contain the software decoder for RGB images.

void TemplateView::setupScreen()
{
...
// Decompress the bitmap (RGB using Chrom-DEC)
bool r = Bitmap::decompressHW(BITMAP_CLOCK_BACKGROUND_ID);
...
}

Bitmap::decompressHW only supports RGB compressed images (RGB565, RGB888, and ARGB8888). L8 compressed images must be decompressed using Bitmap::decompress or Bitmap::decompressL8. In the simulator, Bitmap::decompressHW decompresses the image in software.

限制​

处理压缩图像时存在一些限制。压缩图像不能与缩放或旋转图像的控件、填充区域的控件或画布控件一起使用。

将压缩图像用于不兼容的控件。

Caution
压缩图像不能与所有控件一起使用。 TouchGFX Designer gives you a warning icon.

此类限制出于性能原因而制定。 TouchGFX Designer will not allow you to select a compressed image.

如果你想在这些控件中使用一个特定的图像,我们建议不要对图像进行压缩。或者,您可以在运行时解压缩图像。

不支持压缩图像的控件有:

  • 纹理映射
  • 可缩放图像
  • 指针和弧形仪表
  • 用于填充图形下方区域的静态和动态图表
  • 指针模拟时钟
  • 圆、线和形状
  • 圆形和线形进度条