M5Stackスクリーンキャプチャツール

[企画・制作] ZEPエンジニアリング

M5Stack 画面キャプチャ・ツール

  M5Stackの画面をブログなどに投稿するときに画面のキャプチャ・ツールが欲しくなります。検索するといくつかの方法が紹介されていますが、シンプルで使い易そうなものを見つけられなかったので、今回、自作してみました。キャプチャしたデータは、TF(microSD)カードにBMPファイル形式で任意のファイル名で保存できます。本ツールは、ライブラリ化せずにインクルードファイルとして記述しましたので、自由に改版が可能です。

画面キャプチャ例

対象機種はM5Stack Coreシリーズ(BASIC, FIRE等)です。Core2でも同様に動作します。 

M5Stack BASIC
M5Stack Basic V2.6
【M5STACK-K001-V26】
M5Stack FIRE IoT開発キット(PSRAM)V2.6
M5Stack FIRE IoT開発キット(PSRAM)V2.6
【M5STACK-K007-V26】
M5Stack Core2 IoT開発キット
M5Stack Core2 IoT開発キット
【M5STACK-K010】

基本仕様 

 本ツールの仕様と動作について以下に示します。

 ・関数名:void Screen_Capture_BMP(char *file_name)
  ※全画面をキャプチャし、file_nameで指定されたファイル名でTF(microSD)カードにBMP形式で保存
 ・関数が呼ばれた時点でTF(microSD)カードが挿入されていない場合は、画面にエラー表示し動作停止
 ・ファイルが何らかの原因でオープンできなかった場合も画面にエラー表示をし動作停止
 ・キャプチャ中は画面バックライトの明るさを5%まで暗くする
  ※キャプチャ中であることを示すためと、使用するTF(microSD)カードによって書き込み中の電圧変動により、
   書き込みに失敗する例があったため実施(バックライトを暗くすることにより解消された)

BMPファイルフォーマット

 キャプチャ範囲を変更するなど本プログラムの改造に必要な情報として、BMPファイルフォーマットについて記述します。理解を深めるためにご参照ください。

 BMPファイルの基本構成は、以下のとおり、ファイルヘッダと情報ヘッダ、カラーパレット、イメージデータの大きく4つの部分から成り立っていますが、今回はカラーパレットは使用していませんので、その部分の説明は割愛します。

BMPファイルヘッダ 情報ヘッダ カラーパレット イメージデータ
 14バイト  40バイト  今回は未使用  BRG, BRG, ・・・・

BMPファイルヘッダ

 BMPファイルであることを示します。14バイトで構成され、内容は以下のとおりです。ファイルサイズ以外は固定値ですが、今回は、M5StackのLCD画面全体をキャプチャするので、ファイルサイズも一定で固定値になります。

       
アドレス 名称 内容
 0x0000
uint16_t bfType ファイルタイプ "BM"
 0x0002uint32_t bfSizeファイルサイズ (byte) 
 0x0006uint16_t bfReserved1リザーブ 0x0000
 0x0008 uint16_t bfReserved2 リザーブ 0x0000
 0x000A uint32_t bfOffBits ファイルの先頭からイメージデータまでのオフセット 14+40 (byte)

情報ヘッダ

 BMPファイル中のイメージデータの内容を表す情報が含まれます。こちらも今回の場合は、固定値を設定しています。キャプチャ範囲を変更するなど場合は、適宜書き換えを行ってください。

       
アドレス 名称 内容
 0x000E
uint32_t biSize ヘッダサイズ 40 (byte)
 0x0012int32_t biWidthイメージサイズの幅 320 (pixel)
 0x0016int32_t biHeightイメージサイズの高さ 240 (pixel) 正の値の場合はイメージデータは左下から右上に向かって並べる。
負の値とした場合は、左上から右下に向かって並べる。
 0x001A uint16_t biPlanes プレーン数 (常に1)
 0x001C uint16_t biBitCount 1ピクセル当たりのビット数 24 (bit) 
 0x001E uint32_t biCompression 圧縮方式 0:無圧縮
 0x0022 uint32_t biSizeImage イメージデータサイズ 320 * 240 * 3 (byte)   
 0x0026 int32_t biXPelsPerMeter 幅方向の解像度。1m当たりのピクセル数 320 / 4 * 100
 0x002A int32_t biYPelsPerMeter 高さ方向の解像度。1m当たりのピクセル数 320 / 4 * 100
 0x002E uint32_t biClrUsed 使用する色数。カラーパレットのインデックス数 0
 0x0032 uint32_t biClrImportant 表示に必要なカラーインデックス数 0

