Help us understand the problem. What is going on with this article?

RICOH THETA Z1の有機ELパネルをプラグインからコントロールする方法

More than 1 year has passed since last update.

RICOH THETA Z1がついに日本でも発売

リコーの@ueueです。

THETA Z1が日本でも発売になりました。

z1.png

THETA Z1もVと同じくプラグインをインストールして機能を拡張することができます。
最高かよ。

そして、THETA Z1には有機ELパネル(OLED)がついています。
神だな、おい。
oled.png

ということで、この記事ではプラグインからOLEDの表示をコントロールする方法について説明します。
ちなみにTHETAプラグイン開発者向けドキュメントの「Control OLED」の章に同じことが記載されているので、英語つよつよの人はそちらを参照いただければと思います。

THETA プラグイン is 何?という方はこちら

本題

先にも記載しましたが、THETA Z1は撮影情報を表示するモノクロのOLEDを搭載しています。大きさは128×36ピクセルです。

このOLEDの下2/3の領域(128×24)に対してプラグインから文字列または画像を表示させることが可能です。逆にプラグインモードのときでも、OLEDの表示を通常モードと同じようにすることも可能です。また、「何も表示させない」といった制御も可能です。
画面の明るさも制御可能で、1-100の間で指定できます。

この記事では「各ボタンで表示を切り替えるプラグイン」のサンプルコードを元にして
OLEDの表示をコントロールする方法について解説します。

サンプルプログラムのボタンと表示内容の対応は以下のとおりです。

  • シャッターボタンで文字列を表示
  • シャッターボタン長押しで何も表示させない
  • Wi-Fiボタンで画像を表示
  • Wi-Fiボタン長押しで画像を点滅表示
  • ファンクションボタン(Fn)で通常モードの画面表示

また、画面の明るさは100としています。

サンプルコードは以下のとおりです。

public class MainActivity extends PluginActivity {
    private Bitmap theta_bmp = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setAutoClose(true);

        // 画像の準備
        try (InputStream inputStream = getAssets().open("theta.bmp")) {
            theta_bmp = BitmapFactory.decodeStream(inputStream);
        } catch (IOException e) {
            notificationError("Failed to load theta.bmp");
        }

        //明るさの調整
        Intent oledBrightnessIntent = new Intent("com.theta360.plugin.ACTION_LED_BRIGHTNESS_SET");
        oledBrightnessIntent.putExtra("target", "OLED");
        oledBrightnessIntent.putExtra("brightness", 100);
        sendBroadcast(oledBrightnessIntent);

        setKeyCallback(new KeyCallback() {
            @Override
            public void onKeyDown(int keyCode, KeyEvent event) {
                if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
                    Intent textIntent = new Intent("com.theta360.plugin.ACTION_OLED_TEXT_SHOW");
                    textIntent.putExtra("text-middle", "hogehoge");
                    textIntent.putExtra("text-bottom", "fugafufa");
                    sendBroadcast(textIntent);
                } else if (keyCode == KeyReceiver.KEYCODE_WLAN_ON_OFF) {
                    Intent imageIntent = new Intent("com.theta360.plugin.ACTION_OLED_IMAGE_SHOW");
                    imageIntent.putExtra("bitmap", theta_bmp);
                    sendBroadcast(imageIntent);
                } else if (keyCode == 119) {  // 119はFnボタンのKeyCode
                    Intent oledSetIntent = new Intent("com.theta360.plugin.ACTION_OLED_DISPLAY_SET");
                    oledSetIntent.putExtra("display", "basic");
                    sendBroadcast(oledSetIntent);
                }
            }

            @Override
            public void onKeyLongPress(int keyCode, KeyEvent event) {
                if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
                    Intent textIntent = new Intent("com.theta360.plugin.ACTION_OLED_HIDE");
                    sendBroadcast(textIntent);
                } else if (keyCode == KeyReceiver.KEYCODE_WLAN_ON_OFF) {
                    Intent blinkImageIntent = new Intent("com.theta360.plugin.ACTION_OLED_IMAGE_BLINK");
                    blinkImageIntent.putExtra("bitmap", theta_bmp);
                    blinkImageIntent.putExtra("period", 300);
                    sendBroadcast(blinkImageIntent);
                }
            }

            @Override
            public void onKeyUp(int keyCode, KeyEvent event) {
            }
        });
    }
}

※ 現時点(2019/05/22)ではプラグインSDKにOLED表示のためのメソッドは存在しないので、インテントを直接利用するコードになっています。

