Color/GrayScale 画面をPC-UNIX 環境で作成する方法

グレイスケールを設定する方法についてのメモです. ここでは,一般的な環境(CodeWarriorなど)ではなく,PC-UNIX 環境上で 実現することを考えてみます.

※ 独自に試行/解析した方法なので, もしかしたら他にいい方法(Palm が推奨する方法?) があるかもしれません.
※ ここに書いた方法は引用自由ですが,何かに使用/参考にされる場合は, 一言その旨を書いていただけると助かります.



使用する環境

うちの環境は貧弱なまま使い続けてるので,最新の SDK はまだ対応させてません. ということで,下のようなツールを使います. うちの環境が新しくなれば,また新しい環境に対応した内容にする予定です.

prc-tools + PilRC(2.5a) + GIMP という組合せで *.bmp を表示させる方法は, おそらくどこにも書かれてない気がしてますので, ここでは,リソースとしてビットマップを表示させることを目標にします. これができれば,Color 系の API で色付きのグラフィック描画も問題なく できます.

また,Windows+ cygwin で PilRC を使う場合もほぼ同じ手順を取ります. Windows の場合は市販のグラフィックツールがあるので,パレットをうまく合わせるようにする 必要があります.

機種別対応モード

カラーやグレイスケールの表示が可能なのは,PalmOS3.0 以上の機種だけです. また,機種毎にサポートしているモードが異なります.

カラー機は通常パレットを変更することはないので,グレーは16階調になります (OS3.5 でのパレットは4096色(R/G/B で各256階調)対応なので, 原理的に 256階調可能ですが).

モードの判別はOSバージョンで行ってはいけません.モードとOSバージョンは (本来なら)対応していないためです.OSバージョンは 3.0 以上であることを確認するために使い, モード確認は次の方法で行います.

PalmOS 3.0〜3.3
DWord SupportDepth;
Boolean SupportColor_flag;

ScrDisplayMode(scrDisplayModeGetSupportedDepths,NULL,NULL,&SupportDepth,NULL);
ScrDisplayMode(scrDisplayModeGetSupportsColor,NULL,NULL,NULL,&SupportColor_flag);
PalmOS 3.5〜
UInt32 SupportDepth;
Boolean SupportColor_flag;

WinScreenMode(winScreenModeGetSupportedDepths,NULL,NULL,&SupportDepth,NULL);
WinScreenMode(winScreenModeGetSupportsColor,NULL,NULL,NULL,&SupportColor_flag);

SupportDepth にはその機種でサポートしている1ピクセルのビット数(をORしたもの)が入り, SupportColor_flag にはカラーに対応しているかどうかが入ります.

私が認識している範囲での機種別モードを挙げておきます.
機種 サポートモード SupportDepth SupportColor_flag
WorkPad(30J), WorkPad c3(40J) 2bpp(グレー4階調) 0x00000003 false
PalmVx, WorkPad c3(50J) 4bpp(グレー16階調) 0x0000000B false
PalmIIIc 8bpp (カラー256色) 0x0000008B true

画像を GIMP 作成

  1. 画像を GIMP で作ります.完成したら *.xcf(GIMP形式) で保存しておきます. もちろんレイヤなどの GIMP 上の特殊情報も後で修正に必要ならば残しておきます.

  2. 次に,PilRC に対応するビットマップを作成しますが, ここで注意しないければならないのは,PilRC はパレットを厳密に定義していることです. 単なる減色では PilRC では使えません. そのため,まずパレットを準備する必要があります.

    ~/.gimp/palettes/ ディレクトリに次のファイルを作ります.

    内容はパレットファイルを参考にして下さい. Palm_Color は同じディレクトリにあるWeb に 0 の行を40個付け加えたもの (全部で256パレット分)になります.
    ※パレットダイアログで同じように作成することも出来ます.

  3. GIMP にて,レイヤーやアルファチャネルなどを統合し,一枚の RGB 画像にしておきます (タイトルバーに "(RGB)" となっている).

    この状態で,[画像]→[インデックス画像] でダイアログを開き, [カスタムパレットを使用] とパレットファイルを指定します.

    多色画の場合はパレットの色に減色するため,ディザオプションを好みで選ぶことも出来ます. 指定しなければ最も近いパレットの色に変更されます.

    ※ここでパレットファイルが見つからない場合は,前項のパレットファイルの作成に 失敗しています.
  4. インデックスモード(タイトルバーに "(indexed)" となっている)になった ところで保存します.形式は *.bmp にしておいて下さい.

    これで,PilRC に必要な画像は作成できました.

