image2cpp - Resimden C Dizisi Oluşturucu (Mono ve Renkli)

image2cpp (LCD Assistant), bir resmi C dizisine veya bayt dizisine çeviren, elinizdeki diziyi de tekrar resme döndüren ücretsiz bir araçtır. Arduino, ESP32 ve Raspberry Pi projelerinde kullanılan iki ekran tipini de kapsar: 1 bit tek renkli (SSD1306 / SH1106 OLED ve Nokia 5110) ve RGB565 veya RGB888 renkli (ST7735, ST7789, ILI9341, ILI9488 TFT paneller). Çıktı olarak Adafruit GFX, U8g2, düz bayt veya MicroPython / CircuitPython seçebilirsiniz.

1. Fotoğraf seç

Tüm işlemler tarayıcınızda yerel olarak yapılır; fotoğraflarınız çevrim içi olarak herhangi bir yere yüklenmez veya saklanmaz.

veya

1. Düz Bayt dizisi yapıştır


x px
Okunan fotoğraflar sağdaki ön izlemede görünür

2. Fotoğraf Ayarları

    Yalnızca fotoğraf dosya türüne izin verilir
    Dosya seçilmedi!
    Panelin çözünürlüğünü yukarıdaki tuval boyutu alanlarına tek hamlede yazar. Henüz fotoğraf yüklemediyseniz değerler yandaki bayt yapıştırma kutusunun genişlik ve yükseklik alanlarına gider.
    100%
    100%
    0 - 255; Bir pikselin parlaklığı verilen seviyenin üzerindeyse piksel beyaz olur, aksi takdirde siyah olur. Alfa kullanıldığında bunun yerine opak ve şeffaf kullanılır.
    Fotoğrafı merkezlemek, yalnızca orijinal fotoğraftan daha büyük bir tuval kullandığınızda mümkündür.

    3. Çıktı

    Diziyi LovyanGFX.hpp başlığı ve hazır bir lcd.pushImage(0, 0, genişlik, yükseklik, dizi) satırıyla birlikte üretir. Renkli RGB565 çizim moduyla birlikte kullanın; renkler ters çıkarsa çıktıdaki lcd.setSwapBytes(true) satırını açıp kapatın.
    Micropython ve CircuitPython için bytearray formatında çıktı oluşturur.
    Bu oled_example örneğine kolay kopyalama yapıştırma için çıktının etrafına bazı ek Arduino kodu ekler. Birden fazla fotoğraf yüklenirse, her biri için bir bayt dizisi oluşturur ve tanımlayıcıya bir sayaç ekler.
    Kolay kopyalama yapıştırma için çıktının etrafına bazı ek Arduino kodu ekler. Birden çok fotoğraf yüklenirse, tek bir bayt dizisi oluşturur.
    GFXbitmapFont formatında bir çıktı oluşturur. Değiştirilmiş bir versiyonuyla kullanılan Adafruit GFX kütüphanesine aittir. GitHub projesi ve örnek kod bitmap-font
    Her fotoğraf için 1 karakter uzunluğunda bir glif tanımlayıcısı sağlanmazsa, ilk ASCII karakter değeri kullanılır. Değer, her glif için 1 artırılır.

    Aşağıdaki fotoğraf gibi fotoğrafınız ekranınızda bozuk görünüyorsa, farklı bir mod kullanın.

    info image
    U8g2 kütüphanesi ile çalışırken kullanışlıdır; XBM bit sırasını üretmek için tek renkli modlarda işaretleyin. Renkli RGB565 çıktısında boş bırakın. O moddaki renk bozulmasının kaynağı bit sırası değil bayt sırasıdır ve doğru yeri kütüphanedir: TFT_eSPI ve LovyanGFX ile tft.setSwapBytes(true) satırını ekleyin ya da kaldırın, Adafruit GFX drawRGBBitmap() ise standart bayt sırasını bekler. Bu, RGB565 dizilerinde gerçek hayatta en sık düşülen hatadır.
    0 yazarsanız satır, görselin kendi genişliğinde biter: 8 piksel genişliğindeki bir görselde her 8 baytta bir alt satıra geçer.
    Her bayt satırının sonuna, o piksel satırını nokta ve diyezle çizen bir yorum ekler. Diziyi göze bakarak denetlemenin en hızlı yolu. Bu modda her çıktı satırı bir görsel satırıdır, "satır başına bayt" yok sayılır.
    -
    Hesap için önce bir fotoğraf yükleyin ya da bir bayt dizisi yapıştırın.

    Monokrom bitmap dizisi aslında nedir?

    Monokrom bir bitmap piksel başına tek bit tutar: 1 pikselin yandığı, 0 söndüğü anlamına gelir. Ne gri ton vardır ne renk. 128x64 bir OLED'in tüm ekranının yalnızca 1.024 bayt tutmasının sebebi budur. Dolayısıyla bir resmi bitmap dizisine çevirmek iki karara indirgenir ve ekranda bozuk çıkan görüntülerin neredeyse tamamı bu iki karardan birinin yanlış verilmesinden doğar: hangi sekiz piksel aynı bayta paketlenecek, ve o baytın içindeki bitler hangi sırayla sayılacak.

    Yatay bayt sırası, her seferinde bir satır

    Yatay modda dönüştürücü resmi soldan sağa, yukarıdan aşağıya tarar ve aynı satırdaki sekiz komşu pikseli tek bayta paketler. Gruptaki en soldaki piksel en anlamlı bite (MSB) düşer. 128 pikselik bir satır 16 bayt olur, bir sonraki satır hemen ardından başlar; yani dizi, resmin bir metin sayfası gibi soldan sağa okunmuş hâlidir. Adafruit_GFX drawBitmap() ve U8g2 drawXBMP() tam olarak bunu bekler.

    Bir ayrıntı neredeyse herkesi yakalar: satır her zaman bayt sınırında biter. Resim 60 piksel genişse her satır yine 8 bayt yer kaplar ve son 4 bit dolgudur. drawBitmap() çağrısına genişlik olarak 60 verdiğinizde kütüphane, satır başına 64 bit saklayan bir diziden 60 bit okur; her satır 4 piksel daha kayar ve resim çapraz biçimde eğrilir. Monokrom genişlikleri 8'in katı tutmak bu hata sınıfının tamamını ortadan kaldırır.

    Dikey (sayfa) bayt sırası, her seferinde sekiz satır

    Dikey modda bir bayt, tek bir sütunda üst üste duran sekiz pikseli tutar; en üstteki piksel en anlamsız bite (LSB) düşer. Resim sekiz piksel yüksekliğinde yatay şeritlere, yani sayfalara bölünür ve her sayfa ekran boyunca uzanan bir bayt dizisi olarak saklanır.

    Donanımı görene kadar bu düzen keyfi görünür. SSD1306 denetleyicisinin kendi ekran belleği tam olarak böyle dizilmiştir: 128x64 bir panel, 128 baytlık 8 sayfadır ve I2C üzerinden yazılan tek bir bayt, tek işlemde 8 pikselden oluşan dikey bir sütunu yakar. Nokia 5110 (PCD8544) da aynı mantıkla çalışır. Dikey mod, diziyi mikrodenetleyicide hiç yeniden paketlemeden doğrudan o belleğe boşaltabilesiniz diye vardır. Yatay mod ise bir çizim kütüphanesinin satır mantığına uyduğu için vardır; bitmap'i kırpabilmesini ve sayfa sınırına takılmadan istediği y koordinatına yerleştirebilmesini sağlayan şey odur.

    Bayt sırasıBir bayt neyi tutarBit 7 (MSB)128x64 diziKullanan
    Yatay, MSB önceAynı satırdan 8 pikselgruptaki en soldaki piksel1.024 baytAdafruit_GFX drawBitmap(), MicroPython MONO_HLSB
    Yatay, LSB önce (XBM)Aynı satırdan 8 pikselgruptaki en sağdaki piksel1.024 baytU8g2 drawXBM(), .xbm dosyaları
    Dikey (sayfa)Aynı sütundan 8 pikselgruptaki en alttaki piksel1.024 baytham SSD1306 / SH1106 / PCD8544 tamponları

    Hangi çıktı biçimini seçmeliyim?

    Çizim modu, piksellerin baytlara nasıl paketleneceğini belirler. Zevke göre değil, ekran sürücüsüne göre seçin; yoksa resim dilimlenmiş veya aynalanmış çıkar.

    Çizim moduBayt / pikselTipik ekranlarÇizim çağrısı
    Mono, yatay1 bitSSD1306, SH1106, SSD1309 OLEDdrawBitmap() / drawXBM()
    Mono, dikey1 bitNokia 5110 (PCD8544), SSD1306 sayfa moduham tampon yazma
    Renkli RGB5652 baytST7735, ST7789, ILI9341, ILI9488, GC9A01drawRGBBitmap() / pushImage()
    Alfa maskesi1 bitrenkli bitmap yanında saydamlık maskesi olarakmaskeli blit
    Renkli RGB8883 bayt24 bit çerçeve tamponları, ESP32 RGB LCD panelleripanel sürücüsü
    Renkli HSV3 baytLED matrisler, çalışma anında ton kaydıran efektlerözel

    Diziyi kodunuzda kullanmak

    Tek renkli OLED, Adafruit SSD1306:

    #include <Adafruit_SSD1306.h>
    Adafruit_SSD1306 display(128, 64, &Wire, -1);
    
    // yukarıdaki Çıktı kutusundaki diziyi yapıştırın
    const unsigned char myBitmap [] PROGMEM = { /* ... */ };
    
    void setup() {
      display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
      display.clearDisplay();
      display.drawBitmap(0, 0, myBitmap, 128, 64, SSD1306_WHITE);
      display.display();
    }

    U8g2 ile tek renkli (XBM bayt sırası):

    u8g2.firstPage();
    do {
      u8g2.drawXBMP(0, 0, 128, 64, myBitmap);
    } while (u8g2.nextPage());

    ST7735 / ILI9341 üzerinde renkli RGB565, Adafruit GFX:

    #include <Adafruit_ILI9341.h>
    
    // RGB565 çıktısı piksel başına 2 bayt, bu yüzden unsigned char değil uint16_t
    const uint16_t myImage [] PROGMEM = { /* ... */ };
    
    tft.drawRGBBitmap(0, 0, myImage, 160, 128);

    TFT_eSPI ile renkli RGB565 (daha hızlı, ESP32 için ideal):

    #include <TFT_eSPI.h>
    TFT_eSPI tft = TFT_eSPI();
    
    tft.setSwapBytes(true);            // renkler ters görünüyorsa bu satırı kaldırın
    tft.pushImage(0, 0, 160, 128, myImage);

    Adafruit GFX, U8g2, ham SSD1306 ve klasik LCD Assistant

    Bu dördü aynı pikselleri tüketir ama aynı baytları tüketmez. Gerçekte hangi çağrıyı yapıyorsanız ona uyan çıktıyı üretin.

    Adafruit_GFX drawBitmap: yatay, MSB önce, PROGMEM

    drawBitmap(), Adafruit_GFX'ten türeyen her ekran kütüphanesinin ortak çağrısıdır; bu yüzden tek bir dizi SSD1306 OLED'de de, SH1106'da da, monokrom e-ink panelde de çalışır. Baytları yatay ve MSB önce okur, üstelik bunu pgm_read_byte() üzerinden yapar. Dizinin AVR kartlarda PROGMEM ile tanımlanması gerekmesinin sebebi budur. Arduino Uno'da PROGMEM'i unutursanız tam ekran bir bitmap flash yerine RAM'in yarısını yer. ESP32 ve RP2040'ta PROGMEM zaten hiçbir şey yapmaz ve zarar vermez, taşınabilirlik için bırakın. Son parametre renktir; ön plan rengi yerine arka plan rengini geçmek, şekli ekranda hâlihazırda duran görüntünün içinden oyup çıkarır.

    // Çizim modu: Mono - Yatay, çıkış formatı: Arduino kodu
    const unsigned char logo [] PROGMEM = { 0x00, 0x7e, 0x81, /* ... */ };
    
    display.clearDisplay();
    display.drawBitmap(0, 0, logo, 128, 64, SSD1306_WHITE);  // yanan pikseller
    display.drawBitmap(0, 0, logo, 128, 64, SSD1306_BLACK);  // şekli oyarak çiz
    display.display();

    U8g2 drawXBMP ve herkesi düşüren XBM bit sırası

    U8g2 bitmap'leri XBM biçiminde, yani eski X11 bitmap biçiminde çizer. XBM ise baytın içindeki bitleri ters yönde numaralar: bit 0 en soldaki pikseldir, en sağdaki değil. Baytlar hâlâ yataydır, dizinin uzunluğu da tıpatıp aynıdır; yalnızca her baytın bitleri ters çevrilmiştir. GFX için üretilmiş bir diziyi drawXBMP()'ye verirseniz genel şekil ayakta kalır ama her 8 piksellik grup kendi içinde aynalanır; sonuç, resminizin ince ince doğranıp yeniden yapıştırılmış hâli gibi görünür. Çıktı bölümündeki Bitleri bayt olarak değiştirin kutusu tam olarak bunun içindir: U8g2 için işaretleyin, Adafruit_GFX için boş bırakın.

    // Çizim modu: Mono - Yatay, "Bitleri bayt olarak değiştirin" işaretli
    static const unsigned char logo_xbm[] U8X8_PROGMEM = { 0x00, 0x7e, 0x81, /* ... */ };
    
    u8g2.firstPage();
    do {
      u8g2.drawXBMP(0, 0, 128, 64, logo_xbm);
    } while (u8g2.nextPage());

    drawXBMP() PROGMEM sürümüdür, drawXBM() ise zaten RAM'de duran bir dizi içindir. U8g2'de drawBitmap() adında bir metot da vardır ama o Adafruit'in çağrısı değildir ve aynı parametreleri almaz; alışkanlıkla birini diğerinin yerine yazmayın.

    Ham SSD1306 sayfa modu, tamponu kendiniz yazmak

    Hiç grafik kütüphanesi kullanmıyorsanız, örneğin çıplak bir I2C sürücüsüyle veya ESP-IDF üzerinde çalışıyorsanız, paneli sayfa ve sütun adresiyle hedefler ve baytları doğrudan belleğine gönderirsiniz. Bunun için Mono - Dikey çizim modunu seçin: dizi o zaman zaten denetleyicinin kendi düzeninde olur ve aktarım, mikrodenetleyicide hiç bit oynatmadan düz bir kopyalamaya döner.

    // Çizim modu: Mono - Dikey. 128x64 = 128 baytlık 8 sayfa
    const uint8_t frame[1024] = { /* ... */ };
    
    for (uint8_t page = 0; page < 8; page++) {
      ssd1306_cmd(0xB0 | page);  // sayfa başlangıç adresi
      ssd1306_cmd(0x00);         // alt sütun adresi = 0
      ssd1306_cmd(0x10);         // üst sütun adresi = 0
      ssd1306_data(&frame[page * 128], 128);
    }

    Klasik Windows programı LCD Assistant

    LCD Assistant, tarayıcılar bu işi yapamadan çok önce, 2000'lerin sonunda yazılmış küçük bir Windows masaüstü programıdır. Monokrom bir BMP dosyası açar ve C tablosu yazar; yatay veya dikey bayt sırası ile 8 ya da 16 bitlik tablo genişliği sunar. Çıktısı bugünün Arduino kütüphanelerinin istediğinden üç noktada ayrılır. Yalnızca hâlihazırda 1 bit olan BMP kabul eder, yani resmi önce bir editörde eşiklemeniz gerekir. Varsayılanı dikey sıradır, oysa drawBitmap() için yanlış olan sıra odur. Ve çıplak bir const unsigned char tablosu üretir, PROGMEM niteleyicisini AVR'de siz elle eklemek zorundasınız. Ayrıca dithering yoktur, benzetilmiş panel üzerinde önizleme yoktur ve elinizdeki bir diziyi geri resme çevirme imkânı yoktur.

    Buraya LCD Assistant indirmek için geldiyseniz indirmenize gerek yok. Bu sayfa aynı dönüşümü tarayıcıda yapar, yalnızca 1 bit BMP yerine PNG, JPG, BMP, GIF ve WebP dosyalarını doğrudan kabul eder ve sonucu koda yapıştırmadan önce benzetilmiş bir OLED üzerinde gösterir.

    Hex kodu mu, C dizisi mi, XBM mi?

    Burada piksellerin paketlenmesi ile metnin biçimlenmesi iki ayrı karardır. Çizim modu baytları belirler, Kod çıkış formatı ise o baytların nasıl yazdırılacağını. Aranan neredeyse her şeyi üç biçim karşılar.

    • C dizisi. Arduino kodu seçeneği, const unsigned char isim [] PROGMEM = { 0x00, 0xFF, ... }; şeklinde eksiksiz bir tanım verir; doğrudan setup() üstüne yapıştırılır. Adafruit_GFX ve U8g2 için istediğiniz budur.
    • Düz hex. Düz bayt (plain bytes) seçeneği C tanımını atar, geriye yalnızca bayt değerleri kalır; bunlar bir Python listesine, bir JSON dosyasına, bir struct başlatıcısına veya bambaşka bir dile olduğu gibi girer. Üstüne Çıktıdan '0x' ve virgülleri kaldır kutusunu da işaretlerseniz çıplak bir hex dizesi elde edersiniz; pratikte "bitmap hex kodu" derken kastedilen budur.
    • XBM. XBM, farklı bir bayt paketlemesinden çok, farklı bir bit sırası ve etrafına sarılmış bir C tablosudur. Mono - Yatay seçin, Bitleri bayt olarak değiştirin kutusunu işaretleyin; elde ettiğiniz dizi XBM sıralamasındadır ve drawXBMP()'ye doğrudan girer. Gerçek bir .xbm dosyası ise aynı tablonun üstüne genişlik ve yükseklik için iki #define satırı eklenmiş hâlidir.

    MicroPython / CircuitPython seçeneği aynı monokrom baytları framebuf.FrameBuffer(..., framebuf.MONO_HLSB) için bir bytearray içine sarar; bu da yatay MSB önce düzeninin başka bir addaki hâlidir. Binary .bin indirmesi ise hiç metin biçimlendirmesi olmayan ham baytlardır, SD karttan veya SPIFFS'ten akıtmak için.

    Bitmap bozuk, aynalı, ters veya döndürülmüş çıkıyorsa

    Bozuk çıkan bitmap'lerin neredeyse tamamı birkaç hatadan biridir ve hangisi olduğunu belirti söyler. Kodunuzda bir şey değiştirmeden önce bu tabloyu yukarıdan aşağıya tarayın.

    GördüğünüzSebebiÇözümü
    Resim 8 piksellik yatay şeritlere bölünmüş, her şerit yana doğru sürünmüşBayt sırası yanlış: dikey veri yatay çizim çağrısına gitmiş veya tersiÇizim modunu Mono - Yatay ile Mono - Dikey arasında değiştirip kodu yeniden üretin
    Şekil tanınıyor ama her 8 piksellik grup kendi içinde soldan sağa aynalanmış, ince doğranmış gibiBit sırası yanlış: MSB önce veri XBM çağrısına gitmiş veya tersiBitleri bayt olarak değiştirin kutusunu değiştirin. U8g2 drawXBM için işaretli, Adafruit_GFX drawBitmap için boş
    Resim her satırda biraz daha yana kayıyor, sonunda çapraz bir eğrilme çıkıyorGenişlik uyuşmazlığı, çoğunlukla 8'in katı olmayan bir genişlikTuval genişliğini 8'in katı yapın ve aynı genişliği çizim çağrısına da geçin
    Her şey negatif: arka plan yanıyor, konu sönükPanel 1'i sönük sayıyor ya da kaynak resmin arka planı koyuFotoğraf Ayarları'ndaki Fotoğraf renklerini tersine çevir kutusunu işaretleyin veya SSD1306_BLACK ile çizin
    Resmin tamamı 90 derece dönmüş veya blok hâlinde aynalanmışPanel yönelimi, dizi değilBuradaki Fotoğrafı döndür ve Fotoğrafı çevir ayarlarını kullanın ya da kütüphanede setRotation() çağırın
    Yalnızca ekranın en üst sekizde birinde bir şeyler varDizi kareden kısa, çoğunlukla 128x8 çıktının 128x64 sanılmasıTuval boyutunu kontrol edin ve dizi uzunluğunun genişlik / 8 * yükseklik olduğunu doğrulayın
    Boş ekran veya rastgele gürültüDizi kütüphanenin beklediği yerde değil ya da işaretçi tipi yanlışAVR'de PROGMEM ekleyin, RGB565 dizilerini unsigned char değil uint16_t tutun

    Sorunu hızlıca ayırmanın yolu: diziyi aynı genişlik, yükseklik ve çizim moduyla sayfanın üstündeki Düz Bayt dizisi yapıştır kutusuna geri yapıştırın. Buradaki önizleme doğru görünüyor ama panel görünmüyorsa dizi sağlamdır, hata kodunuzdadır. Önizleme de bozuksa dışa aktarma ayarları yanlıştır.

    Ne kadar bellek tutar?

    1 bit bitmap genişlik / 8 * yükseklik bayt tutar. RGB565 bitmap ise genişlik * yükseklik * 2. Aradaki fark hangi kartı kullanabileceğinizi belirler:

    • 128x64 tek renkli OLED: 1.024 bayt. Arduino Uno flash'ına düşünmeden sığar.
    • 160x128 RGB565 (ST7735): 40.960 bayt. Uno'nun 32 KB'lık tüm flash'ından zaten büyük. ESP32, RP2040 kullanın veya SD karttan akıtın.
    • 320x240 RGB565 (ILI9341): 153.600 bayt. Sadece ESP32 veya SD kart.

    Renkli resim sığmıyorsa Floyd-Steinberg dithering ile 1 bite çevirin. Küçük panelde dithering'li hâli, aşırı küçültülmüş renkli hâlinden genelde daha okunaklı görünür.

    Yaygın bitmap boyutlarının flash maliyeti

    1 bit bir resimde hesap genişlik / 8 * yükseklik'tir, genişliği 8'in bir üst katına yuvarlayarak. Kartların flash bütçesine vurulduğunda tablo şöyle çıkıyor:

    BitmapBaytUno'nun 32 KB flash'ında payıESP32'nin 4 MB flash'ında payı
    32x32 simge, 1 bit128%0,4ihmal edilebilir
    84x48 tam ekran, Nokia 5110528%1,6ihmal edilebilir
    128x32 tam ekran, küçük OLED512%1,6ihmal edilebilir
    128x64 tam ekran, standart OLED1.024%3,1%0,02
    160x128 RGB565, ST773540.960sığmaz%1,0
    320x240 RGB565, ILI9341153.600sığmaz%3,7

    Pratik okuması şu: Uno'da bir açılış ekranı ve birkaç simge kaldırabilirsiniz, bir simge kütüphanesi kaldıramazsınız; üstelik bootloader ile SSD1306 sürücüsü siz daha ilk bitmap'i eklemeden birkaç KB'ı almış olur. Yirmi adet 32x32 simge toplamda 2.560 bayt tutar ve genellikle tek bir tam ekran resimden daha iyi bir yatırımdır. ESP32'de ise flash sorun olmaktan çıkar, soru RAM'e döner: Adafruit_SSD1306 her hâlükârda RAM'de 1.024 baytlık bir çerçeve tamponu tutar, buna karşılık 320x240 RGB565 tam bir çerçeve tamponu 150 KB olurdu. Renkli panellerin tamamı tamponlanmak yerine şerit şerit çizilmesinin sebebi budur.

    Panel hazır ayarları ve canlı flash göstergesi

    Tuval boyutunu elle yazmak yerine 2. bölümdeki Panel hazır ayarı menüsünden panelinizi seçebilirsiniz. Listede SSD1306'nın 128x64 ve 128x32 hâlleri, Nokia 5110 için 84x48, ST7735 için 128x160 ve 128x128, ST7789 için 240x240, 240x320 ve 135x240, yuvarlak GC9A01 için 240x240, ILI9341 için 240x320 ve ILI9488 için 320x480 var. Seçim, yüklü her fotoğrafın genişlik ve yükseklik alanını doğrudan doldurur; henüz fotoğraf yoksa değerler bayt yapıştırma kutusunun boyut alanlarına yazılır. Doğru çözünürlükle başlamak, sonradan ekranda ortaya çıkan kayma ve kırpılma hatalarının çoğunu baştan siler.

    4. bölümdeki Flash maliyeti satırı, seçili çizim moduna göre sonucun kaç bayt tutacağını anında gösterir; tuval boyutunu, çizim modunu veya indeksli palet kutusunu her değiştirdiğinizde rakam yenilenir. Değer 30 KB'ı aştığında Arduino Uno uyarısı çıkar, çünkü 32 KB'lık flash'ın bootloader ve kütüphanelerden geriye bıraktığı pay bu kadardır. 1,3 MB'ı aştığında ikinci uyarı gelir: varsayılan ESP32 uygulama bölümü o civardadır ve sketch de aynı bölüme sığmak zorundadır. İki eşiğin arasındaki her şey ESP32, ESP8266 veya RP2040 için rahat, Uno için değildir.

    Kaynak resmi hazırlamak: eşikleme mi, dithering mi?

    1 bit bir ekranda piksel başına iki durum vardır, dolayısıyla giren her pikselin ya açık ya kapalı olması gerekir. Bu kararı vermenin iki yolu var ve doğrusunu seçmek, kütüphanedeki hiçbir ayardan daha çok fark yaratır.

    Eşikleme, Titreme menüsündeki Binary seçeneğidir. Her pikselin parlaklığını Parlaklık / alfa eşiği değeriyle (varsayılan 128) karşılaştırır ve yuvarlar. Keskin kenarlı her şey için doğru seçim budur: logolar, çizgi grafikler, simgeler, yazı, QR kodları, şema sembolleri. Sonuç nettir ve panel küçüldükçe de net kalır. Logonuz kayboluyor ya da tamamen dolu bir lekeye dönüşüyorsa dithering'e sarılmadan önce eşiği oynatın.

    Dithering, açık ve kapalı pikselleri bir desen hâlinde serpiştirerek bölgenin ortalama parlaklığını korur; yani çözünürlüğü verip görünürde gri kazanır. Floyd-Steinberg yuvarlama hatasını komşu piksellere dağıtır ve en fotoğrafımsı sonucu verir. Orijinal Macintosh'un algoritması olan Atkinson ise hatanın bir kısmını bilerek atar; uçlarda biraz ayrıntı kaybeder ama orta tonları daha temiz ve daha az gürültülü bırakır, küçük bir OLED'de genellikle daha iyi görünür. Bayer sabit bir matris kullanır; gözle görülür bir kareleme deseni bırakır ama kareden kareye kararlıdır, animasyon yapıyorsanız bu önemlidir.

    Fotoğrafların neden nadiren tuttuğuna gelince: 128x64 bir OLED'de 8.192 piksel vardır, kabaca bir telefon küçük resminin yirmide biri kadar; dithering ise tek bir gri tonu ima etmek için o piksellerden birkaçını harcar. O boyutta bir yüz dokuya dönüşür. Tek bir konuya sıkıca kırpın, çevirmeden önce Kontrast kaydırıcısını yukarı çekin ve okunabilir sonucun çoğu zaman fotoğrafın kendisi değil, silueti olacağını kabul edin. Eşiklemeden önce kontrastı yükseltmek, dithering algoritması değiştirmekten çok daha fazla resmi kurtarır.

    image2cpp nedir, bu sürümün farkı ne?

    image2cpp, Jasper van Loenen'in yazdığı, GitHub'da açık kaynak olarak yayımlanan ve javl.github.io/image2cpp adresinde barınan, tarayıcıda çalışan bir resimden C dizisi dönüştürücüsüdür. Bir resmi Arduino bitmap'ine çevirmenin varsayılan cevabı hâline gelmesinin sebebi basit: kurulum istemiyor, tamamen istemcide çalışıyor ve SSD1306 dünyasının gerçekten kullandığı yatay ile dikey bayt sıralarının ikisini de biliyor. Bir eğitim videosunda "resmi image2cpp ile çevirin" dendiğinde kastedilen araç odur; bu sayfa da aynı açık kaynak çekirdeğin üzerine kurulmuştur ve altbilgide kaynağı belirtilmiştir.

    O çekirdeğin iyi yaptığı her şey burada korunuyor: dönüşüm yerelde oluyor ve hiçbir dosya yüklenmiyor, birden fazla resim sıraya alınabiliyor, hem düz bayt hem Arduino çıktısı var ve elinizdeki bir dizi geri resme çözülebiliyor. Üzerine eklenenler ise şunlar:

    • Renkli çıktı. RGB565, RGB888, HSV ve 1 bit alfa maskesi; böylece aynı sayfa yalnızca monokrom OLED'lere değil, ST7735, ST7789, ILI9341, ILI9488 ve GC9A01 panellerine de hizmet ediyor.
    • Daha fazla dithering. Düz eşiklemenin yanında Floyd-Steinberg, Atkinson ve Bayer; üstüne dönüşümden önce uygulanan parlaklık ve kontrast kaydırıcıları.
    • Gerçekçi önizleme. Sonuç, klasik yeşil LCD, mavi OLED ve sarı-üstü-mavi OLED dahil benzetilmiş bir panel üzerinde gösteriliyor; hiçbir kablo bağlamadan okunabilirliğe karar verebiliyorsunuz.
    • MicroPython ve CircuitPython çıktısı bytearray olarak, ayrıca SD kart ve SPIFFS akışları için binary .bin indirmesi.
    • Türkçe arayüz ve bu rehberin Türkçesi; İngilizce sürüm /en/tools/lcd-assistant/ adresinde.

    Bunların hiçbiri orijinali yanlış yapmaz. Yalnızca monokrom bir diziye ihtiyacınız varsa ve image2cpp zaten yer imlerinizdeyse işinizi gayet iyi görür. Buradakini tercih etmenin sebebi renkli paneller, ek dithering seçenekleri ve OLED'in gerçekte nasıl görüneceğini gösteren önizlemedir.

    Sık sorulan sorular

    image2cpp renkli resim destekliyor mu?

    Evet. Klasik 1 bit tek renkli modun yanında RGB565 (2 bayt/piksel), RGB888 (3 bayt/piksel) ve HSV dizi çıktısı verir. Renkli RGB565 - 2 bayt/piksel çizim modunu seçerseniz ST7735, ST7789, ILI9341 veya ILI9488 TFT ekrana doğrudan gönderebileceğiniz bir dizi elde edersiniz.

    RGB565 nedir, neden piksel başına 2 bayt?

    RGB565 bir rengi 16 bite sıkıştırır: 5 bit kırmızı, 6 bit yeşil, 5 bit mavi. Fazladan bit yeşile gider çünkü göz en çok yeşile duyarlıdır. Sonuç, 24 bit RGB888'in yarısı bellekte 65.536 renk. Arduino ve ESP32 üzerindeki neredeyse her küçük TFT sürücüsü bu yüzden RGB565 kullanır.

    Diziyi SSD1306 128x64 OLED ekranda nasıl gösteririm?

    Tuvali 128x64 yapın, yatay tek renkli çizim modunu ve Adafruit GFX çıktı biçimini seçin, sonra display.drawBitmap(0, 0, myBitmap, 128, 64, SSD1306_WHITE) ve ardından display.display() çağırın.

    Yatay mı dikey bayt sırası mı kullanmalıyım?

    Adafruit GFX drawBitmap ve U8g2 drawXBM için yatay; bu çoğu SSD1306 ve SH1106 kodunu kapsar. Nokia 5110 (PCD8544) gibi sayfa adresli sürücüler ve ham SSD1306 sayfa tamponları için dikey. Resim yatay şeritlere bölünüyorsa yanlış olanı seçmişsinizdir.

    Bitmap ekranda neden bozuk veya kaymış görünüyor?

    Neredeyse her zaman genişlik uyuşmazlığı. Dizinin genişliği drawBitmap'e verdiğiniz genişlikle aynı olmalı ve 1 bit modlarda 8'in katı olmalı; aksi halde her satır doldurulur ve resim çapraz kayar. İkinci olarak bayt sırasını, RGB565'teyseniz ve şekil değil renkler ters görünüyorsa üçüncü olarak setSwapBytes() ayarını kontrol edin.

    Adafruit GFX ile U8g2 çıktısı arasındaki fark ne?

    Adafruit GFX, drawBitmap ile çizilen bir PROGMEM bayt dizisi bekler ve 1 bitini açık piksel sayar. U8g2 ise drawXBM ile XBM sıralaması kullanır; orada her baytın içindeki bitler ters çevrilidir. Yanlışını seçmek her 8 pikseli aynalar.

    C dizisini tekrar resme çevirebilir miyim?

    Evet. Mevcut bir bayt dizisini Düz Bayt dizisi yapıştır kutusuna yapıştırın, doğru genişlik, yükseklik ve çizim modunu seçin; önizleme diziyi resme geri çevirir. Başkasının kodundan gelen bir bitmap'i kontrol etmek için kullanışlı.

    Hareketli GIF çevirebilir miyim?

    Burada hayır. Bu dönüştürücü tek bir durağan kare okur, çünkü dosyayı bir HTML canvas'a çiziyor ve canvas aynı anda tek kare tutuyor. Hareketli GIF verdiğinizde yalnızca birinci kareyi alırsınız. Animasyonlar için GIF'ten OLED animasyon dönüştürücüyü kullanın; o araç GIF formatını doğrudan ayrıştırıp her kareyi ayrı bir dizi olarak verir, üstüne kareler arasında dolaşan hazır kodu da üretir.

    Hangi resim boyutunu kullanmalıyım?

    Ekranınıza göre: yaygın SSD1306 OLED'ler için 128x64 veya 128x32, Nokia 5110 için 84x48, ST7735 için 160x128, yuvarlak GC9A01 için 240x240, ILI9341 için 320x240. 320x240 RGB565 bir resmin 153.600 bayt tuttuğunu unutmayın; bu Arduino Uno'ya sığmaz, ESP32 veya SD kart gerekir.

    Arduino ile OLED ekranda resim nasıl gösterilir?

    Resmi yükleyin, tuvali panelinizin boyutuna ayarlayın (SSD1306 için genellikle 128x64), Çizim modu olarak Mono - Yatay, 1 bit/piksel ve çıkış formatı olarak Arduino kodu seçin. Üretilen diziyi setup() üstüne yapıştırın, ardından display.drawBitmap(0, 0, logo, 128, 64, SSD1306_WHITE) ve display.display() çağırın. Ekranda hiçbir şey çıkmıyorsa önce I2C adresini (çoğunlukla 0x3C), sonra dizinin PROGMEM ile tanımlandığını kontrol edin.

    Resmi C dizisine çevirme adım adım nasıl yapılır?

    Dört adım: dosyayı seçin, 2. bölümde tuval boyutunu ve gerekiyorsa eşik ile dithering ayarını yapın, 4. bölümde ekranınıza uyan Çizim modunu seçin, Kod Oluştura basın. Çıktı kutusundaki dizi doğrudan derlenebilir hâldedir. Sonucu koda yapıştırmadan önce 3. bölümdeki önizlemeye bakın: orada bozuk görünüyorsa panelde de bozuk görünecektir.

    U8g2 ile resim göstermek için hangi ayarları seçmeliyim?

    Mono - Yatay çizim modunu seçin ve Bitleri bayt olarak değiştirin kutusunu işaretleyin, çünkü U8g2 XBM bit sırası kullanır. Diziyi static const unsigned char isim[] U8X8_PROGMEM olarak tanımlayın ve firstPage ile nextPage döngüsü içinde u8g2.drawXBMP(x, y, genişlik, yükseklik, isim) çağırın. O kutuyu işaretlemezseniz görüntü her 8 piksellik grup içinde aynalanır.

    JPG fotoğrafı monokrom bitmap'e nasıl çeviririm?

    JPG'yi yükleyin, sonra her şeyden önce eşikleme mi dithering mi kullanacağınıza karar verin. Logo veya çizgi grafik için Titreme menüsünden Binary seçin ve şekil temizlenene kadar Parlaklık / alfa eşiği değerini oynatın. Fotoğraf için Floyd-Steinberg ya da Atkinson seçin ve önce Kontrast kaydırıcısını yukarı çekin; 128x64 bir panelde yalnızca 8.192 piksel olduğu için düşük kontrastlı görüntü gri bir dokuya dönüşür. Kareyi tümüyle çevirmek yerine tek bir konuya sıkıca kırpın.

    C dizisi yerine düz hex kodu alabilir miyim?

    Kod çıkış formatıDüz bayt (plain bytes) yapın; C tanımı düşer, geriye yalnızca bayt değerleri kalır. Üstüne Çıktıdan '0x' ve virgülleri kaldır kutusunu da işaretlerseniz Python'a, JSON'a, bir struct başlatıcısına veya hex editöre yapıştırabileceğiniz çıplak bir hex dizesi elde edersiniz. Bitmap'i derlemek yerine SD karttan akıtacaksanız Binary (.bin) dosya olarak indir düğmesi aynı baytları dosya olarak verir.

    Bu araç XBM dönüştürücü olarak kullanılabilir mi?

    Evet, tek ayarla. Mono - Yatay seçin ve Bitleri bayt olarak değiştirin kutusunu işaretleyin: XBM, aynı yatay paketlemenin baytların içindeki bitleri ters çevrilmiş hâlidir, dolayısıyla elde ettiğiniz dizi XBM sıralamasındadır ve drawXBM() ile drawXBMP()'de doğrudan çalışır. Gerçek bir .xbm dosyası için tablonun üstüne genişlik ve yükseklik #define satırlarını ekleyip dosyayı .xbm uzantısıyla kaydedin.

    SSD1306 OLED için özel font üretebilir miyim?

    Kısmen. Adafruit GFXbitmapFont çıkış formatı, karakter görselleri şeridinden bir GFX font tablosu üretir; ilk ASCII karakteri ve x advance alanlarını doldurup setFont() ile kullanacağınız özel bir font elde edebilirsiniz. Ancak bu bir karakter çizim editörü değildir. 16x2 veya 20x4 HD44780 karakter LCD'lerin 5x8 özel karakterleri bambaşka bir konudur, onun için LCD Karakter Oluşturucu aracını kullanın.

    LCD Assistant programını indirmem gerekir mi?

    Hayır. LCD Assistant, 1 bit BMP dosyasını C tablosuna çeviren bir Windows masaüstü programıdır; bu sayfa aynı işi kurulum istemeden, her işletim sisteminde, tarayıcıda yapar. Üstelik yalnızca önceden eşiklenmiş BMP değil PNG, JPG, GIF ve WebP kabul eder, drawBitmap()'in beklediği yatay sırayı varsayılan alır ve PROGMEM niteleyicisini çıktıya sizin yerinize ekler.

    BMP dosyası ile bitmap dizisi arasındaki fark nedir?

    BMP bir kaptır: genişliği, yüksekliği, renk derinliğini ve satır dolgusunu anlatan bir başlık, ardından piksel verisi. Bitmap dizisi ise yalnızca piksel verisidir; belirli bir ekranın beklediği şekilde paketlenmiş ve C kaynağı olarak yazılmıştır. Mikrodenetleyicinin flash'ında dosya sistemi de yoktur BMP çözücü de, ihtiyacı olan şey dizidir. Bu araç da onu üretir; "image to bmp array" ile "image to bitmap array" aramalarının aynı kapıya çıkmasının sebebi budur.

    İndeksli palet modu ne zaman işe yarar?

    RGB565 çizim modunu seçtiğinizde beliren İndeksli palet kutusu, resmi en fazla 256 renge indirger ve tek bir dizi yerine bir uint16_t isim_palette[] ile bir uint8_t isim_pixels[] üretir. Piksel başına 2 bayt yerine 1 bayt harcandığı için sonuç kabaca yarı yer tutar: 240x240 bir görselde 115.200 bayt yerine 58.112 bayt. Logo, simge, arayüz çizimi ve az renkli grafiklerde fark gözle görülmez, çünkü zaten 256 renkten azını kullanırlar. Fotoğraf ve degradelerde bantlaşma başlar, orada tam RGB565 dizisinde kalmak daha iyidir. Çizim tarafındaki bedeli ise diziyi doğrudan pushImage çağrısına verememektir: satır satır palete bakıp bir uint16_t tamponu doldurmanız gerekir, çıktının sonundaki hazır döngü tam olarak bunu yapar.

    İlgili araçlar