Piet golfでハマる

npiet(1.3d時点)のGIF周りのバグや未実装機能など。全ピクセルを愚直に圧縮せず、末端(最終行など右下方面)は書かないというのがゴルフ的な手法だが、ハマリポイントだった。

まず、npietはGIFのimage部分しか見ていないため、Background Color Indexは無視される。GIFの規格を読んだ感じでは、imageが割り当たっていないpixelの色はBackground Colorで塗りつぶされるらしいので、Pietコードをterminateさせるために作るL字領域の作成に便利なのだが。

次に、エンコードされたピクセル数が一行の幅に足りない場合。GIFLIBはエラーを返すが、npietはそれを握りつぶしている(握りつぶしてくれなかったら大変だ)。このとき足りなかったピクセルはnpietが用意した状態のままで、color index 0が埋まった状態になっているようだ。mallocしただけの領域なので、理屈の上では他の値になってもおかしくないが、ヒープの末端かどこかのサラピンの領域がもらえているのかな。なので、color tableを作るときに、image末端のエンコードをサボる部分の色をcolor index 0にする必要がある。

さらにこれに関連してハマるポイントとして、ある行でピクセル数が足りずエラーが返ると、GIFLIBの内部ステート(ピクセルスタック)が変な状態で止まってしまい、次の行をnpietが処理したときに、先頭に(color index 0でなく)ゴミが描かれる場合がある。ゴミの正体は、複数ピクセルを表すコードを使ったときにエラーが返った行の上の行からエラーが返った行に持ち越したピクセル(長い)。たとえば以下の絵でいうと、右上のnB nRを一語にエンコードして、かつ、xxの部分で終了するようなソースコードを書いた場合、zzの部分はyy同様color index 0の色で塗られることを期待するが、実際はxxの行に持ち越したnRで塗られてしまう。

.. .. .. .. nB
nR .. xx yy yy
zz yy yy yy yy