文字列表示

OLEDの下2/3の領域に2行の文字列を個別に表示させることが可能です。
サンプルコードの以下の部分が文字列表示に対応します。

if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
         Intent textIntent = new Intent("com.theta360.plugin.ACTION_OLED_TEXT_SHOW");
         textIntent.putExtra("text-middle", "hogehoge"); // 真ん中の領域に表示される文字列
         textIntent.putExtra("text-bottom", "fugafufa"); //一番下の領域に表示される文字列
         sendBroadcast(textIntent);

表示は以下のようになります。
moji.JPG

IntentクラスのputExtraメソッドで文字列を設定します。text-middleが画面を3分割した真ん中の行に表示されます。text-bottomが画面が一番下の行です。

表示できるのはASCII printable charactersの大文字です。サンプルコードのように指定した文字列に小文字が使われている場合は、自動的に大文字に変換されます。

以下にその他の注意事項をまとめます。

  • text-middleを指定しない場合はプラグイン名が表示されます。
  • text-bottomを指定しない場合は空白が表示されます
  • 表示は左詰めになります。
  • 表示領域から指定した文字列がはみ出る場合には、スクロールしてすべての文字が表示されます。スクロールをプラグインから制御することはできません。

以下が、スクロールさせた場合の画像です。1行目は"KAOMOJI"という短い文字列。2行目に顔文字が続く長い文字列を設定しました。2行目のほうだけスクロールが走ります。

OLED_Scroll_w640.gif

画像表示

次に画像表示ついて説明します。
画像はOLEDの下2/3の領域に一つの画像を表示させることができます。
また、点滅表示をさせることも可能です。

画像の準備

まずは画像を準備します。

画像の形式はビットマップ、大きさは128x24にする必要があります。
形式や大きさが異なると何も表示されませんのでご注意ください。

今回はサンプル画像として、いらすとやの360度カメラを表示させてみました。
camera360.png
大きさが128x40のなるように画像を修正してビットマップとして保存します。

この画像ファイルをアセットフォルダーに配置します。
アセットフォルダーは、Android Studioのメニューから
[File] -> [New] -> [Folder] -> [Assets Folder]
で作成できます。

なお、カラー画像であってもTHETA側でモノクロに変換して表示するので、濃淡を気にしないならばカラーのビットマップファイルをアセットフォルダーに配置するだけでオッケーです。

画像そのものの作り方については最後の「おまけ」でもう少し細かく説明します。

サンプルコード(Assetsから画像を取り込む)

まずアセットフォルダ内の画像を取り込む部分が以下になります。

// 画像の準備
try (InputStream inputStream = getAssets().open("theta.bmp")) {
    theta_bmp = BitmapFactory.decodeStream(inputStream);
} catch (IOException e) {
    notificationError("Failed to load theta.bmp");
}

サンプルコード(画像の表示)

