跳转到主要内容

使用L8图像格式减少存储空间消耗

L8格式的图像占用的闪存空间较少,比诸如ARGB8888等格式的绘制速度更快。

L8格式的图像包含调色板和像素数组:调色板包含了指定的至多256种颜色,可以为16位RGB565格式、24位RGB888格式或32位ARGB8888格式。 像素数组包含每个像素一个字节的数据。 该字节数据是调色板(颜色列表)索引,指向像素的颜色。 为了绘制L8图像,TouchGFX框架逐一读取像素,在调色板中查找颜色,再将其写入帧缓冲。 这些操作是自动完成的,如果硬件支持,可以通过STM32 Chrom-ART硬件加速器进行加速。

每像素8位意味着一幅L8图像可使用256种不同颜色。 另一幅L8图像可使用256种其他颜色,这是因为两幅图像各有自己的调色板。

一幅有4 x 4个像素的L8图像和一个包含4种颜色的调色板

每个像素一个字节(8位)。 因此,像素数据大小等于(宽度 x 高度)个字节。 调色板颜色可以是16位、24位或32位颜色。 因此,每种颜色定义将占用2、3或4个字节。

立体图像应存储在L8_RGB888中。 如果图像是透明的,则必须使用32位格式(ARGB8888):

格式帧缓冲格式支持透明像素 DMA2D支持
L8_RGB56516位RGB565
L8_RGB88824位RGB888
L8_ARGB8888二者兼有

DMA2D不支持带RGB565调色板的L8格式。 这意味着绘制这种格式的图像不会执行硬件加速。 因此,除非您使用的平台没有DMA2D(例如:STM32G0或STM32F410),否则不应使用这种格式。

如果您使用了一个串行Flash(非存储映射)来存储图像,并使用了一个16位帧缓存(格式为RGB565),那么您应该使用L8_RGB565格式,因为色彩格式与帧缓存格式匹配,且复制到帧缓存会更快。

下表显示了首选的L8格式:

帧缓冲格式有DMA2D的平台 无DMA2D的平台
RGB565L8_RGB888L8_RGB565
RGB888L8_RGB888L8_RGB888
ARGB8888L8_RGB888L8_RGB888

透明图像应始终使用L8_ARGB8888格式。

