PebbleTime 開発 - 画像を表示する
前回 はデジタル時計を作ってみました。
今回は、このコードを修正して背景に画像を表示してみます。 真っ赤だと面白くないですからね。
今回のゴール
以下の様な見た目になります。
レイヤー構造
今回作る Watchface は、以下の様なレイヤー構造となります。
root_layer
(必ずある)の上に画像を表示する bitmap_layer
があり、
その上に時間を表示する text_layer
があります。
text_layer
は透明です。
コード
これが今回作成するコードです。
前回からの変更点
以下が、前回のコードからの変更点の概要です。
- 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)
で指定しています。
レイヤーには bounds
と frame
という大きさの概念があり、これは bounds
を取得する API です。
意味としては「root_layer と同じ大きさ(と位置)」となります。
bounds
と frame
に関しては次回に説明します。
背景色を「透明」に設定
text_layer は「赤色」でしたが、今回は下のレイヤーの画像を見せたいので「透明」にします。
void handle_init(void) { ... // text_layer の背景色を 透明 に設定 text_layer_set_background_color(text_layer, GColorClear); ... }
透明色は GColorClear
で指定します。
bitmap を新規作成
画像を表示させましょう。
以下の様な手順が必要です。
- 色数が 2色(白黒)と 64色 の PNG 画像を用意する
- CloudPebble に画像を「PNG image リソース」として登録する
- リソース名を指定してビットマップオブエジェクトを作成する
- ビットマップオブジェクトを BitmapLayer に設定する
それぞれ見ていきます。
色数が 2色(白黒)と 64色 の PNG 画像を用意する
画像は、同じものを色数を変えて2枚用意します。 今回は PebbleTime 用の Watchface を作るので白黒画像は表示しないのですが、CloudPebble の制限(障害?)により、「PNG image リソース」を登録する場合は白黒画像も登録しないとコンパイルエラーが発生するのです。。。
サンプル画像
今回は、素材サイト「GIRLY DROP」から夕焼けの画像を借りてきました。
変換
サンプル画像はフルカラーなので、2色および64色に減色する必要があります。 幸い、Pebble 用の減色ツール「Image Converter for Pebble Time」があるので、それを使用しましょう。
まず、[ファイルを選択] ボタンをクリックして画像を選びます。
すると、その画像から PebbleTime で表示できる 64色 の中で近い色を選んで減色してくれます。
白黒画像を作りたい場合は「Color mode」を「black and white」に変更してください。
CloudPebble に画像を「PNG image リソース」として登録する
CloudPebble のプロジェクトを開き、左側の「RESOUCES」に横にある [ADD NEW] ボタンを押してください。
下のような画面が開きます。
項目 | 説明 |
---|---|
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] ボタンを押すと以下のように登録されます。
リソース名を指定してビットマップオブエジェクトを作成する
それでは、登録した 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_layer
も root_layer
に重ねることで表示されます。
レイヤーは後から重ねたものが上になります。
今回は、下から root_layer
、bitmap_layer
、text_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 を使用して色々な画像を表示したり、ビットマップイメージを複数用意して時間に合わせて表示する画像を変更してみても面白いと思います。
ところで、同じ場所に表示しても意味は無いので表示する位置を変えたいですが、その方法を紹介していませんでしたね。
表示位置とサイズは bounds
と frame
で設定します。
次回は、bounds
と frame
について紹介します。
PebbleTime は、公式サイトでプレオーダーを受付中です。 2015-07-12 現在で $199.99 です。
Amazon.co.jp に並行輸入品が出てますね。 ただ、正直高いです。 公式サイトで買うことをおすすめします。
Pebble Time スマートウォッチ 腕時計 (レッド) [並行輸入品]
- 出版社/メーカー: Pebble
- メディア: 時計
- この商品を含むブログを見る
こちらは古い白黒のやつ。 見た目の違いで2種類あります(性能は同じ)。
Pebble Steel (Brushed Stainless)
- 出版社/メーカー: Pebble
- メディア: Personal Computers
- この商品を含むブログを見る
Pebble Smartwatch for iPhone and Android ( ブラック / レッド ) 並行輸入品
- 出版社/メーカー: pebble
- メディア: Wireless Phone Accessory
- この商品を含むブログを見る
*1:どのようなレイヤーにも画像を描くことはできますが設定が面倒です。