golang
micropython
M5stack
RGB565

仕方がないのでPNGからRGB565への変換ツールをGoで作った。

GIMPにはがっかりだよ、仕方がないな自分でツールつくるか。

という感じで。せっかく楽できると思ったのにほんとがっかりです。

変換ツールを作ろうってことでとりあえず何で作るか考えましたが、Javaは除外するとして画像の扱いが得意そうなのはGoですか。Pythonはモジュールが錯綜していてあんまり楽じゃなかったイメージ。

まあ、Goならよしでしょう。
ちょっと調べたらPNG使えるというし、よしつくるぞ。

よし、できたぞ。

やればすぐなんだから最初から作りゃ良かったんだよ。

rgb565.go
package main

import (
    "fmt"
    "os"
    "image/png"
    "path/filepath"
)

func main(){
    imgf,_ := os.Open(os.Args[1])
    defer imgf.Close()

    img,_ := png.Decode(imgf)
    bnd := img.Bounds()
    w := bnd.Max.X
    h := bnd.Max.Y

    fmt.Printf("binary size %d\nwidth : %d\nheight: %d\n",w*h*2,w,h)

    buf:= make([]byte,w*h*2)
    for y := 0; y < h ; y++ {
        for x := 0; x < w; x++ {
            r,g,b,_ := img.At(x,y).RGBA()
            hb,lb := rgb32torgb565(r,g,b)
            idx := (y*w+x)*2
            buf[idx]   = hb
            buf[idx+1] = lb
        }
    }
    current,_ := filepath.Abs(".")
    f,err := os.Create(filepath.Join(current,"out.dat"))
    if err != nil {
        fmt.Print("file create err")
    }
    defer f.Close()
    f.Write(buf)
}

func rgb32torgb565(r uint32,g uint32,b uint32) (uint8,uint8) {
    var r8,g8,b8 uint16
    var rgb565 uint16
    r8 = uint16(r>>11)
    g8 = uint16(g>>10)
    b8 = uint16(b>>11)
    rgb565 = uint16((r8 << 11) | (g8 << 5) | b8)
    return uint8((rgb565 & 0xff00)>>8) , uint8(rgb565 & 0xff)
}

ほぼやっつけなので単純にビット間引いてるだけですし解像度変換なんていう高等なものは付いていません。とりあえずテストってことでね。

go run rgb565.go ほにゃらら.png とかするとout.datってのが出来上がって、コンソールにデータサイズと画像のサイズが表示されます。
画像サイズはバイナリに埋め込むか悩んだんですがM5stackの横幅320って1byteに入りきらないじゃないですか。だからやめました。

出来上がったデータをM5stackで表示してみよう!

ili934xnew.pyを使ってるの前提ですよ。
でもrgb565のデータだから他の環境でもデータさえ送りこんでやれば表示出来るはずだね。

disp.py
import m5stack
display = m5stack.display

imgWidth  = 320
imgHeight = 200
fileName = "/sd/kitten.dat"

display._writeblock(0,0,imgWidth-1,imgHeight-1)
f=open(fileName,"r+b")

for i in range(imgHeight):
    f.seek(i*imgWidth*2)
    data = f.read(imgWidth*2)
    mv = memoryview(data)
    display._data(mv)
f.close()

わたしがちょいちょい書いてるM5stackでESP32のmicropython~っていう環境に特化したようなコードですけども。

さあ、どうかなどうかな!
いざ実行!

kitten.jpg

きましたわ!
キトゥンかわいい!!!

ってことで、変換はうまくいってるようですねー。
これであの雑な処理してるGIMPの画像ソースコードともおさらばだ! ハッハッハ!
そして、おもったよりは速度も出てる。M5cloudのJPG表示と同じくらいじゃないかな。

課題

ビットを間引いてるだけなので階調の変化がちょっとアレ。
ディザリングするとかして液晶画面に特化させる処理入れた方が良いね。

あとは複数ファイル対応とか?
リサイズとか?(萎え

まあ、いろいろ改善の余地はあるよね。
いろいろいろいろがんばりまっしょい。