前回はSPIFFSの中に格納したBMPファイルを表示させましたが、JPEG、GIF、PNGなどのファイルも表示させたくなりますね。
調べてみたところ、これらの画像形式の中でESP8266で比較的扱いやすいのはJPEGのようです。
JPEG、GIF、PNGはいずれも圧縮アルゴリズムを使っていますが、GIFとPNGは辞書形式の圧縮符号化方式(GIFはLZW、PNGはZlib)を使っています。
このタイプの圧縮アルゴリズムは、辞書をRAM上に展開すると、比較的大きなワーキングメモリが必要になります。
一方、JPEGは計算量はGIFやPNGよりも大きい代わりに、ワーキングメモリはそれほど大きくないようです。
picojpegというメモリ消費の少ないデコーダ実装があり、これをArduino上で利用した例も見つかりました。
今回は、上記のデコーダを使って前回同様にSPIFFS上に置いたJPEGファイルをLCDに表示させてみました。
まず、デコーダライブラリを下記からダウンロードしてArduino IDEに追加(スケッチ→Include Library→Add .ZIP Library…)します。
このライブラリはSDカードでの利用が想定されていますので、SPIFFSで使うために、以下の部分をちょこっと変更します。
変更するファイルは「マイドキュメント\Arduino\Libraries\JPEGDecoder-master\JPEGDecoder.cpp」です。
修正前: #include <SD.h>
修正後: #include <FS.h>
修正前: g_pInFile = SD.open(pFilename, FILE_READ);
修正後: g_pInFile = SPIFFS.open(pFilename, “r”);
スケッチ本体は以下のようになります。
もともとのライブラリに、デコード結果をシリアルポートに表示する分かりやすいサンプルがありましたので、シリアルポート出力の代わりにLCDに点を打つだけで動作させることができました。
SPIFFSの中に”test1.jpg”というファイルを入れておくと、それをST7735ベースのLCDに表示します。
ESP8266のSPIFFSへのファイル転送のやり方は以前の記事を参照してください。
#include <arduino.h> #include <SPI.h> #include <FS.h> #include <JPEGDecoder.h> #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific library #define TFT_CS 15 #define TFT_RST 5 #define TFT_DC 4 Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); void setup() { Serial.begin(115200); Serial.println(""); delay(10); tft.initR(INITR_BLUETAB); tft.fillScreen(ST7735_BLACK); SPIFFS.begin(); jpegDraw("/test1.jpg"); } void jpegDraw(char* filename) { char str[100]; uint8 *pImg; int x,y,bx,by; // Decoding start JpegDec.decode(filename,0); // Image Information Serial.print("Width :"); Serial.println(JpegDec.width); Serial.print("Height :"); Serial.println(JpegDec.height); Serial.print("Components:"); Serial.println(JpegDec.comps); Serial.print("MCU / row :"); Serial.println(JpegDec.MCUSPerRow); Serial.print("MCU / col :"); Serial.println(JpegDec.MCUSPerCol); Serial.print("Scan type :"); Serial.println(JpegDec.scanType); Serial.print("MCU width :"); Serial.println(JpegDec.MCUWidth); Serial.print("MCU height:"); Serial.println(JpegDec.MCUHeight); Serial.println(""); sprintf(str,"#SIZE,%d,%d",JpegDec.width,JpegDec.height); Serial.println(str); // Raw Image Data while(JpegDec.read()){ pImg = JpegDec.pImage ; for(by=0; by<JpegDec.MCUHeight; by++){ for(bx=0; bx<JpegDec.MCUWidth; bx++){ x = JpegDec.MCUx * JpegDec.MCUWidth + bx; y = JpegDec.MCUy * JpegDec.MCUHeight + by; if(x<JpegDec.width && y<JpegDec.height){ if(JpegDec.comps == 1){ // Grayscale tft.drawPixel(x, y, tft.Color565(pImg[0], pImg[0], pImg[0])); }else{ // RGB tft.drawPixel(x, y, tft.Color565(pImg[0], pImg[1], pImg[2])); } } pImg += JpegDec.comps ; } } } } void loop() { }
コメント