[ESP32] ESP32でGIFを軽量GIFデコーダでデコードする


まず…なぜGIFなのか?

「esp32とTFT液晶で強震モニタを作りたい」

を前提に色々試行錯誤しています。前のTTSの記事もその一環です。強震モニタとはリアルタイムで緊急地震速報(予報も含める)を見ることができるアレです。

webページを分析してみると

リアルタイムにGIFファイルをDLしてを重ねて表示しているようです。なのでGIFファイルを表示する必要があるのです。


ESP32でTFT液晶(ILI9486)を使う準備

ILI9486である必要はありませんが、TFT液晶を使うとなるとライブラリが必須になります。

TFT液晶用のライブラリは何個か候補があります。僕が渡り歩いたのは下の3つです。

Adafruit-GFX-Library

TFT_eSPI

LovyanGFX

この中で一番高機能、しかも日本人なら、LovyanGFX一択です!!開発者の「らびやん」さんは日本人でリファレンスも多くあり高性能なライブラリです。書き出し時に拡大・縮小ができたり、日本語出力が標準でできたり(これは便利!!)、海外ライブラリにはない便利なことができて大変助かりました。Adafruitの謹製ライブラリは速度面で遅いイメージ、TFT_eSPIも高機能ですが、日本語出力なんて海外ライブラリにあるわけもなく…リファレンスを読むと

最初からLovyanGFX使っとけばよかったOTL

基本的な命令は標準ライブラリやTFT_eSPTと同じメソッドですのですんなり移行できます。

esp32との接続やデモの表示の例はたくさんありますので、そちらを参考に画面表示できるまでしときます。これができないとデコードしても表示までたどり着けません。


GIFのデコーダーを探しまくる

LovyanGFXではJPEGはlcd.drawJpgFileですぐ表示できるようです。TJpg_Decoderとかでデコードしてたのは何だったんだろうと思ってしまいます。

GIFもデコーダあるのかなぁ(ワクワク

チーン。AnimatedGIFを使いましょうということですね。

らびやんさんが言うなら間違いないです!AnimatedGIFのリファレンスを読んでみました。結構、機能満載なライブラリでして、

もっとGIFファイル(静止画)をサッとデコードできそうな簡単なライブラリはないかなぁ~(贅沢

と探してはみたんですけど意外にないんですねwで、見つけた記事が

です。この記事を書いた人も軽量デコーダーを探していました。なんと下の方にシンプルなデコーダのソースコードが載っているではないですか。


GIFデコーダの改良

さきほどの記事のデコーダを早速コピペして動かしたところ、GIFファイルが表示できません。というか、いろいろ試すと表示できるのもあればできないものもあります。よく調べてみるとinit_decoder()で負数が返ってきているようです。

これは…GIFファイルのヘッダをうまく読めてないようです。ヘッダを正しく読んでいないので透過GIFにも対応していないということになります。

さぁ~次いこー(棒

としましたが、あまりに探して見つからないので重い腰を上げることにしました。今考えると意地になってましたねw

GIFのヘッダの仕様書を読みながらライブラリを改良してみました。どうやらExtensionを正しく読んでいない様子。正しく読むようにして透過GIFへの対応をしました。長いですが下にコードを張ります

基本的に使い方はこのライブラリが紹介してあったサイトのサンプルコードで動きますが、コールバック関数が

(*gif_draw_pixel)(rgbColor.R, rgbColor.G, rgbColor.B, trans_gif , trans_pixel);

で返ってきますので修正してください。デコードしたピクセル毎に呼び出されます。trans_gifは透過GIFファイルかどうか、tens_pixelは透過ピクセルかどうかという変数を加えていますので透過処理も可能となります。これで正しくデコードはできるようになりました。

余談ですが、汎用性・互換性の為、このライブラリもイニシャライズ時にファイルストリームを渡して初期化していますが、強震モニタを作る上で画像生成の流れ的に

  1. GIFダウンロード
  2. GIFデコード
  3. 画像処理&合成
  4. TFT出力

のステップを想定しています。結構なメモリが必要ですので、PSRAMがあるESP32-wroverシリーズが必須といえます。この場合は、GIFをダウンロードしたメモリ領域ごとデコーダに渡せるようにした方が便利なので実際はそちらの方で実装しています。

重複するので全掲載は避けますが、上のような感じで変更します。gifはGIFをダウンロードしたPSRAM上のバッファを想定してます。こうすればSPIFFSやSDカード不要でPSRAM上で処理を完遂できます。