Proje Defteri

LVGL Görsel Çevirici

PNG, JPG, BMP, GIF veya WebP görselini LVGL C dizisine ya da .bin dosyasına çevirin. LVGL v9 ve v8 renk formatları, palet kuantalama, dithering, canlı önizleme ve flash maliyeti. Her şey tarayıcıda çalışır, hiçbir dosya yüklenmez.

Görseli buraya bırakın ya da tıklayıp seçin. PNG, JPG, BMP, WebP ve GIF (ilk kare).

Sürümü değiştirdiğinizde format listesi de değişir. v9 kesin formatlar (LV_COLOR_FORMAT_...), v8 ise derleme zamanı renk derinliğine bağlı eski adlar (LV_IMG_CF_...) kullanır.

Alfa taşımayan formatlarda saydam alanlar bu renge karıştırılır.

Geçerli bir C tanımlayıcısına dönüştürülür. Dizi my_image_map, tanımlayıcı ise my_image olur.

Henüz görsel seçilmedi.

.c dosyasını projenize ekleyip derleyin. .bin dosyasını SD karta veya LittleFS bölümüne kopyalayın; LVGL onu çalışma anında okur.

Görsel seçtiğinizde kullanım kodu burada oluşur.

LVGL Görsel Tanımlayıcısı Nedir?

LVGL bir görseli düz piksel dizisi olarak tanımaz. Diziyi tarif eden küçük bir yapı üzerinden tanır: LVGL v9'da lv_image_dsc_t, LVGL v8'de lv_img_dsc_t. Bu yapının içinde renk formatı, genişlik, yükseklik, veri boyutu ve piksel dizisinin adresi bulunur. lv_image_set_src() fonksiyonuna verdiğiniz şey piksellerin kendisi değil, bu yapının adresidir.

Bu araç görselinizi tarayıcıda çözer, istediğiniz boyuta ölçekler, seçtiğiniz renk formatına göre baytları paketler ve hem uint8_t dizisini hem de tanımlayıcı yapıyı yazar. Aynı veriden LVGL'nin dosya sisteminden okuduğu .bin biçimini de üretebilir.

LVGL v8 ve v9: Görsel API'sinde Ne Değişti?

İnternette bulduğunuz çoğu LVGL örneği v8 döneminden kalmadır ve v9'da olduğu gibi derlenmez. Fark üç başlıkta toplanıyor.

1. İsimler

v9 img kısaltmasını bırakıp image kelimesini kullanmaya geçti. Karşılıklar şöyle:

LVGL v8LVGL v9
lv_img_dsc_tlv_image_dsc_t
lv_img_create()lv_image_create()
lv_img_set_src()lv_image_set_src()
LV_IMG_DECLARE()LV_IMAGE_DECLARE()
lv_scr_act()lv_screen_active()

2. Renk formatları kesinleşti

v8'de LV_IMG_CF_TRUE_COLOR tek başına bir anlam taşımaz; ne demek olduğunu lv_conf.h içindeki LV_COLOR_DEPTH belirler. 16 bit derlemede iki bayt, 32 bit derlemede dört bayt eder. Aynı dizi başka bir projede farklı yorumlandığı için sessiz bozulmaların büyük kısmı buradan çıkardı.

v9 bu belirsizliği kaldırdı. LV_COLOR_FORMAT_RGB565 her derlemede piksel başına tam olarak iki bayttır, LV_COLOR_FORMAT_ARGB8888 her derlemede dörttür. Renk derinliği artık yalnızca ekran tamponunu ilgilendirir, görselleri değil.

Bu yüzden v8 seçtiğinizde araç ayrıca LV_COLOR_DEPTH sorar ve dizinin başına bir #if LV_COLOR_DEPTH kontrolü koyar. Yanlış derinlikte derlenen bir dizi sessizce bozuk çizer; bu kontrol sayesinde derleme aşamasında durur.

3. Başlık yapısı

v9 başlığına iki yeni alan geldi. magic alanı LV_IMAGE_HEADER_MAGIC değerini taşır ve LVGL'nin "bu gerçekten bir görsel mi" kontrolüdür; unutursanız görsel hiç çizilmez. stride alanı ise bir satırın bayt cinsinden uzunluğudur, piksel değil. RGB565 için genişliğin iki katıdır. Buna karşılık v8'in always_zero ve reserved alanları kalktı.

