Arduboyの画面に、PCで選択した画像ファイルを表示するようなツールを作ってみたいと思います。
この場合はArduboyとPC間で通信をすることになります。
PC側を何で開発するかちょっと迷ったのですが、画像処理(2値化)などもすることを考えると、とりあえずProcessing(Proce55ing)かなあと思い、ちょっと使ってみました。
ProcessingはArduinoの兄弟のような開発環境で、IDEも似ています。
ベースの言語はJavaです。
画像処理関係の機能が充実しており、画像処理フィルタ機能が標準で使えます。
filter() \ Language (API) \ Processing 2+
IDEそのものはArduinoにそっくりなのですが、Arduinoと違い、現在のバージョン(v3)ではステップ実行や変数の確認ができるデバッガが付いています。
まずは画像ファイルを読み込んでウインドウに表示させるプログラムを作ってみました。
思ったより手こずりましたが、できたのが以下です。
スペースキーを押すとファイル選択ダイアログが立ち上がり、画像ファイルを選択すると表示できます。
PImage img; String fName; void setup() { size( 512, 512 ); background(0, 0, 0); } void keyReleased() { if (key == ' ') { noLoop(); selectInput("Select an image file", "fileSelected"); while(fName==null) {delay(200);} if (fName != null) { img = loadImage(fName); clear(); redraw(); } loop(); } } void fileSelected(File selection) { if (selection == null) { println("Window was closed or the user hit cancel."); fName = null; } else { fName = selection.getAbsolutePath(); } } void draw() { if (img != null) { image(img, 0, 0 ); } }
ただ・・・このプログラム、一応は動くのですが、2回目以降に画像を開くとき、画像を開いた直後には表示されません。
redraw()をコールすれば、直後でdraw()で新しい画像が描かれると思ったのですが、何かタイミングが合っていないようです。
また、私にとっては言語として、どうも気持ちの悪い点がいくつかあります。たとえば
・keyReleased()で使用しているkeyのように、グローバル変数が多い。
・手続き型言語の印象が強い。img.drawじゃなくてimage(img)とか。
・ループの一時停止と再開を意味するnoLoop(), loop()という表現も古臭い。
・ライブラリを見る限り、GUI関係がちょっと弱そう。
などなど・・・
また、最近Arduboyシミュレータを使うためにVisual Studioばかり使っていたためか、ProcessingのIDEも不便に感じるようになってしまいました。
そんなわけで他の選択肢を探してネットを見ていたところ、「openFrameworks」に行き当たりました。Processingの影響を受けたC++ライブラリですが、Mac、Linux、WindowsのほかiOSやAndroidにも対応しているようです。
Windowsでは、VisualStudioの上で開発が行えます。
日本語の情報はProcessingに比べると少ないのですが、嬉しいことに日本語の書籍で、無料でダウンロードできるものがあります。
Beyond Interaction メディアアートのためのopenFrameworksプログラミング入門 | 株式会社ビー・エヌ・エヌ新社
というわけで、こちらを使ってみることにしました。
ライブラリはダウンロードして展開するだけですが、それ以外にVisual Studio用のプラグインが必要です。
これはVisual Studio内からダウンロードできます。
まず「ツール」→「拡張機能と更新プログラム…」を選択します。
そして、openFrameworksを検索してダウンロードします。
これで完了です。
ダウンロードしたライブラリには、サンプルが沢山付属しています。
GUIツールキットも用意されています。
プラグインをインストールしたので、新規のプロジェクトを作成する際にはテンプレートの選択肢にopenFrameworksが出てきます。
なお初回は、openFrameworksを展開したディレクトリの場所を指定するよう求められました。
テンプレートには最初から必要なファイルが含まれています。
プログラム本体はofApp.cpp / ofApp.hに記述します。
openFrameworksで、先ほどと同様に画像ファイルを選択して表示するプログラムを書いてみました。
テンプレートがあるので、実際に書いた部分は青字の部分だけです。
#pragma once #include "ofMain.h" class ofApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void keyPressed(int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void mouseEntered(int x, int y); void mouseExited(int x, int y); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); void processOpenFileSelection(ofFileDialogResult openFileResult); ofImage img; };
#include "ofApp.h" //-------------------------------------------------------------- void ofApp::setup(){ ofSetWindowShape(512, 512); ofBackground(0,0,0); } //-------------------------------------------------------------- void ofApp::update(){ } //-------------------------------------------------------------- void ofApp::draw(){ if (img.isAllocated()) img.draw(0, 0); } //-------------------------------------------------------------- void ofApp::keyPressed(int key){ } //-------------------------------------------------------------- void ofApp::keyReleased(int key){ if (key == ' ') { ofFileDialogResult openFileResult = ofSystemLoadDialog("Select a jpg or png"); if (openFileResult.bSuccess) { processOpenFileSelection(openFileResult); } } } void ofApp::processOpenFileSelection(ofFileDialogResult openFileResult) { ofFile file(openFileResult.getPath()); if (file.exists()) { string fileExtension = ofToUpper(file.getExtension()); if (fileExtension == "JPG" || fileExtension == "PNG") { img.load(openFileResult.getPath()); } } } //-------------------------------------------------------------- void ofApp::mouseMoved(int x, int y ){ } //-------------------------------------------------------------- void ofApp::mouseDragged(int x, int y, int button){ } //-------------------------------------------------------------- void ofApp::mousePressed(int x, int y, int button){ } //-------------------------------------------------------------- void ofApp::mouseReleased(int x, int y, int button){ } //-------------------------------------------------------------- void ofApp::mouseEntered(int x, int y){ } //-------------------------------------------------------------- void ofApp::mouseExited(int x, int y){ } //-------------------------------------------------------------- void ofApp::windowResized(int w, int h){ } //-------------------------------------------------------------- void ofApp::gotMessage(ofMessage msg){ } //-------------------------------------------------------------- void ofApp::dragEvent(ofDragInfo dragInfo){ }
とりあえず、openFrameworksを使ってみようかと思います。
コメント