グレイスケールを設定する方法についてのメモです. ここでは,一般的な環境(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); |
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 で作ります.完成したら *.xcf(GIMP形式) で保存しておきます. もちろんレイヤなどの GIMP 上の特殊情報も後で修正に必要ならば残しておきます.
次に,PilRC に対応するビットマップを作成しますが, ここで注意しないければならないのは,PilRC はパレットを厳密に定義していることです. 単なる減色では PilRC では使えません. そのため,まずパレットを準備する必要があります.
~/.gimp/palettes/ ディレクトリに次のファイルを作ります.
※パレットダイアログで同じように作成することも出来ます.
GIMP にて,レイヤーやアルファチャネルなどを統合し,一枚の RGB 画像にしておきます (タイトルバーに "(RGB)" となっている).
この状態で,[画像]→[インデックス画像] でダイアログを開き, [カスタムパレットを使用] とパレットファイルを指定します.
多色画の場合はパレットの色に減色するため,ディザオプションを好みで選ぶことも出来ます. 指定しなければ最も近いパレットの色に変更されます.
※ここでパレットファイルが見つからない場合は,前項のパレットファイルの作成に 失敗しています.
インデックスモード(タイトルバーに "(indexed)" となっている)になった ところで保存します.形式は *.bmp にしておいて下さい.
これで,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); } |
以上で,カラーやグレイスケールのビットマップ表示が可能になります. 以下では,注意しなければならない点やその理由などについて書いています.
2bpp(グレー4階調)の場合,パレットは16個にしておく必要があります. これは PilRC でのパレット設定が 16階調を元にしているためです. また,16個のパレットは以下のように認識されます.
このため,単純に 0,1,2,3 の4パレットで 4階調を表現すると,blackとlightgrayしか 表示されなくなります. 正しく認識するためには,パレットファイルでこれらのパレットを正しく指定する 必要があります.
これは事例から発見したことですが, 以前,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 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 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 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 個分 |