圖片部件可用于顯示圖片,圖片源可以是 C 語言數組格式的文件、二進制的.bin 文件以及圖標字體。值得注意的是,圖片部件要顯示 BMP、JPEG 等格式的圖片,則必須經過解碼。
圖片部件的組成部分僅有一個:主體(LV_PART_MAIN)
圖片源選擇
圖片部件的圖片來源分為三種:C 語言數組;存儲在外部的圖片文件;圖標字體(詳見8.2 章節)。接下來,我們詳細介紹上述三種圖片源的使用方法:
C語言數組
上面的網址如下:Online image converter - BMP, JPG or PNG to C array or binary | LVGL
這里有幾個問題需要我們注意下:
剛進入這個界面,估計看不到這個轉換的界面,只能看到一些文字介紹,我們稍微等一等,就會出現了;
沒有加載圖片之前,轉換界面是上面那樣的,導入圖片之后,就會多了個文件名稱的選項,這里的名稱默認就是圖片的命名,如下所示:
我們可以修改這個名稱,也可以不改,但是這個名稱我們后面會用到,所以推薦做好管理。
選項選好之后我們點擊Convert,轉換完成后,我們就會得到一個以剛才那個名字命名的c文件
可以看到,這個文件有4M之大,我導入的圖片尺寸是320*240的,圖片本身大小為43K,竟然一下子變得那么大,那這個文件里面到底是什么樣的內容呢?
在熟悉文件內容之前,有個問題得再次強調下:
運行之前內存中是沒有數據的,所有代碼信息都存在flash里面,內存中的數據是運行時從flash中加載進去的,用完就會釋放,所以內存夠不夠,并不能看總的數據,而是要看同一時間加載進入內存的數據量是不是會溢出。
繼續看文件內容。
打開看看
這個文件里面有兩塊內容
一個就是圖片對應的數組變量
這個數組加了const前綴,所以處于常量區,數組的名稱也是剛才上面取的名稱后面加了個_map
這一塊值得注意的是,在轉換器C數組(變量)中,所有顏色深度(1、8、16或32)的位圖都包含在C文件中
把文件接著往下拉,就會看到這些顏色深度通過宏定義進行了選擇
1位或者8位對應的數據
16位并且不交換字節時對應的數據
16位并且交換了字節時對應的數據
32位對應的數據
雖然這些顏色深度的數據都放進來了,但是只有與lv_conf.h中的LV_COLOR_DEPTH匹配的顏色深度才會實際鏈接到生成的可執行文件。
第二塊就是基于這些數據,LVGL為自己定義的一個變量,提供給我們引用的,這是個結構體變量,里面除了圖片數據,還定義了圖片的一些屬性參數。
如下:
這里可引用的名稱和我們之前轉換時所取的名稱是一樣的。
我們只會用到一種顏色深度,所以嘗試把其他不要的數據都刪掉看看。
前提是別刪錯了數據。
刪掉之后數據變成了900多K
可以大大減小圖片文件的占用內存。
我們試著將刪減前的完整文件導入程序中,看看能不能顯示。
這里我擔心一個問題,那就是4M大小的c文件,電腦倒是能放得下,但是工程鏈接之后,會占用多少單片機的Flash呢?運行之后會占用單片機多少內存呢?會不會不夠用?
我們先看下沒有加入圖片之前的空間占用情況
內存占用82.41kB,Flash占用196.24kB
我用的是F407,內存192k,Flash是512k
接著看加入圖片之后的情況
將剛才的文件復制進入工程文件里,然后在keil里導入
然后編譯看看
此時,編譯還不會產生空間占用,因為還沒有使用,所以就不會被鏈接。
可見,此時這個4M大小的圖片,占用的還只是我電腦上的存儲空間,所以文件大也沒什么關系,影響的只是我們的整個工程的占用空間,跟最終燒錄的文件沒關系。
我們嘗試著使用這個圖片文件
注意,圖片源變量必須要先聲明再引用,其實就算LVGL不引用,我們自己也要聲明外部變量,才能被調用,并且,引用的是指針。
其實就三個步驟:
聲明圖片源;
創建圖片對象;
設置圖片源。
此時編譯后查看空間占用情況
顯然flash占用情況提高了將近150kB,但是內存占用沒有太大的增長。
這樣來看,如果圖片太多了,自帶的空間肯定就不夠用了。
可是我現在想要用圖片做背景,然后切換頁面,需要用到幾十張圖片,怎么辦呢?
雖然切換頁面時,內存可以釋放再切換,但是這個素材要怎么處理呢?
這個問題后續得想辦法解決下,我們先把剛才使用的圖片下載看看能不能顯示。
經確認,可以正常顯示。
我們再用加一張圖片切換下試試看。
加了兩張圖片后,Flash占用又大了
下載看看,可以實現切換效果,但是過程中發現一個問題,那就是不斷切換圖片,圖片切換越來越慢,猜想應該是不斷切換,導致不斷創建圖片對象,而之前的圖片對象還沒有刪除,所以導致內存空間越來越小。
于是又有個疑惑,這里都是局部變量,出函數就釋放了,為啥還要手動刪除?
就算我想刪除,也識別不到對方的對象呀。
這種情況下,我們可以將頁面對象都上升成全局變量
燒錄后可以解決這個問題。關于更詳細的多頁面管理和切換,后續會專門講解。
至此,就算完成了c數組作為圖片源顯示圖片的操作。
其實這里還有個疑惑,開頭說的這句話
這里說要解碼,可是我這一頓操作下來,也沒有哪里涉及到解碼了呀。
咋回事
我們先來了解下什么是圖片的編碼。
各類型的圖片為了實現對應的要求,比如不失真,比如體積小等等,就要對原始的像素數據進行相應的處理,不同的處理就對應了不同的圖片格式,因此編碼就是將原始像素數據給處理成其他的一套編碼數據,方便傳輸加密等等。
有編碼,就有解碼,就是將這一套編碼數據給解析成原始的像素數據,然后在屏幕上顯示出來。
圖片解碼是將原始的圖像數據轉換為可用于顯示的格式的過程。常見的圖片格式包括JPEG、PNG、BMP等。為了能夠在嵌入式設備上高效地進行圖片解碼,通常會使用專門的圖像解碼庫,例如1ibjpeg、1ibpng等。這些庫提供了豐富的API和算法,能夠有效地解碼各種圖片格式。
圖片解碼的步驟通常包括以下幾個環節:
更多可參考這篇文庫《關于圖片的解碼和顯示》
為了弄懂上面提到的解碼庫的問題,關鍵就是搞清楚網站生成的c數組是帶圖片格式的數據,還是就是像素數據,如果是帶格式的數據,那么lvgl就肯定就是使用了內置的解碼庫,如果是像素數據,那么就說明網站所做的操作其實就是解碼的過程,LVGL直接將其刷到顯存中即可,不必再次解碼。
怎么確定是哪種呢?
我做了張純紅色的圖片,導入之后轉換,結果如下:
全是F800,這其實就是純紅色的像素數據。
而且,之前的移植中根本就沒有把解碼庫加進工程里。
由此可見,這個網站得到的就是像素數據,也就是說,這個網站已經把圖片進行了解碼。
我們導入后直接使用就行了。
關于圖片編碼和解碼,上面有個現象可以結合理解,上面我的一張PNG圖片只有40多K,但是解碼后得到的文件大小有900多K,這就是因為PNG在磁盤里存的是帶格式的編碼數據,為了顯示轉化成原始像素數據后,就占用了很大的空間,我這里單片機開發是直接讀取的解碼后的數據,所以要將這些原始數據直接存放在flash中,但是電腦里放的就是PNG格式的編碼數據,要想顯示,就得在內存讀取時,先經過解碼器解析成原始數據,二者的邏輯是不一樣的,要注意體會和區分。
外部圖片源文件
在上面C語言數組方式中,有個很大的問題,那就是我只使用了兩張圖片,就已經占用了將近500k的falsh,這顯然是不行的,我需要使用的圖片有大概50張,如果一張的大小是150k,那么就需要8M的空間才行。
怎么辦呢?
解決辦法就是將這些圖片以網站生成的bin文件形式放在外部Flash,然后使用LVGL自帶的文件系統來讀取素材。
這一部分內容較多,后續專題講解。
圖標字體
API函數?
我們介紹 LVGL 圖片部件常用的 API 函數:
解碼庫
根據各種資料我們知道,LVGL集成了圖片的解碼庫,既然這種C語言數組的方式網站已經幫我們解碼了,這個解碼庫有什么用呢?
我所能想到的應用場景就是,一個外部存儲介質,比如SD卡或者U盤,里面放的就是一張PNG或者BMP等原格式的圖片,里面存的是帶格式的數據,現在我設備要讀取這張照片,讀到的就是帶格式的數據,這種情況下沒有網站給你轉成像素數據,所以就只能LVGL自己來解碼,將這個數據轉成像素數據了。
這應該就是解碼庫的使用場景。
上面說的電腦里的PNG圖片只有40多K,這就是存放的格式編碼數據,計算機為了顯示,就得集成對應的解碼器,才能將其解析成像素數據然后顯示出來。
而上面說的三種方式,網站已經幫我們解碼了,所以這幾個場景下,都無需使用解碼庫。
待解決問題
那么,就還剩下兩個問題:
還有就是如何合理地管理和切換各個頁面?
再就是圖片作為整個背景,上面還能疊加一些小尺寸的圖片嗎?
后續再專門講解。