/* LVGL v9 */
const lv_image_dsc_t my_image = {
    .header.magic  = LV_IMAGE_HEADER_MAGIC,
    .header.cf     = LV_COLOR_FORMAT_RGB565,
    .header.w      = 240,
    .header.h      = 240,
    .header.stride = 480,          /* bayt, piksel degil */
    .data_size     = sizeof(my_image_map),
    .data          = my_image_map,
};

/* LVGL v8 */
const lv_img_dsc_t my_image = {
    .header.cf          = LV_IMG_CF_TRUE_COLOR,
    .header.always_zero = 0,
    .header.reserved    = 0,
    .header.w           = 240,
    .header.h           = 240,
    .data_size          = sizeof(my_image_map),
    .data               = my_image_map,
};

Renk Formatı Seçimi

Format seçimi doğrudan flash maliyetidir. Aşağıdaki tablo 240x240 piksellik bir görselin her formatta ne kadar yer tuttuğunu gösteriyor. Bir ESP32'nin uygulamaya ayırdığı bölüm çoğu zaman 1,3 MB civarı olduğu için bu sayılar hızla önem kazanır.

Format (v9)Bayt / pikselAlfa240x240 maliyetiNerede
LV_COLOR_FORMAT_RGB5652yok115.200 B (112,5 KB)Genel amaçlı, TFT panellerin doğal formatı
LV_COLOR_FORMAT_RGB565A838 bit172.800 B (168,8 KB)Yumuşak kenarlı ikon ve logolar
LV_COLOR_FORMAT_RGB8883yok172.800 B (168,8 KB)24 bit paneller, fotoğraf
LV_COLOR_FORMAT_ARGB888848 bit230.400 B (225 KB)Tam kalite, bol RAM'li kartlar
LV_COLOR_FORMAT_XRGB88884yok230.400 B (225 KB)32 bit hizalı tamponlar
LV_COLOR_FORMAT_I81 + paletpalet başına58.624 B (57,3 KB)Az renkli düz grafikler
LV_COLOR_FORMAT_A81yalnızca alfa57.600 B (56,3 KB)Tek renkli maske, stilden renklenen ikon
LV_COLOR_FORMAT_L81yok57.600 B (56,3 KB)Gri tonlamalı görsel

v8 tarafında LV_IMG_CF_TRUE_COLOR 16 bit derlemede RGB565 ile aynı maliyeti, LV_IMG_CF_TRUE_COLOR_ALPHA ise piksel başına üç baytı verir. LV_IMG_CF_INDEXED_4BIT 16 renkle sınırlıdır ama piksel başına yarım bayta iner; simge setleri ve düz renkli arayüz grafikleri için hâlâ en verimli seçimdir.

İndeksli formatlar ve dithering

İndeksli bir görselde piksel verisinin önünde palet durur: her giriş dört bayttır ve bellekte mavi, yeşil, kırmızı, alfa sırasıyla yazılır. Bu araç paleti median cut ile kurar, yani renkleri kaba bir küpe bölmek yerine görselin gerçek renk dağılımına göre ayırır. Görselde saydam piksel varsa bir palet yuvası tamamen saydam girişe ayrılır.

Degrade içeren bir görseli 16 renge indirdiğinizde bantlaşma kaçınılmazdır. Floyd-Steinberg dithering kutucuğu bu bantları komşu piksellere dağıtarak kırar. Düz renkli ikonlarda ise dithering gereksiz gürültü yaratır, kapalı bırakın.

C Dizisi mi, Binary Dosya mı?

C dizisi projenizle birlikte derlenir. Dosya sistemi gerektirmez, açılışta okuma gecikmesi yoktur, kaybolmaz. Buna karşılık her görsel firmware boyutuna eklenir ve görseli değiştirmek için yeniden derleyip yüklemek gerekir. Simgeler, düğme grafikleri ve logolar için doğru seçim budur.

.bin dosyası ise SD karta, SPIFFS ya da LittleFS bölümüne kopyalanır ve LVGL onu çalışma anında okur. Görsel büyükse, sık değişiyorsa veya kullanıcı kendi görselini yükleyecekse tek makul yol budur. Dosyanın başında LVGL'nin başlık yapısı yer alır: v9'da 12 bayt (magic, renk formatı, bayraklar, genişlik, yükseklik, stride, ayrılmış alan), v8'de 4 bayt (renk formatı, genişlik, yükseklik tek bir 32 bitlik kelimeye sıkıştırılmış olarak).