Further reading
  • 点击链接阅读关于调色板图像格式的更多内容:https://en.wikipedia.org/wiki/Indexed_color
  • L8图像

    这是一幅典型的徽标图像。 这幅图像只使用了16种不同颜色:

    200 x 200像素L8图像,有16种24位颜色。

    此图像占用的闪存空间明显小于标准24位格式(RGB888)的原始图像。 下表列出了此实际图像使用三种不同调色板格式和非L8格式的闪存占用量。

    格式像素大小(字节)调色板大小(字节)总大小(字节)缩减率(%)
    RGB888120,0000120,000-
    L8_RGB56540,0003240,03266.6
    L8_RGB88840,0004840,04866.6
    L8_ARGB888840,0006440,06466.6

    我们看到图像大小缩减率很大,调色板的大小在中等尺寸图像上显得微不足道。

    在TouchGFX Designer中使用L8图像

    TouchGFX中L8图像格式的使用十分简单。 只需配置图像转换器,以便将图像从PNG转换为L8格式。 下面我们将介绍整个过程:

    在TouchGFX Designer中启动一个新工程。 将图像复制到新工程中的assets/images文件夹:

    TouchGFX工程的Images文件夹

    现在转至TouchGFX Designer,点击顶部导航栏中的“图像”选项卡并选中图像:

    进入TouchGFX Designer的图像视图

    在窗口右侧,选择图像格式L8_RGB888(本例运行24位颜色)。

    现在,可以在画布上插入一个图像控件(这里我们在背景上插入了一个方框):

    TouchGFX Designer中画布上的图像控件

    无需在UI代码中做任何修改。 根据我们在“图像”选项卡上所做设置,图像转换器转换PNG文件并生成L8格式的图像。

    透明图像

    如前面所述,还可以对透明图像使用L8图像。

    32位ARGB8888格式的170 x 60像素按钮图像

    以上图像使用了108种颜色(许多色度的蓝色)。 此图像可使用格式L8_ARGB8888。 大小将显著缩减:

    格式像素大小(字节)调色板大小(字节)总大小(字节)缩减率%
    ARGB888840,800040,800-
    L8_ARGB888810,20043210,63273.9%

    Moving the palette to internal flash

    On platforms that uses non-memory-mapped flash for the images (for example the STM32G0, STM32U0, or STM32C0), it is required to move the L8 palette data to internal flash. Otherwise the L8 images will not be drawn.

    Configure location of extra data for an image to be in internal flash.

    The palette of an image can be moved to internal flash by changing the "Extra Section" to "IntFlashSection" in the TouchGFX Designer (Open the Images tab, find your image, and go to the right-most column).

    L8图像压缩

    通过选择L8图像压缩,可以进一步减少内存消耗。 图像转换器支持三种压缩算法(L4、RLE、LZW9)。 在TouchGFX Designer中,您可以将压缩值设置为“自动”,使图像转换器为您的图像选择合适的算法,或者您也可以强制使用特定的算法。 在某些情况下,内存减少的好处是以CPU负载增加为代价,因为在绘制图像时会直接解压缩到帧缓存。

    选择L8图像压缩

    Note
    L8压缩图像默认禁用抖动算法和阿尔法抖动。 如需要,请在每个L8图像上选择特定的抖动算法和阿尔法抖动。

    L8图像压缩有一个默认设置,可在TouchGFX Designer的默认图像配置选项卡上进行配置,请参阅以下屏幕截图。 在这里,您可以选择整个应用程序的默认设置。

    L8图像默认压缩设置

    Caution
    不是所有控件都可以使用压缩图形。 请参阅列表
    Further reading

    下文中,我们将使用之前的L8图像来演示每种算法的压缩能力和解压缩性能。

    我们将STM32F429-DISCO与包含4个屏幕的应用程序一起使用,具有不同的压缩:

    • 无压缩
    • L4压缩
    • RLE压缩
    • LZW9压缩

    STM32F429-DISCO上运行L8图像的示例屏幕(240x320)

    Note
    DMA2D被禁用,仅比较软件渲染。
    格式压缩像素大小
    (字节)
    调色板+标题的大小
    (字节)
    总大小
    (字节)
    缩减率
    (%)
    性能
    (渲染时间,毫秒)
    RGB56580,000080,0000-
    L8_RGB56540,00032 + 440,03650.02.12
    L8_RGB565L420,00032 + 420,03675.02.34
    L8_RGB565RLE3,19732 + 1643,39395.71.66
    L8_RGB565LZW94,47532 + 1684,67596.17.45

    上表显示了压缩后的内存减少情况和解压缩绘制图像性能。 Both the compression (reduction) and decompression (performance) highly relies on the complexity of the image and number of colors. Each algorithm has its limits of application, meaning, L4 is limited to 16 colors, RLE is limited to 64 colors and LZW9 works for all L8 images, i.e. no limits. 此外,L4和RLE在绘制图像时实际上比LZW9表现得更好,但如前所述,它们不能覆盖所有L8图像。 All algorithms will decrease in performance if the image is clipped. In general this means you always have to consider the number of colors (quality requirement), the flash memory available (reduction requirement) and the complexity of your application (animations) when you use L8 image compression. 例如, 如果您有一个超过64种颜色的图像,并且你使用LZW9,但性能损失太大,如果质量要求允许,则可以尝试将图像中的颜色数量减少到64种或更少,然后选择RLE。 如果这不可行,那么你最好使用未压缩的L8图像。 请参阅ImageMagick了解如何减少图像中的颜色。

    如果您不打算在应用程序中使用L8图像压缩,则应禁用该功能,下面是TouchGFX 设计器的屏幕截图,展示了具体方法。

    禁用L8图像压缩

    控件中压缩和未压缩的L8图像示例

    尽管L8图像压缩不能用于所有控件,但在由多个图像组成的控件中,如:仪表和模拟时钟,仍然可以压缩某些图像,而不压缩其他图像。 下面的示例显示了在仪表控件中如何压缩背景而不压缩指针。

    仪表控件中使用的图像

    仪表控件

    将图像转换为256色或以下

    许多图像使用的颜色多于256种。 这对照片级真实感的图像或有渐变梯度的图像而言很常见。 由于这些图像包含多种颜色,因此不能在TouchGFX Designer中直接转换为L8图像格式。

    但是,在许多情况下,可以减少特定图像中使用的颜色数量。 在理想情况下,平面设计师可以转换或提供256色图像,而图像操作工具也可以执行转换,同时不会过度损失图像质量。

    Paint.NET

    最简单的办法是使用Paint.NET。 打开原始图像,使用“另存为”将图像保存为另一个文件。 在“保存设置”对话框中,选择8位像素深度:

    Paint.NET将图像保存为8位格式

    现在,在工程中使用新的PNG。 记得在TouchGFX Designer中的“图像”选项卡上选择L8_ARGB8888格式。 在许多情况下,阴影处理的不够好,但有透明边缘的图标看起来不错。 可以调整“透明度阈值”,在某些情况下可以改善效果。

    ImageMagick

    另一种合适的工具是ImageMagick(从www.imagemagick.org下载),有时也能获得更好的L8图像。 此工具可以通过命令行转换图像。 适合在脚本中用。 使用以下命令,可将clock_bg.png转换为使用至多256种颜色的图像:

    magick convert clock_bg.png -colors 256 clock_bg_l8_256.png

    在启用RLE或L4压缩算法的情况下,也可以将颜色减少到256色以下。

    magick convert clock_bg.png -colors 64 clock_bg_l8_64.png

    ImageMagick还可以告诉您图像中使用了多少种颜色。 使用下面命令:

    magick identify -format %k Blue_Buttons_Round_Edge_small.png

    比较

    下面比较了三幅图像(原图、使用Paint.NET的L8图像和使用ImageMagick的L8图像):

    钟表图像比较,从左到右为:原图、Paint.NET生成图,ImageMagick生成图

    中间的钟表丢失了边界阴影中的细节。 在这两种情况下,时钟背景的中央部分看起来都是可以的。

    手动配置

    不使用TouchGFX 设计器也可以选择图像格式和压缩算法。 指定设置的文件application.config位于项目根目录中:

    application.config
    {
    "image_configuration": {
    images": {
    "Blue_Buttons_Round_Edge_small.png": {
    "format": "L8_ARGB8888",
    "l8_compression": "LZW9"
    }
    },
    "dither_algorithm": "2",
    "alpha_dither": "yes",
    "layout_rotation": "0",
    "opaque_image_format": "RGB888",
    "nonopaque_image_format": "ARGB8888",
    "section": "ExtFlashSection",
    "extra_section": "ExtFlashSection",
    "l8_compression": "yes"
    }
    }

    “Image_configuration”下的“images”部分指定了每幅图像的格式。 在这里没有提及的图像将会以默认格式(opaque_image_format或nonopaque_image_format)生成。

    我们建议使用TouchGFX Designer进行图像设置(如可能)。