カラーパレット

 今回は未使用ですので、説明を割愛します。

イメージデータ

 M5StackのLCD画面のデータは、左上から右下に向かって、RGBの順に並んでいますが、BMPファイルのイメージデータは、通常、左下から右上に向かって、BGRの順に並べます。(情報ヘッダ:biHeightを参照) また、1行分のデータは、4の倍数のバイト数になっている必要があり、足らない分は、0x00でパディングする必要があります。今回は、1行当たり、960バイトで4の倍数になっていますから、プログラムでは考慮していません。
イメージデータの配置

画面キャプチャ・プログラム

 画面キャプチャ・プログラムは、ライブラリ化せずにインクルードファイル(Capture.h)として、キャプチャしたいプロジェクトから#include によって読み込む形式としました。実装した関数は、以下の関数のみです。

  void Screen_Capture_BMP(char *file_name)

 キャプチャしたい場面で、上記関数を呼び出せば、その時点のLCD画面の内容をBMPファイル形式で、TF(microSD)カードに書き出します。書き出し時間は約3秒です。

  記述例) Screen_Capture_BMP(”/screen0.bmp" );

  ※ファイル名先頭のルートディレクトリを表す「/」は、必須です。必ず記述するようにしてください。  

(1)開発環境

 M5StackのArduino IDE開発環境用です。その構築方法については、別記事「いろいろなマイコンボードに使えるArduino IDE。環境構築メモ」の「M5StackをArduino IDEで使う」の章を参考にしてください。

(2)プログラム

 Caputure.hとサンプルのプロジェクトは、こちらよりダウンロードしてください。 

Capture.hプログラムリスト

  1. // M5Stack Screen Capture
  2. // Copyright (c) 2022- @logic_star
  3. #define BitImageSize (320 * 240 *3) //画面キャプチャーイメージサイズ
  4. #define PixelPerMeter (320 / 4 * 100) //画面解像度
  5. //Function entry
  6. void Screen_Capture_BMP(char *file_name){
  7. uint8_t FrameBuffer[320*3];
  8. File fp;
  9. int x,y,i;
  10. const uint16_t BMP_header[14 + 40] = //BMPファイルヘッダー定義
  11.   { //File header 14 bytes
  12.     'B','M', //uint16_t bfType
  13.     (BitImageSize & 0xff),((BitImageSize>>8) & 0xff),((BitImageSize>>16) & 0xff),0, //uint32_t bfSize
  14.     0,0, //uint16_t bfReserved1
  15.     0,0, //uint16_t bfReserved2
  16.     14+40,0,0,0,//uint32_t bfOffBits
  17.     //Information header 40 bytes
  18.     40,0,0,0, //uint32_t biSize
  19.     (320 & 0xff),((320 >> 8)& 0xff),0,0, //int32_t biWidth
  20.     240,0,0,0, //int32_t biHeight
  21.     1,0, //uint16_t biPlanes
  22.     24,0, //uint16_t biBitCount
  23.     0,0,0,0, //uint32_t biCompression
  24.     (BitImageSize & 0xff),((BitImageSize>>8) & 0xff),((BitImageSize>>16) & 0xff),0, //uint32_t biSizeImage
  25.     (PixelPerMeter & 0xff),((PixelPerMeter>>8) & 0xff),0,0, //int32_t biXPelsPerMeter
  26.     (PixelPerMeter & 0xff),((PixelPerMeter>>8) & 0xff),0,0, //int32_t biYPelsPerMeter
  27.     0,0,0,0, //uint32_t biClrUsed
  28.     0,0,0,0 }; //uint32_t biClrImportant
  29.   Serial.printf("Start %s\n", file_name);
  30.   M5.Lcd.setBrightness(10); //バックライトを暗くする
  31.   if (!SD.begin(4)) {
  32.     M5.Lcd.println("NO SD CARD.");
  33.     M5.Lcd.setBrightness(200);
  34.     while (1) ;
  35.   }
  36.   fp = SD.open(file_name, FILE_WRITE);
  37.   if(!fp){
  38.     M5.Lcd.println("File open error.");
  39.     M5.Lcd.setBrightness(200);
  40.     while (1) ;
  41.   }
  42.   for(i=0;i<(14+40);i++) fp.write(BMP_header[i]); //BMPファイルヘッダーの出力
  43.   for(y=239;y>=0;y--){ //画面の下から上へスキャン
  44.     M5.Lcd.readRectRGB(0, y, 320, 1, FrameBuffer); //1ライン分の画面データの取得
  45.     for(x=0;x<320*3;x+=3){ //1ライン分のデータ出力
  46.       fp.write(FrameBuffer[x+2]); //Blue
  47.       fp.write(FrameBuffer[x+1]); //Green
  48.       fp.write(FrameBuffer[x]); //Red
  49.     }
  50.   }
  51.   fp.close();
  52.   M5.Lcd.setBrightness(200); //バックライトの明るさを戻す
  53.   Serial.printf("end %s\n", file_name);
  54. }
  • 8行目 スクリーンキャプチャ関数エントリー
  • 13~31行目 BMPファイルヘッダ、情報ヘッダ定義
  • 33~39行目 TF(microSD)カード使用開始。カードが挿入されていないときは、メッセージを出力してプログラム停止
  • 40~45行目 出力ファイルオープン。エラー時はメッセージを表示してプログラム停止
  • 46行目 ヘッダー情報出力
  • 47~54行目 イメージデータをVRAMから取得し、並びを変えながら出力
  • 55~58行目 ファイルクローズし、リターン

(3)サンプルプロジェクト

 画面に数字を表示し、0.5秒毎にインクリメントします。M5Stack左下のAボタンを押下するとその時点の画面をキャプチャし、 CounterXXX.bmp(XXXはその時の数字) というファイル名でTF(microSD)カードに書き込みます。右下のCボタンを押下するとプログラムを停止します。

Screen_Capture.inoプログラムリスト

  1. //M5Stack screen capture sample project Copyright (c) 2022- @logic_star
  2. //#define CORE2 //CORE2を使用する場合は有効化要
  3. #ifdef CORE2
  4.   #include <M5Core2.h>
  5. #else
  6.   #include <M5Stack.h>
  7. #endif
  8. #include "Capture.h"
  9. int counter;
  10. char fn[100];
  11. void setup() {
  12.   M5.begin();
  13.   M5.Lcd.fillScreen(TFT_BLACK);
  14.   M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);
  15.   M5.Lcd.setTextDatum(TL_DATUM);
  16.   M5.Lcd.setTextFont(4);
  17.   M5.Lcd.setTextSize(1);
  18.   counter = 0;
  19. }
  20. void loop() {
  21.   M5.update();
  22.   M5.Lcd.setCursor(10, 30);
  23.   M5.Lcd.printf("Counter = %d", counter);
  24.   if(M5.BtnA.isPressed()){
  25.     sprintf(fn, "/Counter%d.bmp", counter);
  26.     Screen_Capture_BMP(fn);
  27.   }
  28.   if(M5.BtnC.isPressed()) while(1);
  29.   counter++;
  30.   delay(500); //0.5秒ウェイト
  31. }
  • 2行目 M5Stack Core2を使用する場合は有効化してください。
  • 8行目 Capture.hをインクルード
  • 13~21行目 M5Stac, 画面初期化
  • 23~34行目 メインルーチン
  • 27~30行目 ボタンAが押されたら画面をキャプチャ
  • 31行目 ボタンCが押されたら実行停止

 サンプルプログラムを実行したときのM5StackのLCD画面をキャプチャしたものを以下に示します。