Wi-Fiボタンを押して画面に表示させる部分が以下になります。
“com.theta360.plugin.ACTION_OLED_IMAGE_SHOW” インテントを利用します。

} else if (keyCode == KeyReceiver.KEYCODE_WLAN_ON_OFF) {
    Intent imageIntent = new Intent("com.theta360.plugin.ACTION_OLED_IMAGE_SHOW");
    imageIntent.putExtra("bitmap", theta_image);
    sendBroadcast(imageIntent);

表示は以下のようになります。
oled_theta.JPG

サンプルコード(画像の点滅表示)

画像を点滅させたい場合は “com.theta360.plugin.ACTION_OLED_IMAGE_BLINK”インテントを利用します。

putExtraメソッドのkeyとして"period"指定して、点滅間隔を制御できます。
制御間隔1-2000[msec]の間で指定できます。デフォルトは2000 [msec]です。

対応するサンプルコードは以下の箇所です。ここでは間隔を300msecに設定しています。

else if (keyCode == KeyReceiver.KEYCODE_WLAN_ON_OFF) {
    Intent blinkImageIntent = new Intent("com.theta360.plugin.ACTION_OLED_IMAGE_BLINK");
    blinkImageIntent.putExtra("bitmap", theta_image);
    blinkImageIntent.putExtra("period", 300);
    sendBroadcast(blinkImageIntent);
}

通常モードと同じ表示にする

OLEDの表示を通常のモードとする場合には
“com.theta 360.plugin.ACTION_OLED_DISPLAY_SET”インテントを利用して
putExtraメソッドのkeyを"display"、値を"basic"とします。

サンプルコードの以下の部分が対応します。

else if (keyCode == 119) {  //ファンクションボタン
    Intent oledIntentSet = new Intent("com.theta360.plugin.ACTION_OLED_DISPLAY_SET");
    oledIntentSet.putExtra("display", "basic");
    sendBroadcast(oledIntentSet);

なお、Z1で追加されたファンクションボタンについてはKey Codeの定数が定義されていないので、こちらのドキュメントを参考に値を119としました。

keycode.png

表示は以下のようになります。
normal_mode.JPG

何も表示させない

プラグインで制御できる下2/3領域にに何も表示させたくない場合は
“com.theta360.plugin.ACTION_OLED_HIDE”インテントを利用します。

if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
    Intent textIntent = new Intent("com.theta360.plugin.ACTION_OLED_HIDE");
    sendBroadcast(textIntent);

表示は以下のようになります。
oled_nothing.JPG

画面の明るさ

画面の明るさは以下の部分で設定しています。

//明るさの調整
Intent oledBrightnessIntent = new Intent("com.theta360.plugin.ACTION_LED_BRIGHTNESS_SET");
oledBrightnessIntent.putExtra("target", "OLED");
oledBrightnessIntent.putExtra("brightness", 100);
sendBroadcast(oledBrightnessIntent);

インテントの値が
com.theta360.plugin.ACTION_"O"LED_BRIGHTNESS_SET
ではなく
com.theta360.plugin.ACTION_LED_BRIGHTNESS_SET
であることにご注意ください。

このインテントはOLEDだけでなく、他のLEDの明るさ調整にもつかわれるため"OLED"ではなく"LED"になっています。したがって、putExtraメソッドのtargetの値を “LED1”、 “LED2”とすることでLEDの明るさコントロールにも利用できます。

おまけ(画像の作成について)

最後に表示させる画像についていくつかTipsを紹介します。

濃淡のコントロール

以下が、新宿の街で信号を見上げるワイです。
uesan.png

このようにごちゃごちゃしたカラー画像をTHETA側のおまかせでモノクロに変換すると、なんだかよくわからない画像になります。

oled_uesan.JPG

このような場合、例えばこのサイトなどで、自分でしきい値を調整しながらモノクロ画像をつくることで見やすく改善することが可能です。
上記サイトで調整しながらモノクロに変換したのが、次の画像です。

uesan_mono.png
これをTHETAで描画すると
oled_uesan_mono.JPG

けっこうよくなったのが伝わるでしょうか。

ビットマップ画像を自分で作成

これまでのサンプルはすでにできあがった画像を表示していましたが、自分で画像を作成することも可能です。
詳しくないので、横シマを描画する簡単なサンプルだけのせておきます。

int black = 0xFF000000;
int white = 0xFFFFFFFF;
Bitmap bitmap2 = Bitmap.createBitmap(128, 24, Bitmap.Config.ARGB_8888 );
for (int width=0; width<128; width++) {
    for (int height=0; height<24; height++) {
        //if (width%2==0) { //縦縞
        if (height%2==0) {  //横縞
            bitmap2.setPixel(width, height, white);
        } else {
            bitmap2.setPixel(width, height, black);
        }
    }
}

こんな感じで横縞が描画されます
横縞.jpg

コードのコメント行のところを下記のように入れ替えて、縦縞を有効にすると

if (width%2==0) { //縦縞
// if (height%2==0) {  //横縞

縦縞が描画されます。
縦縞.jpg

興味を持った方はこのあたりを読めばもっといろいろできると思います。

あと、近々、THETAプラグイン開発者コミュニティのメンバーがOLEDの画像描画についてもうすこしつっこんだ記事を書くっぽいです。

まとめ

THETA Z1の有機ELパネルの表示をプラグインからコントロールする方法を説明しました。

RICOH THETAプラグインパートナープログラムについて

THETAプラグインに興味を持たれた方がいれば、以下の記事もぜひご覧ください。

RICOH THETAプラグイン開発者コミュニティでは、他にも記事を書いています。
RICOH THETAプラグインについてはこちらに情報がまとまっています。興味を持たれた方はtwitterのフォローとTHETAプラグイン開発コミュニティ(slack)への参加もぜひどうぞ。

theta-plugin
株式会社リコーの技術者有志による、RICOH THETAプラグイン技術情報の提供を目的としたコミュニティです。
https://api.ricoh/products/theta-plugin/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away