T time

プログラミングや電子工作、各種ガジェットに関するブログです。

PebbleTime 開発 - 画像を表示する

前回 はデジタル時計を作ってみました。

今回は、このコードを修正して背景に画像を表示してみます。 真っ赤だと面白くないですからね。

今回のゴール

以下の様な見た目になります。

f:id:tatur0u:20150710003658p:plain

レイヤー構造

今回作る Watchface は、以下の様なレイヤー構造となります。

root_layer(必ずある)の上に画像を表示する bitmap_layer があり、 その上に時間を表示する text_layer があります。 text_layer は透明です。

f:id:tatur0u:20150710003702p:plain

コード

これが今回作成するコードです。

前回からの変更点

以下が、前回のコードからの変更点の概要です。

  • window
    • 変更なし。
  • text_layer
    • レイヤーのサイズを値(144x168)で設定していたのを、「root_layer と同じ大きさ」に設定するように変更。
    • 背景色を「赤」から「透明」に変更。
  • bitmap
    • リソースに追加した PNG からビットマップを作成。
  • bitmap_layer
    • 新規作成。
    • レイヤーのサイズは「root_layer と同じ大きさ」に設定。
    • text_layer の下に挿入。

text_layer の変更点

text_layer の大きさと背景色を変更します。

TextLayer 型のオブジェクトに設定可能な値は、 前回の記事 を参照してください。

サイズを「root_layer と同じ大きさ」に設定

text_layer を作成するときの大きさを、今までは GRect(0, 0, 144, 168) と直接指定していました。 画面いっぱいに表示したいのでこれでも良いのですが、今回は別の方法を紹介します。

void handle_init(void) {
    ...
    // text_layer を作成
    text_layer = text_layer_create(layer_get_bounds(root_layer));
    ...
}

大きさを layer_get_bounds(root_layer) で指定しています。

レイヤーには boundsframe という大きさの概念があり、これは bounds を取得する API です。 意味としては「root_layer と同じ大きさ(と位置)」となります。

boundsframe に関しては次回に説明します。

背景色を「透明」に設定

text_layer は「赤色」でしたが、今回は下のレイヤーの画像を見せたいので「透明」にします。

void handle_init(void) {
    ...
    // text_layer の背景色を 透明 に設定
    text_layer_set_background_color(text_layer, GColorClear);
    ...
}

透明色は GColorClear で指定します。

bitmap を新規作成

画像を表示させましょう。

以下の様な手順が必要です。

  1. 色数が 2色(白黒)と 64色 の PNG 画像を用意する
  2. CloudPebble に画像を「PNG image リソース」として登録する
  3. リソース名を指定してビットマップオブエジェクトを作成する
  4. ビットマップオブジェクトを BitmapLayer に設定する

それぞれ見ていきます。

色数が 2色(白黒)と 64色 の PNG 画像を用意する

画像は、同じものを色数を変えて2枚用意します。 今回は PebbleTime 用の Watchface を作るので白黒画像は表示しないのですが、CloudPebble の制限(障害?)により、「PNG image リソース」を登録する場合は白黒画像も登録しないとコンパイルエラーが発生するのです。。。

サンプル画像

今回は、素材サイト「GIRLY DROP」から夕焼けの画像を借りてきました。

girlydrop.com

変換

サンプル画像はフルカラーなので、2色および64色に減色する必要があります。 幸い、Pebble 用の減色ツール「Image Converter for Pebble Time」があるので、それを使用しましょう。

www.watchface-generator.de

まず、[ファイルを選択] ボタンをクリックして画像を選びます。

f:id:tatur0u:20150710003617p:plain

すると、その画像から PebbleTime で表示できる 64色 の中で近い色を選んで減色してくれます。

f:id:tatur0u:20150710003625p:plain

白黒画像を作りたい場合は「Color mode」を「black and white」に変更してください。

f:id:tatur0u:20150710003632p:plain

CloudPebble に画像を「PNG image リソース」として登録する

CloudPebble のプロジェクトを開き、左側の「RESOUCES」に横にある [ADD NEW] ボタンを押してください。

下のような画面が開きます。

f:id:tatur0u:20150710003641p:plain

項目 説明
RESOURCE TYPE PNG 画像の場合は「PNG image」か「PNG with tranparency」を設定します。
両者の違いは、透明色を含まないか含むかです。
今回の画像は透明色を含まないので「PNG image」を設定します。
FILE 白黒の PNG を設定します。
COLOR FILE 64色 の PNG を設定します。
IDENTIFIER 画像の識別子を設定します。
これはASCII文字ならどのような名前を設定しても良いですが、習慣として IMAGE_ で始まる大文字の名前を付けると良いです。

