關於這個工具
顯示器真正要的那份陣列
顯示驅動不吃 PNG。它吃的是一串位元組,而且要照它的控制器讀取的方式排好,其中每一項都得有人決定:一個像素一個位元還是十六個位元?最左邊那個像素放在第 7 位還是第 0 位?一列接一列,還是切成八個像素高的頁?紅色在高五位還是低五位?把圖丟進來、選好格式,位元組就照著那個排法打包——mono、gray2、gray4、gray8、LVGL 要的 alpha1 到 alpha8 遮罩,以及 rgb565、rgb888 和 argb8888。控制項旁邊那張預覽不是把原圖縮小:它是把打包好的陣列再讀回來畫的,所以你看到的就是面板會顯示的。
一個像素只有一個位元,這個位元怎麼花
128x64 的 OLED 有 8,192 個像素,每個一個位元,所以整張圖的成敗就在黑白分界線切在哪裡。線稿和圖示用單純的門檻就對了,滑桿就是在移動那條線。照片則要把誤差散開:Floyd–Steinberg 把誤差擴散給旁邊的像素,做出報紙印刷那種顆粒感;Bayer 4x4 的規則矩陣則給你一片整齊的網紋,在小面板上往往更好認。亮度和對比在切之前作用,invert 在切之後,而且每一個都會在你拖動的當下重畫預覽——因為一個圖示撐不撐得住一個位元,只能用它實際會顯示的尺寸看出來。
把 framebuffer 讀回成一張圖
反方向這件事沒人做,而它正好回答你手上真正的問題:這份陣列到底對不對?貼一段 C 陣列(0x 的位元組、十進位、\x 跳脫、一整塊裸的十六進位,有沒有大括號、註解和 #define 行都無所謂),或是丟一份從快閃記憶體挖出來的 .bin,它就會被畫成圖。接著拉寬度滑桿。寬度不對的 framebuffer 會歪成一道道斜條紋,而寬度一對,整張圖就當場立起來——這是辨認來路不明傾印的標準手法。它同樣可以拿來檢查自己的輸出:轉一個圖示,把陣列貼回來,如果出來的東西看起來就是你的圖示,那位元順序和每列補的位元都對了。讀不出來的 token 會連同位置一起報出來,不會被吞掉,所以貼上的陣列打錯一個字,賠掉的是一個值,不是後面整份。
樣板、位元組順序,還有那個一定會咬人的
同樣一串位元組,看是誰要編譯它,包裝就不一樣:素的 static const uint8_t 陣列、附 _WIDTH 和 _HEIGHT 巨集的 Adafruit GFX PROGMEM 陣列、用 #define 寫尺寸的 u8g2 XBM、LVGL v8 的 lv_img_dsc_t 和 v9 的 lv_image_dsc_t、丟給 TFT_eSPI pushImage() 的 uint16_t 陣列,還有旁邊直接把 framebuf 建構式寫好的 MicroPython bytes 字面值。會咬人的是 TFT_eSPI:它讀 16 位元像素時先讀高位元組,所以只有這個樣板要把 RGB565 用大端序打包,其他一律小端序。在這裡你選樣板,位元組順序就跟著走——一份編得乾乾淨淨、顏色卻整個錯掉的陣列,是沒有人喜歡花時間去找的臭蟲。整套都在這個分頁的 Web Worker 裡跑:不上傳、不用帳號,還沒公開的產品美術素材不會離開你的機器。