Counter =12 Counter = 20 

(4)トラブルシューティング

 本ツールをデバック中にTF(microSD)カードを正しく装着しているにも関わらず、エラーとなる現象が何回か発生しました。その際は以下の点を確認してみてください。

 ・TF(microSD)カードの装着不良 ⇒ 何度か挿抜を繰り返してください。
 ・電源変動 ⇒ 電源電圧の変動に弱いTF(microSD)カードがあるようです。他の種類のTF(microSD)カードを試す。
  内蔵バッテリーが十分充電されているかなど確認してください。

まとめ

 M5Stackの表面パネルは、アクリル板なので、反射により画面撮影が難しいです。ブログに投稿したり、取説等を作成するときにかなりの手間を掛けていましたが、本ツールによってかなり効率を上げることができました。キャプチャしたい場面に予め本ツールの関数を埋め込んでおけば、TF(microSD)カードの容量が許す範囲で、自動的にキャプチャしていくので、とても便利です。ソースも公開していますので、自由に改造してより使いやすくしてみてください。

M5Stack BASIC
M5Stack Basic V2.6
【M5STACK-K001-V26】
M5Stack FIRE IoT開発キット(PSRAM)V2.6
M5Stack FIRE IoT開発キット(PSRAM)V2.6
【M5STACK-K007-V26】
M5Stack Core2 IoT開発キット
M5Stack Core2 IoT開発キット
【M5STACK-K010】

©2022ー @logic_star All rights reserved.



Page Top