PICのフォーマットについて '93-9-26 やなぎさわ ●はじめに 今までPICのフォーマットについてのまともな資料を作っていなかったので移植 者の皆さんにはかなり御迷惑をお掛けしたことと思います。実はまともで無い資料は 結構ありまして、少し根性があれば何とか判る物だったのですが。あまり出まわって いなかったのと、あまりまともではなかったので、いつも資料は無いですと面倒くさ がって言っちゃっていました(^^; 。 今回ある程度まとめた訳ですが、今更と言う感じもしますが許してください(^^; それから記憶があやふやな所もあるので(オイオイ) もし変なところに気付きましたら、 知らせください。またかなり手抜きになっていますので判りにくいかも知れませんが 許して下さい。 それからC言語のローダのソースを同封しましが、昔Oh!Xに掲載されたのと殆ど 同じ手抜き版です。対応はX68kの15ビット色でサイズは 512x512のみです。あくまで もPICのアルゴリズム理解の補助的なものと考えて下さい。 ●読み方 正式には「ぴっく」ですが、少しくらい違っても特に問題ありません。(^^; ●フォーマット ○概観およびヘッダ ファイルの先頭から次のようになっています。 'P' 1byte PICであることの印 'I' 1byte 'C' 1byte $1A以外 任意byte コメント部 $1A(EOF) 1byte コメントの終わりを示す 0以外 任意byte ダミー 0 1byte 真のコメントの終わり 0 1byte 予約 x 1byte bit 0..3 機種タイプ bit 4..7 機種毎のモード x 1word 色のビット数 x 1word X方向のサイズ x 1word Y方向のサイズ p nbyte パレットデータなど 内容は機種/モード/色数によって変わります (オリジナルは、ここは何もない) 以後圧縮データが入る なお、ワードデータは2バイトで並びはbig-endian(モトローラ)です。 ●圧縮部の説明 ここではX68kの15bit色(いわゆる基本のPIC)について説明をします。他のPI Cについては基本的には同じなので後の方で違う所だけを説明をします。 まず圧縮には大きく分けて可逆(完全に元に戻るもの)と非可逆(見た目に問題な い部分を省略する)のものがあり、PICは完全復元する前者の方です。そしてどん な圧縮でも絵を選ばず良い圧縮することはかなり難しいので、まず対象をはっきりさ せる事が重要になります。PICの場合にはセルアニメ調の絵に対して良い圧縮が得 られるように考えてあります。(それ以外の絵も、他の圧縮に比べて遜色無いレベル にはあると思っていますが) さて対象が決まるとその特性を利用して圧縮するわけです。アニメ調の絵の場合に は見れば判るように同じ色の画素が縦や横に広く連続しています。圧縮はこの性質を 利用して行うことになります。例えば簡単な方法としてはランレングス法が考えられ ます。これは画素を左から右へ見て、出てくる色とその色が何ドット連続しているか を記録する方法ですが、圧縮率はあまり高くありません。しかし色の変化点を出し、 位置と色を記録するというアイデアはPICの基本となります。つまりいかに変化点 を少なくして、いかに位置を効率良く記録して、いかに色データを少なく済ますかが 勝負と言えます。 まず変化点の出し方を考えてみます。 ■■■▲▲▲▲ ランレングスの場合は横方向のみなので、 ■■■■▲▲▲ これを何とか縦方向にも考慮したいと思 ■■■■■▲▲ うのは当然です。そこでPICでは輪郭 ■■■■■▲▲ をたどる事をしています。例えば図1の ■■■■▲▲▲ ような絵の場合にまず変化点を抽出しま ■■■▲▲▲▲ す。 図1 すると図2のようになります。これを ■□□▲□□□ みると判ると思いますが変化点の▲が下 ■□□□▲□□ の方にクネクネと伸びているのが判りま ■□□□□▲□ PICではこれを連鎖と言い、これを記 ■□□□□▲□ 録して変化点からは外して変化点の数を ■□□□▲□□ 減らしています。具体的に図2の場合に ■□□▲□□□ は、まず1ライン目の▲から2ライン目 図2 以降は、"右右下左左"となります。■は "下下下下下"となります。この連鎖を ■□□▲□□□ 取ると図3のようになり変化点は2つだ □□□□□□□ けになります。 □□□□□□□ なお、連鎖を辿るときの範囲ですが、 □□□□□□□ 注目点の下のラインの左右2ドットを □□□□□□□ 見て同じ色の変化点なら連鎖として、 □□□□□□□ さらに注目点をそこに移動させ無くなる 図3 まで繰り返します。なお、この連鎖の符 号化は図4のように行います。なお0/1は符号化されるビットで 01は2ビットで0と1に符号化されると言うことです。 無 連鎖 -----+----> 0 ----------------------------------------> 連鎖おわり | ^ |有 | ----> 1 ----+--> 00 ------+-------> 0 -----+ ^ | | | | | | | +----> 1 -+-->0 -->| | |--> 01 -->| | 左2 | | | 左 | | | | | | | | | | | |-->1 -->| | |--> 10 -->| 右2 | | | 中 | | | | | | | | | | | |--> 11 -->| | | 右 | | | | | +--------<----+------------<--------+ 図4 次に位置の記録ですが、横方向の変化点の距離を記録しています。そしてこの時、 長さを図5のように符号化しています。 1~2 0× 3~6 10×× 7~14 110××× 15~30 1110×××× 31~62 11110××××× 63~126 111110×××××× 127~254 1111110××××××× 255~510 11111110×××××××× ・ ・ ・ ・ ・ ・ ×は1か0で2進数です。 図5 これだと、例えば距離2を記録する時は、2進数で”01”の2ビットですむので 距離が短いほど少ないビット数で済みますし、効率自体もそこそこです。 最後に色の記録ですが、同じ色は近所にあることが多いと言うことを利用して 簡単なキャッシュをします。具体的には過去128色分をテーブルに取って置き、 次の色が来たときに既にその色がテーブル中にあれば、テーブル中に有るという フラグ+テーブル中の位置を記録するようにして、テーブル中に無ければ、無い というフラグ+色コードを記録するようにします。これで同じ色が頻繁に出てく る場合は、少ないビット数で済みます。符号化は図6のようになります。 色 --+--> 0 ----> 15ビットの色コード ------------+-------------> | | +--> 1 ----> 7ビットで色テーブルの位置-------+ 図6 またテーブルに無い色が出たときには、テーブルから最も古くに使用された色コー ドを捨てて代わりにこの新しい色をセットすることを行います。LRU法ですね。 なお、ここらへんの具体的な方法ですが。C言語ソースを別途UPしておきますので それを参考にして下さい。(^^; 以上の事をまとめると図7のようになります。 はじめ ------> 長さ ------> 色 ------> 連鎖 --+---> 終わり ^ | | | +----------------------------------- 図7 つまり圧縮の流れは、 1、まず絵から変化点を抽出する。(画面右端は下のラインの左端に続く) 2、変化点を探し、変化点間の長さ記録 3、変化点の色を記録する 4、その点を注目点として下のラインに連鎖があるか探す -- 連鎖があったら -- 4ー1、連鎖の位置を記録して、その点を変化点から外す 4ー2、さらに下のラインで連鎖を探す 4ー3、連鎖が無くなるまで繰り返す *なお連鎖は画面の左右端をまたぐ事はない 5、2へ戻り終わるまで繰り返す。 となります。なお2で変化点が無く画像が終わったら終わったところまでの 長さを出力して終わりとします。 展開は逆です(^^; ●色々なPIC PICは機種ごとに、その特性に合わせてフォーマットが微妙に違います。他機種用 のローダを作る人は何故? と思うかも知れませんが。その機種にとってはやはり専用 のフォーマットは便利で捨て難いものがあります。 (まあ今みたいにやたら早いマシンだらけだったら少しは違ったのでしょうけど) まずヘッダの次の所に種類が入っています。 x 1byte bit 0..3 機種タイプ bit 4..7 機種毎のモード 下位4ビットが機種をあらわし次の物があります。 機種タイプ | 機種 ==============+================ 0 | X68k 1 | PC-88VA 2 | FM-TOWNS 3 | MAC $F | 汎用 ------------------------------- なお基本的な圧縮方法は全て一緒で、比率、色数、パレットの有無などが違います ので、その違いのみを以下に説明していきます。 またパレットデータがある場合はサイズデータと圧縮データの間にパレットが色数分 だけ入ります。そして説明中にGGGRRRBBBIと書いてあった場合は上位ビットからG(緑) が3ビット、R(赤)が3ビット、B(青)が3ビット、I(輝度)が1ビットと言う意味で す。因みにIはRGBのそれぞれの下のビットになります。例えば上の例なら、赤=RRRIの 4ビット、緑=GGGIの4ビット、青=BBBIの4ビット、となります。 比率は人(CRT)により解釈が異なるのでおよその値と思ってください。 ○機種タイプ 0 : X68k PICのオリジナルです。拡張されたAPICは対応色数が増えただけですので まとめて説明をしていきます。なおサイズは可変です。 またモード情報は0のみです。 色数 | 比率 | パレット情報 | 色キャッシュ | その他 =======+============+==================+===============+======== 16 | 1:1 | GGGGGRRRRRBBBBBI | なし | *1 256 | 16:9 | GGGGGRRRRRBBBBBI | なし | 32768 | 16:9 | なし *2 | あり | 65536 | 16:9 | なし *3 | あり | -------+------------+------------------+---------------+-------- *1 画像が 512ライン超の場合に、連鎖バッファが普通だと縦ライン数分だけ 必要な所ですが、セーブ側で 512ライン目を連鎖がまたがないように記録 してあり、メモリが足りない場合なども 512ライン分の連鎖バッファを前 半と後半の 2回に分けて使うことにより省メモリ展開ができるように工夫 されているようです。 なお、メモリが十分にある場合は、ローダ側では上記の事は全く意識す ることなく展開できます。 *2 色は GGGGGRRRRRBBBBB の15ビット固定です。(I=0) *3 色は GGGGGRRRRRBBBBBI の16ビット固定です。 ・おまけ その1、pic.rで「もう読めないエラー」がでる APICファイルについて。 PICは可変bit長の記録をしていますが、pic.rでは内部のビットバッファ の都合により最後のビットが丁度バイト長になった場合でも数バイト余 分にデータが必要になっています。ところがAPICは内部のビットバッファ の方法が違うために、丁度の時は丁度でも良くなっています。そのせい か余分なデータを出力してくれないので pic.rではエラーが出る場合が 生じてしまうのです。 その2、正方PIC 512x512を1;1にするフォーマットです。ヘッダのコメント部に情報が埋 めこまれています。NIFTY/FGALAVのライブラリにUPされているので必要 な人は参考にすると良いでしょう。 ○機種タイプ 1 : PC-88VA 88VAには色々な手法が採用されています。まずは共通した特徴から ・比率について 88VAではPICは可変サイズではありません。いつでもフルスクリーン表示になっ ています。そのためPICのサイズデータがそのまま画面モードに対応していると 考えて下さい。 また基本的な比率はPC-98と同じで 640x400を表示すると約 1:1 となります。 例えば 640x200 では、これがフルスクリーンだから 640x400と比べると…縦が2 倍長いと言うことが判ると思います。 ただし、ちょっと例外があります。HRモードと呼ばれるモードですが、このモー ドの時はフルスクリーンのサイズがCRTの半分となります。つまり640x400中の320x 400だけに画像が表示されている感じになります。 ・サイズについて 88VAはサイズが画面モード分だけ(かな?)沢山あります。 そこで次のサイズは出来るだけサポートして下さい。 640x400(256色)/640x204/640x200/320x408/320x400/320x400(HR)/320x200 反対に 200x640(普通と逆)とかのサイズも88VAでは可能ですが、画像データと してUPされる事はまずないため、面倒な場合は特にサポートしなくても問題は無 いと思われます。 ・HRモード モードの0ビット目が立っている(0001)時はHRモードになります。 このモードでは 320x400が 1:1になります。 ・まとめると 色数 | 比率 | パレット | 色キャッシュ | その他 =======+============+==========+==============+======== 256 |サイズによる| なし *1 | なし | *4 4096 |サイズによる| なし *2 | あり | 65536 |サイズによる| なし *3 | あり | -------+------------+----------+--------------+-------- *1 色は GGGRRRBB の8ビット固定です。 *2 色は GGGGRRRRBBBB の12ビット固定です。 *3 色は GGGGGGRRRRRBBBBB の16ビット固定です。 *4 256色は 2種類ありひとつは普通の 256色。 もうひとつは一見64K色、実は256色モードです。 これはヘッダは64K色ですが、モードの 1ビット目が立っている(0010b)場合 にこのモードになり実は256色となります。 これは、タイリングされたデータを効率良く圧縮するための方法です。 ○●○●○●○●○● 0 一般的にタイリングは ●○●○●○●○●○ 1 右図のようになっています ○●○●○●○●○● 2 これをPICで圧縮しても ●○●○●○●○●○ 3 効率はあまり良くないので ○●○●○●○●○● 4 ●○●○●○●○●○ 5 これを変形します。まず図中の奇数ラインを偶数ラインの右にもってきます 0 ○●○●○●○●○●●○●○●○●○●○ 1 2 ○●○●○●○●○●●○●○●○●○●○ 3 4 ○●○●○●○●○●●○●○●○●○●○ 5 2ドットを1ドットとします(256色を64K色にする) [○●][○●][○●][○●][○●][●○][●○][●○][●○][●○] [○●][○●][○●][○●][○●][●○][●○][●○][●○][●○] [○●][○●][○●][○●][○●][●○][●○][●○][●○][●○] 見やすくするため[○●]を★、[●○]を☆とします。すると ★★★★★☆☆☆☆☆ ★★★★★☆☆☆☆☆ ★★★★★☆☆☆☆☆ となり見て判る通り始めの形よりもずいぶんすっきりします。 これにより、例では始めの 10x6 8bit色のデータが 10x3 16bit色のデータに なりました。つまり色は倍で、横は同じ、縦は半分のデータに変更されます。 そしてこれを記録します。 なお、ヘッダも16ビット色になりサイズも縦が半分になったデータが入ってい ますので注意して下さい。 ようはヘッダ通り16bit色としてバッファに展開して実際の画面に表示する時 に 8bitづつ 256色として表示するだけで普通はすみます。 因みに、16bit色は、上位が元の右側、下位が元の左側に配置されますので68系 な人は注意しましょう。 ・おまけ 2画面データですが、HRモードの横につながった2画面データは割と多いので余 裕のある機種の人は1画面に表示できると喜ばれるでしょう。 ○機種タイプ 2 : FM-TOWNS 比率が 1:1 である点を除けば全てX68Kと同じです。 なお、モードには"画面モード - 5"が入っています。主に入っているのは $0c/$05で $0cは普通の解像度のモードで $05は低解像度(320x240)モード です。ローダの作者は特にモードを意識する必要はありませんが、低解像 度の時に縦横2倍にするとより本物に近い雰囲気がでるかも知れません。 また色は32768色のみで並びはX68Kと同じで GGGGGRRRRRBBBBB です。 ○機種タイプ 3 : MAC 画面サイズは可変で比率は 1:1です。色は今のところ15ビット色のみ で並びは RRRRRGGGGGBBBBBとなっています。 ○機種タイプ $0F 機種タイプ $0Fには、PICを最後に拡張した部分が入っています。 主に 1:1 の256色データで使用されます。また1600万色もこれを 使用します。 また他のデータと違いヘッダの所が少し増えている注意して下さい。 ・モード モードの所には比率を入れてます。 モード | 比率 =========+===================== $00 | 1:1 $01 | X68kの512x512の比率(16:9) $0F | 後の比率情報による ------------------------------- ・ヘッダの拡張 通常のヘッダのYのサイズの後に以下のデータが順に続きます。(ワード=16bit) ・1ワードのセーブ座標 X(-1指定でなし) ・1ワードのセーブ座標 Y(-1指定でなし) ・1ワードで本当の比率 上位バイト:下位バイト(=横:縦) ($0101とか$0D09とか) ・1バイトでパレットのビット長 ( 256/16色の時のみ存在) ・パレットをGRB順で、それぞれビット長づつで詰め込む (256/16色の時のみ存在) ・これ以後圧縮データ なおパレットが半端なビットで終わっていても圧縮データは次のビット から入り特にバイト整合に合わせることはしない。 * モードの比率との関係ですが、普通はモードの比率情報を利用して こちらは無視しても良いとする。ただ律儀に比率を補間したい時には こちらを利用する。 ・まとめると 色数 | 比率 | パレット |色キャッシュ| その他 =======+============+==========+============+======== 16 |ヘッダによる| GRB順 *1 | なし | 256 |ヘッダによる| GRB順 *1 | なし | 4096 |ヘッダによる| なし *2 | あり | 32768 |ヘッダによる| なし *3 | あり | 65535 |ヘッダによる| なし *4 | あり | 24bit |ヘッダによる| なし *5 | あり | 32bit |ヘッダによる| なし *6 | あり | -------+------------+----------+------------+-------- *1 ビット数はヘッダによる *2 GGGGRRRRBBBBの12ビット固定 *3 GGGGGRRRRRBBBBBの15ビット固定 *4 GGGGGRRRRRBBBBBIの16ビット固定 *5 GGGGGGGGRRRRRRRRBBBBBBBBの24ビット固定 *6 決まっていない ・注意 このフォーマットは結構量があるのだけど、PIC2のからみとか色々あり たぶん全てが使われることは無いと思います。そこでローダが楽をする ために、1:1の256色以外のセーバを作成される予定の方がいましたら NIFTY/FGALAVの5番に間接的にでも良いので必ず連絡を下さい。 ●最後に PICを各機種に移植してくださったみなさん。そしてPICを利用して下さってい る皆さんどうもありがとうございます。作者の私がいい加減なため迷惑を掛けている事 もあるかと思いますがどうか許してください。そしてこれからもPICをよろしくお願 いします。 なお本資料の転載、引用すべて自由です(連絡不要)。 ついでにセーバ・ローダの作成は自由です。 NIFTY NCD01745 PC-VAN LVB06263 やなぎさわ