PilRC でリソースファイルを作成

PilRC でコンパイルするリソースファイルを作成します. ここでは,単純にビットマップを張り付けるだけのフォームを例として挙げます. PilRC のフォーマットについては,日本語訳を参考にして下さい.

form id 1000 (0 0 160 160)
usable
begin
        label "TEST PROGRAM" AUTOID at (center 10)

	formbitmap at (0  20) bitmap 2000
	formbitmap at (0  50) bitmap 2001
	formbitmap at (0  80) bitmap 2002
	formbitmap at (0 110) bitmap 2003
end

bitmap       id 2000 "bitmap.bmp"
bitmapgray   id 2001 "bitmap_gray2.bmp"
bitmapgray16 id 2002 "bitmap_gray4.bmp"
bitmapcolor  id 2003 "bitmap_color.bmp"

icon      "icon.bmp"

この例では全てのビットマップ(2階調,4階調,16階調,256色) をformbitmapで画面に書いています. 実際にはサポートされているモードに合わせたものを指定して下さい (プログラムでScrDisplayModeを使って選択した方が賢明です).

プログラム上で画面モードを設定

プログラムの開始時に,画面モードの設定を行います. 例えば,次のような関数を作成します(OS3.0〜3.3用).
void InitialScreenMode()
{
  FtrGet(sysFtrCreator,sysFtrNumDisplayDepth,&OldDepth);
  ScrDisplayMode(scrDisplayModeGetSupportedDepths,NULL,NULL,&SupportDepth,NULL);
  ScrDisplayMode(scrDisplayModeGetSupportsColor,NULL,NULL,NULL,&SupportColor_flag);

  if      (SupportDepth & 0x0080) NewDepth = 8;
  else if (SupportDepth & 0x0008) NewDepth = 4;
  else if (SupportDepth & 0x0002) NewDepth = 2;
  else                            NewDepth = 1;

  if (!FtrSet(sysFtrCreator, sysFtrNumDisplayDepth, NewDepth)) {
      ScrDisplayMode(scrDisplayModeSetToDefaults,NULL,NULL,NULL,NULL);
  }

ここでは,FtrGetで現在のモードをOldDepthに保存しておき, FtrSetで新しいモード(NewDepth)をデフォルトに指定します. プログラム内でビットマップを指定するときは,このNewDepthを使って 切り替えることになります.

※ カラーモードにする場合,実際には SupportColor_flagの値に従って, ScrDisplayMode() でカラーモードに変更する必要があります. ここでは,手抜きで
元々カラーモードだから切り替えなくてよい」
カラーモードで1bpp/2bpp/4bpp に切り替えたら,パレットはグレイスケールに変更される
という事実を前提にして,カラーモードの切り替えをサボってます(^^;)

プログラム終了時は,以下のように前のモードを復帰させます.
void RecoverScreenMode()
{
  FtrSet(sysFtrCreator,sysFtrNumDisplayDepth,OldDepth);
  ScrDisplayMode(scrDisplayModeSetToDefaults,NULL,NULL,NULL,NULL);
}

その他

以上で,カラーやグレイスケールのビットマップ表示が可能になります. 以下では,注意しなければならない点やその理由などについて書いています.

PilRC 2.5a での問題点

2bpp(グレー4階調)の場合,パレットは16個にしておく必要があります. これは PilRC でのパレット設定が 16階調を元にしているためです. また,16個のパレットは以下のように認識されます.

このため,単純に 0,1,2,3 の4パレットで 4階調を表現すると,blackとlightgrayしか 表示されなくなります. 正しく認識するためには,パレットファイルでこれらのパレットを正しく指定する 必要があります.

WorkPad (30J/40J)の注意点

これは事例から発見したことですが, 以前,PalmVx であるアプリを開発していたときに, 256x256 のビットマップを使っていました. このときは何の問題もなく表示できていたわけですが, このアプリを WorkPad(30J/40J) ユーザにビームで渡した時に, 必ず Fatal Error が表示されることが分かりました.

当初は PilRC のパレット指定方法が前述のようになっていることを 知らなかったため,16階調パレットで4階調ビットマップを表示させていました. そして,30J/40J が Vx と違って 4階調表示しかできないことを知り, 16階調パレットであることが原因と分かりました.

4階調ビットマップの作成に成功したのですが,今度はまた別のシステムエラーに見舞われました. こればかりはかなり原因究明に苦労ました. 結論としては,30J/40J(OS3.1機?) はビットマップ表示が 160x160 に限定されているのが 原因のようです.

256x256 の領域のオフスクリーンを作成し,その上に 256x256 の bitmap を WinDrawBitmap()で描画したときにエラーが発生しました. これは161x160 でも発生します. このため,30J/40J でも動作させるためには,ビットマップを 160x160 の単位に分割して, 作成する必要がありそうです.

カラー機種の注意点

GIMP には "Web" と呼ばれるパレットファイルがあり, PalmIIIc でもこの配置と同じパレットを使っています.

しかしこのままこのパレットを使うと,上の方にゴミが出て正しく表示されません. これは,"Web" が 216 色しか指定していないのに対し, PilRC でのパレットでは 256色(余り部分は「黒」) が前提になっているからです. そのためパレットファイルでは,40個のダミーの「黒」パレットを加えて,256個にしています.

※ 実は 40個の黒ダミーを用意すると,GIMP が画像を256色に減色するときに, 「黒」を"0"番目ではなく 40 個のダミーの方に変換してしまうかも知れません (「黒」は 41 個あるので,そのなかから勝手に選ぶ).

あくまでこのパレット配置では 後ろ 40 個の領域は「黒」なので問題ないのですが, 「未使用領域」なので,パレット配置が変更(追加)されると後で使用されることに なるかもしれません. そうなると,色変換された画像表示の黒部分が「黒」でなくなるという危険性があります.

解決する簡単な方法としては,40個のダミーを GIMP が変換しない色に定義しておいて, 画像を描く際にその色に近い色を決して使わない,という手があります. (プログラムで *.bmp の色コンバートが出来るのなら,40個のダミーのピクセルを 「黒」に置き換えるということも可能なんですけど...).

ちなみに,Palm_Gray4(4階調)パレットでは,黒が他の値に変換されないように, (11 11 11)〜(24 24 24) を定義しています.

GIMP 用パレットファイル

~/.gimp/palettes/Palm_Gray4

GIMP Palette
#Gray 16 (2bpp)
0   0   0       Black
11  11  11      -
12  12  12      -
13  13  13      -
14  14  14      -
15  15  15      -
16  16  16      -
170 170 170     LightGray
85  85  85      DarkGray
19  19  19      -
20  20  20      -
21  21  21      -
22  22  22      -
23  23  23      -
24  24  24      -
255 255 255     White

~/.gimp/palettes/Palm_Gray16

GIMP Palette
#Gray 16 (4bpp)
0   0   0      Black
17  17  17     Gray1
34  34  34     Gray2
51  51  51     Gray3
68  68  68     Gray4
85  85  85     Gray5
102 102 102    Gray6
119 119 119    Gray7
136 136 136    Gray8
153 153 153    Gray9
170 170 170    Gray10
187 187 187    Gray11
204 204 204    Gray12
221 221 221    Gray13
238 238 238    Gray14
255 255 255    White

~/.gimp/palettes/Palm_Color

GIMP Palette  #←ここから 
# 256 color
255 255 255
255 255 204
255 255 153
     :
     :
     :
0   0 102
0   0  51
0   0   0     #←ここまでは "Web" パレットと同じ
0   0   0     #←ここから
0   0   0
     :
0   0   0
0   0   0     # ここまでは 0 だけのパレットが 40 個分

戻る