SD karttan .bin okumak

Önce lv_conf.h içinde bir dosya sistemi sürücüsünü etkinleştirin, ardından sürücü harfini kullanın. LVGL'de yol her zaman bir harf ve iki nokta ile başlar:

/* lv_conf.h */
#define LV_USE_FS_STDIO   1
#define LV_FS_STDIO_LETTER 'A'

/* v9 */
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, "A:/icons/logo.bin");

/* v8, LV_FS_POSIX_LETTER 'S' ise */
lv_obj_t * img = lv_img_create(lv_scr_act());
lv_img_set_src(img, "S:/icons/logo.bin");

Yol yanlışsa veya sürücü harfi tanımlı değilse çağrı hata vermez, sadece hiçbir şey çizilmez. Sorun ararken önce LV_LOG_LEVEL ayarını LV_LOG_LEVEL_WARN yapın; LVGL dosyayı bulamadığında bunu günlüğe yazar.

Sık Karşılaşılan Sorunlar

Görsel hiç görünmüyor

v9'da en sık sebep .header.magic alanının eksik olmasıdır. Eski bir v8 dizisini elle v9'a taşırken bu satır kolayca unutulur ve LVGL diziyi geçersiz sayıp sessizce atlar. İkinci sebep yanlış stride: satır uzunluğunu piksel cinsinden yazarsanız çizim ilk satırdan sonra ekranın dışına taşar. Üçüncüsü, görselin ekrana sığmayacak kadar büyük olması veya üst nesnenin sıfır boyutlu kalmasıdır; lv_obj_center() ile ortalayıp deneyin.

Renkler yanlış

Görüntü tanınıyor ama renkler tuhafsa neredeyse her zaman bayt sırası sorunudur. Yukarıdaki bayt sırası kutucuğunu işaretleyip diziyi yeniden üretin. Kırmızı ile mavinin yer değiştirmesi farklı bir sorundur: panel BGR modundadır ve bunu görselde değil sürücü ayarında düzeltmeniz gerekir.

Saydam alan siyah çıkıyor

Alfa taşımayan bir format seçmişsinizdir. RGB565 saydamlık tutmaz; saydam pikseller zemin rengine karıştırılır. Gerçek saydamlık için v9'da RGB565A8 veya ARGB8888, v8'de TRUE_COLOR_ALPHA seçin. Alternatif olarak v8'in TRUE_COLOR_CHROMA_KEYED formatı saydam pikselleri saf yeşile (#00FF00) boyar ve LVGL çizerken o rengi atlar.

Bellek yetmiyor

Derleme "region `FLASH' overflowed" ile duruyorsa görsel firmware'e sığmıyor demektir. Önce boyutu küçültün, sonra formatı düşürün: ARGB8888 yerine RGB565 dört kat, RGB565 yerine INDEXED_4BIT dört kat daha az yer tutar. Bunlar yetmiyorsa görseli .bin olarak dosya sistemine taşıyın; o zaman flash'ta değil SD kartta durur.

Sıkça Sorulan Sorular

LVGL görsel tanımlayıcısı nedir?

LVGL bir görseli ham piksel dizisi olarak değil, o diziyi tarif eden küçük bir yapı üzerinden tanır. v9'da bu yapı lv_image_dsc_t, v8'de lv_img_dsc_t adını taşır. İçinde renk formatı, genişlik, yükseklik, satır uzunluğu (stride), veri boyutu ve piksel dizisinin adresi bulunur. lv_image_set_src fonksiyonuna verdiğiniz şey bu yapının adresidir; piksellerin kendisi değil.

LVGL v8 ile v9 arasında görsel API'sinde ne değişti?

Üç şey değişti. Birincisi isimlendirme: lv_img_dsc_t artık lv_image_dsc_t, lv_img_set_src artık lv_image_set_src, LV_IMG_DECLARE artık LV_IMAGE_DECLARE. İkincisi renk formatı listesi: LV_IMG_CF_TRUE_COLOR gibi derleme zamanı renk derinliğine bağlı adlar yerine LV_COLOR_FORMAT_RGB565, LV_COLOR_FORMAT_ARGB8888 gibi kesin formatlar geldi; artık aynı dizi farklı LV_COLOR_DEPTH ayarlarında farklı anlama gelmiyor. Üçüncüsü başlık: v9 başlığına magic alanı (LV_IMAGE_HEADER_MAGIC) ve stride alanı eklendi, v8'in always_zero ve reserved alanları kalktı.

