快閃記憶體受限的GUI開發
本文說明如何在使用少量快閃記憶體的情況下以TouchGFX開發圖形使用者介面。
使用TouchGFX產生程式碼時,圖像、文字及字型等資產會轉換為C++檔案,然後在程式設計期間與TouchGFX應用程式碼、使用者程式碼及TouchGFX庫一同儲存在快閃記憶體中。 因此如果是具有眾多資產的大型或複雜專案,將會使用大量快閃記憶體。
由於大部分應用程式的記憶體資源都有限,有一些方法可以減少所需的快閃記憶體容量。 TouchGFX有四種內建功能,可協助您大幅減少應用程式所需的快閃記憶體容量。 這四種概念為L8圖像格式、圖像壓縮、可縮放向量圖形(SVG)及向量字型。
本文將介紹如何使用這四種概念,以限制應用程式的快閃記憶體佔用空間。 測量是以STM32U5G9J-DK2執行,不過節省快閃記憶體的概念也可應用於其他硬體平台。
Further reading
如需記憶體管理的詳細資訊,請閱讀記憶體使用一文。
快閃記憶體受限的電動自行車示範
快閃記憶體受限的電動自行車示範,展示如何使用前述四種功能以TouchGFX節省快閃記憶體;您可在TouchGFX Designer之中參考此示範。 此示範為開發板專屬示範,適用於STM32U5G9J-DK2。 使用STM32U5G9J-DK2的優點之一就是其中具有NeoChromVG GPU,由硬體加速向量渲染。 不過L8圖像格式及圖像壓縮特別適合在所有STM32 MCU使用。
如果此示範僅以未壓縮的點陣圖實作(無L8、壓縮、SVG及向量字型),可能會佔用約10.5 MB的快閃記憶體。 在使用四種概念節省快閃記憶體的實作中,此示範僅佔用約800 KB的快閃記憶體。 由此可見,節省大量快閃記憶體是可能做到的。 這四種概念在示範中合計節省了92%的快閃記憶體空間。
各種概念的使用時機
以下是如何以TouchGFX使用四種概念節省快閃記憶體的技術資訊和指南:
這四種概念都能協助減少應用程式所需的快閃記憶體容量。 每種概念的使用時機需視情境而定,不過有些一般規則可供參考。 以下將進行說明。
L8及壓縮
在點陣圖使用L8圖像格式時,點陣圖最多會有256種色彩。 L8格式資產渲染是以Chrom-ART進行硬體加速,因此L8點陣圖的渲染時間幾乎與一般點陣圖相同。 有時渲染L8格式點陣圖的速度甚至比一般點陣圖更快,原因是從快閃記憶體讀取的資料較少。 相較於色深32位元的一般點陣圖,L8可節省70%以上的快閃記憶體。
相較於L8,圖像壓縮可讓您節省更多快閃記憶體。 圖像壓縮有兩種格式:L8壓縮和RGB壓縮。 若要在點陣圖使用L8壓縮,首先點陣圖要採用L8格式,因為L8壓縮演算法會使用色彩查閱資料表。 因此,L8壓縮後的點陣圖仍有最多256色的限制。 部分L8壓縮演算法會進一步限制色彩數量上限。 L4限制為最多16種色彩,L8 RLE則限制為最多64種色彩。 RGB壓縮不要求點陣圖需為L8格式,因此適用於所有點陣圖。 L8點陣圖渲染是以Chrom-ART進行硬體加速,壓縮點陣圖(L8壓縮和RGB壓縮皆同)則不一樣,是以軟體進行渲染,因此渲染成本更高。 壓縮點陣圖的另一項限制,則是無法用於可縮放或可旋轉的小工具。
如果您的資產已經採用PNG格式,則L8圖像格式及圖像壓縮都易於使用。 一般來說,您在最多256色的點陣圖上一律使用L8圖像格式,不會造成任何顯著的效能影響。 如果您需要節省更多快閃記憶體,並具有可用的渲染時間達成所需效能,也可以使用L8圖像壓縮。 如果您想要壓縮與L8格式不相容的點陣圖,您可改用RGB壓縮。 如果您需要在可縮放或可旋轉的小工具使用點陣圖,就無法原生使用壓縮後的點陣圖。 當然我們有方法可以解決這項問題,稍後將簡短說明。
SVG
在資產節省快閃記憶體的另一種選項,就是讓資產採用SVG格式取代PNG格式。 SVG對色彩數量並無限制, 不過SVG的渲染成本通常高於L8及壓縮, 因此建議限制SVG數量,並盡量減少SVG動畫數量。 SVG資產越簡單,所佔用的快閃記憶體就越少,因此可達成更理想的效能。 為此我們建議僅使用單層SVG。
若要在SVG小工具使用資產,您需要匯入SVG格式的資產。 TouchGFX無法轉換資產。
向量字型
對於SVG格式的非字型資產,向量字型也需負擔昂貴的渲染成本,因為其渲染方式與SVG相同。 向量字型一般有利於使用大型字型,或使用多種不同大小的相同字型。 如果您有不同大小及向量表示的相同字型,只需要儲存字型一次即可。 之後您只需要一個縮放係數,即可呈現不同大小的字型。 如果是點陣圖字型,每種字型大小都需要個別儲存。 向量字型所節省的快閃記憶體,通常不及圖像壓縮及SVG所節省的多。 因此主要是在必須盡可能減少使用快閃記憶體的情況下,才應使用此項方法。
範例
為了提供不同概念特性的具體範例,我們以一般點陣圖、L8、L8 RLE壓縮、RGB壓縮及SVG格式,針對電動自行車示範的兩項資產進行測量。 我們在STM32U5G9J-DK2針對內部快閃記憶體之中的資產進行測量。 對於沒有NeoChrom GPU的MCU,SVG的渲染時間較長, 不過速度更快的CPU也可為此提供補償。
以下資產的色深為32位元,是頂端具有圖示的按鈕。 按鈕為122 x 112 px,圖示為72 x 72 px。
以下是在資產執行的測量結果:
格式 | 大小 | 百分比 | 渲染時間 | CPU負載 |
---|---|---|---|---|
點陣圖: | 75.4 KB | 100% | 0.414 ms | 2.4% |
L8: | 19.3 KB | 25.6% | 0.448 ms | 2.3% |
L8 RLE: | 2.55 KB | 3.4% | 1.51 ms | 9.6% |
RGB: | 4.53 KB | 12.0% | 1.65 ms | 10.5% |
SVG: | 3.01 KB | 4.0% | 1.43 ms | 4.1% |
由此可見,L8 RLE所佔用的快閃記憶體最少,不過渲染時間比一般點陣圖格式多出近1 ms。
以下資產色深32位元,是示範儀表板螢幕中儀錶的一部分, 尺寸為150 x 436 px。
以下是在資產執行的測量結果:
格式 | 大小 | 百分比 | 渲染時間 | CPU負載 |
---|---|---|---|---|
點陣圖: | 261.6 KB | 100% | 1.15 ms | 1.5% |
L8: | 65.6 KB | 25.1% | 1.24 ms | 1.4% |
L8 RLE: | 4.66 KB | 1.78% | 2.75 ms | 15.0% |
RGB: | 10.5 KB | 4.01% | 3.08 ms | 17.6% |
SVG: | 0.686 KB | 0.27% | 3.40 ms | 2.0% |
SVG格式資產佔用的快閃記憶體遠低於其他格式,不過渲染成本也是最高。
結論
如前所見,沒有哪一種格式是所有資產的最佳選擇。 不過光就節省快閃記憶體來看,對小型資產而言,L8圖像壓縮佔用的快閃記憶體最少,如果是大型資產,則SVG佔用的快閃記憶體最少。 雖然SVG資產可擁有256種以上色彩,但為了快閃記憶體使用量及效能因素,還是建議讓SVG資產保持簡單。 L8圖像格式在L8、圖像壓縮及SVG之中所佔用的快閃記憶體最多,不過渲染時間最短。
因此在開發快閃記憶體受限的應用程式時,您需要找出瓶頸,並決定應用程式最重要的考量因素為何。 是效能比較重要,還是節省快閃記憶體比較重要? 如果效能比較重要,L8就是最有效的方法。 如果效能允許的話,您甚至可以在部分資產合併使用壓縮方法。 如果盡可能減少使用快閃記憶體最重要,圖像壓縮及SVG就是最理想的方法。
使用「聰明的」資產
使用所謂的「聰明的」資產可節省更多快閃記憶體及提升效能。 本文所述的聰明的資產,是指資產本身及其使用方式。
簡易資產
首先,資產越簡單,所能壓縮的程度就越高,SVG定義也會更簡單, 最終可減少使用快閃記憶體。
作為參考,電動自行車示範中的所有點陣圖資產最多64色;由於資產也適合使用L8 RLE,因此所有點陣圖資產都採用L8 RLE壓縮。 L8 RLE的渲染速度比L8 LZW9更快,因此也能提供最佳效能。
此外如果也採用簡單設計,在部分情況下您也可以使用Tiled Image。 之後您只需要儲存部分圖像並加以重複即可。
使用方塊
另一種節省快閃記憶體的聰明方法,就是使用Box小工具。 使用方塊有兩種主要優點:
- 首先方塊可在影像緩衝區直接繪製, 因此無需快閃記憶體即可儲存方塊。 唯一會用到快閃記憶體的部分,就是定義方塊所需的少量程式碼。
- 第二,方塊可調整,並可於執行階段變更色彩及大小。 在快閃記憶體受限的電動自行車示範中,方塊用於實心背景色彩等範例,透過變更方塊色彩的方式支援淡色及深色模式。
可重複使用的資產
另一種節省快閃記憶體的方法是限制資產總數。 這當然可透過採用非常簡單的設計加以達成,不過有時可重複使用相同資產多次,以限制資產的現有數量。
在快閃記憶體受限的電動自行車示範中,這種方法用於天氣螢幕。 天氣圖示是以相同資產縮放配合所有3種尺寸。 由於這是縮放調整的資產,因此SVG格式會比壓縮更為理想,即使RLE使用的快閃記憶體較少。 不過如果資產是以RLE格式儲存為所有3種尺寸,總計使用的快閃記憶體就會更多。
此外按鈕也是實作為可重複使用的資產。 例如按鈕會與其圖示分開,以便讓按鈕能夠重複使用。
示範中使用可重複性的另一種情況則是背景。 示範中共有5種不同的背景設計,不過使用可調整資產(方塊及可重複使用的資產)就可僅以一個資產和方塊建立所有背景。
提升效能
開發快閃記憶體受限的應用程式時,會有降低效能的風險。 不過如果有備用RAM可供使用,就有方式可以提升應用程式效能。 使用動態點陣圖及可快取容器,就可將資產或容器的靜態快照繪製到RAM。 之後無論何時使用資產或容器,就可改為使用快取版本的資產或容器。 快取版本只是RAM之中的點陣圖,亦即渲染時間與渲染一般點陣圖相同。
在快閃記憶體受限的電動自行車示範中,可快取容器用於捲動SVG資產及向量字型,同時維持良好效能。
一般來說,向量字型只要在執行階段移動或可移動,就會受到快取。 這樣可確保達到最低30 FPS,不受捲動的向量字型影響。
示範中使用的另一項秘訣,就是讓壓縮點陣圖解壓縮為點陣圖快取。 將點陣圖解壓縮至RAM,就能在可縮放及可旋轉的小工具中使用。 點陣圖解壓縮時,TouchGFX在參考點陣圖ID時一律使用解壓縮的快取版本。 以下是電動自行車示範之中的範例。 壓縮點陣圖只要進行解壓縮,之後點陣圖就能像一般點陣圖一樣使用。
StartView.cpp
StartView::StartView()
{
Bitmap::decompress(BITMAP_MAIN_RIPPLE_LEFT_ID); // Decompress compressed image to bitmap cache
Bitmap::decompress(BITMAP_MAIN_RIPPLE_RIGHT_ID); // Decompress compressed image to bitmap cache
}
void StartView::setupScreen()
{
leftMainRippleScale.setBitmap(BITMAP_MAIN_RIPPLE_LEFT_ID); // Set bitmap for Scalable Image
rightMainRippleScale.setBitmap(BITMAP_MAIN_RIPPLE_RIGHT_ID); // Set bitmap for Scalable Image
leftMainRippleScale.setWidthHeight(0, 0); // Set scale of image
rightMainRippleScale.setWidthHeight(0, 0); // Set scale of image
}
由於大量使用動態點陣圖,快閃記憶體受限的電動自行車示範需要的點陣圖快取為922 KB, 代表需要大量的備用RAM。 不過這項示範也讓快閃記憶體達到接近極限的節省幅度。 如果是更簡單的應用程式,或是不那麼重視效能需求的應用程式,就有可能大幅減少所需的點陣圖快取。
Further reading
結論
本文介紹如何限制TouchGFX應用程式的快閃記憶體使用量。
這4種節省快閃記憶體的概念,可在所有STM32硬體平台使用,不過請記得SVG與向量字型具有昂貴的渲染成本。 因此如果沒有向量渲染硬體加速,或是沒有可用的額外運算能力,就可能造成效能下降。
快閃記憶體受限GUI開發的概念,可能會對效能造成不利影響,不過可使用動態點陣圖及可快取容器提升效能。
各項節省快閃記憶體的方法,可提供節省快閃記憶體的龐大潛能。 各種概念可確切節省的快閃記憶體容量,需視特定應用程式而定,不過對快閃記憶體受限的電動自行車示範而言,節省了92%的快閃記憶體。