なお、PNG のファイル名ですが、以下の様な命名規則が推奨されます。

パターン 白黒 カラー
1 foo.png foo~color.png
2 foo~bw.png foo~color.png

パターン 2 がより良いですが、CloudPebble に登録した時の名前は白黒画像の名前となるので、私はパターン 1 を使用しています。

[SAVE] ボタンを押すと以下のように登録されます。

f:id:tatur0u:20150710003648p:plain

リソース名を指定してビットマップオブエジェクトを作成する

それでは、登録した PNG からビットマップオブジェクトを作成しましょう。

そのためには gbitmap_create_with_resource API を使用します。

GBitmap *bitmap;

void handle_init(void) {
    ...
     // リソース "IMAGE_BACKGROUND" から画像を生成
     bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_BACKGROUND);
    ...
}

この API はリソースID(IDENTIFIER)を指定するだけなのですが、そのまま指定するわけではなく RESOURCE_ID_ を追加します。 リソースID IMAGE_BACKGROUND の場合は RESOURCE_ID_IMAGE_BACKGROUND となります。

bitmap_layer を新規作成

画像を表示するには、BitmapLayer 型のレイヤーを使用するのが簡単です*1

BitmapLayer は TextLayer や他のレイヤーと同様に、 bitmap_layer_create で作成し、 bitmap_layer_destroy で削除します。 Layer 型のオブエクトを取得するのは bitmap_layer_get_layer です。

では、使用可能な機能を見てみましょう。

機能 使用するAPI 備考
ビットマップを設定する bitmap_layer_set_bitmap BitmapLayer はビットマップへのポインタを管理します。画像をコピーするわけではないので、ここに指定したビットマップを編集すると、表示する画像も変わります。
設定されているビットマップのポインタを返す bitmap_layer_get_bitmap 初期値は NULL です。
画像を表示する位置を指定する bitmap_layer_set_alignment 左上、上、右上
左、真ん中、右
左下、下、右下
の9種類を設定できます。詳細はこちらを参照してください。
背景色を設定する bitmap_layer_set_background_color レイヤーサイズより画像のほうが小さい場合に背景色が描かれます。
初期値は透明です。
背景画像との合成方法を設定する bitmap_layer_set_compositing_mode 詳細はこちらを参照してください。
初期値は GCompOpAssign (背景に関係なく指定した画像をそのまま表示する)です。

レイヤー作成と画像の設定

これはコードを見ればわかるでしょう。 bitmap_layer_create で作成し、bitmap_layer_set_bitmap で設定しています。 レイヤーの大きさは text_layer と同様です。

text_layer の下に挿入

bitmap_layerroot_layer に重ねることで表示されます。

レイヤーは後から重ねたものが上になります。

今回は、下から root_layerbitmap_layertext_layer の順に重ねたいので、まず bitmap_layer を重ねてから text_layer を重ねます。

void handle_init(void) {
    ...
    // bitmap_layer を root_layer に重ねる
    layer_add_child(window_get_root_layer(window), bitmap_layer_get_layer(bitmap_layer));
    ...
    // text_layer を root_layer に重ねる
    layer_add_child(window_get_root_layer(window), text_layer_get_layer(text_layer));
    ...
}

動作確認

以前の記事のとおり、コンパイルしてエミュレータに実行イメージを転送してください。

現在時刻が表示され、1 秒ごとに表示が更新されるはずです。

あとがき

今回は、画像を表示してみました。

これで、かなり表現力が上がりますね。

あとは、複数の BitmapLayer を使用して色々な画像を表示したり、ビットマップイメージを複数用意して時間に合わせて表示する画像を変更してみても面白いと思います。

ところで、同じ場所に表示しても意味は無いので表示する位置を変えたいですが、その方法を紹介していませんでしたね。 表示位置とサイズは boundsframe で設定します。

次回は、boundsframe について紹介します。


PebbleTime は、公式サイトでプレオーダーを受付中です。 2015-07-12 現在で $199.99 です。

getpebble.com


Amazon.co.jp並行輸入品が出てますね。 ただ、正直高いです。 公式サイトで買うことをおすすめします。


こちらは古い白黒のやつ。 見た目の違いで2種類あります(性能は同じ)。

Pebble Steel (Brushed Stainless)

Pebble Steel (Brushed Stainless)

*1:どのようなレイヤーにも画像を描くことはできますが設定が面倒です。