Hangi LVGL renk formatını seçmeliyim?

Saydamlık gerekmiyorsa RGB565 seçin: piksel başına 2 bayt tutar ve neredeyse bütün TFT panellerinin doğal formatıdır. Yumuşak kenarlı bir simge veya logo çiziyorsanız v9'da RGB565A8, v8'de TRUE_COLOR_ALPHA kullanın; bunlar piksel başına 3 bayt eder. Az renkli düz grafiklerde indeksli formatlar (v9 I8, v8 INDEXED_4BIT) yeri yarıya hatta sekizde bire indirir. Tek renkli maske veya ikon için A8 ya da ALPHA_1BIT en ucuzudur.

C dizisi mi .bin dosyası mı kullanmalıyım?

C dizisi doğrudan derlenir, flash'a gömülür ve hiçbir dosya sistemi gerektirmez; küçük ikonlar için doğru seçimdir. .bin dosyası ise SD karta veya SPIFFS/LittleFS bölümüne kopyalanır ve çalışma anında okunur. Görsel büyükse, sık değişiyorsa ya da kullanıcı kendi görselini yükleyecekse .bin şarttır. .bin dosyasında piksel verisinin önünde LVGL başlığı bulunur: v9'da 12 bayt, v8'de 4 bayt.

Görselim ekranda hiç görünmüyor, sebebi ne olabilir?

En sık üç sebep var. Birincisi, v9'da .header.magic alanının LV_IMAGE_HEADER_MAGIC olmaması; LVGL o değeri görmezse diziyi geçersiz sayar ve hiçbir şey çizmez. İkincisi, v9'da yanlış stride: satır uzunluğu piksel değil bayt cinsindendir, RGB565 için genişliğin iki katıdır. Üçüncüsü dosya yolu: .bin okuyorsanız sürücü harfi (A: veya S:) lv_conf.h içinde tanımlı olmalı, yoksa lv_image_set_src sessizce başarısız olur.

Renkler bozuk veya ters çıkıyor, ne yapmalıyım?

Görüntü tanınıyor ama renkler tuhafsa sorun neredeyse her zaman bayt sırasıdır. RGB565'te LVGL düşük baytı önce yazar; bazı SPI sürücüleri ve DMA yolları tersini bekler. Bu araçtaki bayt sırası kutucuğunu işaretleyip diziyi yeniden üretin. Kırmızı ile mavinin yer değiştirmesi ise farklı bir sorundur ve panelin BGR modunda olmasından kaynaklanır; onu sürücü ayarından düzeltmeniz gerekir.

LV_COLOR_DEPTH nedir ve neden diziyi etkiliyor?

LVGL v8'de bir pikselin bellekte kaç bayt tuttuğunu format adı değil, lv_conf.h içindeki LV_COLOR_DEPTH belirler: 16 ise RGB565 iki bayt, 32 ise mavi, yeşil, kırmızı, alfa sırasıyla dört bayt, 8 (ve 1) ise RGB332 tek bayt eder. TRUE_COLOR dizisi bu düzene birebir bağlıdır, bu yüzden araçta v8 seçtiğinizde projenizin derlendiği derinliği de seçmeniz gerekir. Üretilen dosyaya bir #if LV_COLOR_DEPTH kontrolü eklenir; başka bir derinlikle derlerseniz "This image was generated for LV_COLOR_DEPTH ..." hatasını alırsınız. Bu bilinçli bir tercihtir: derlenip ekranda bozuk çizen bir görsel yerine derleme anında duran bir hata çok daha iyidir. LVGL v9'da bu sorun hiç yaşanmaz, çünkü orada renk formatları derleme ayarından bağımsızdır.

Görselim bir sunucuya yükleniyor mu?

Hayır. Dosya seçtiğinizde görsel yalnızca tarayıcınızın belleğine alınır, canvas üzerinde işlenir ve C dizisi yine tarayıcıda üretilir. Hiçbir ağ isteği yapılmaz, hiçbir veri sunucuya gönderilmez veya saklanmaz. Sayfa bir kez yüklendikten sonra interneti kapatıp çalışmaya devam edebilirsiniz.