yoyaのメモ

2008/10/02(Thu) swfed-0.12 release

[]png_dump 改良

swfed-0.12 対応での調査用に、PALETTE フォーマットの時に含まれる色インデックス(いわゆるカラーマップ)情報の表示を追加しました。

libpng 的には

png_color *palette = NULL;
int palette_num = 0;
png_get_PLTE(png_ptr, png_info, &palette, &palette_num);

こんな感じに取得できて、

for (i = 0 ; i < palette_num ; i+=8 ) {
    printf("[%03d]", i);
    for (j = 0 ; (j < 8) && ((i+j) < palette_num) ; j++) {
        printf(" #%02x%02x%02x",
               palette[i+j].red,
               palette[i+j].green,
               palette[i+j].blue);
    }
    printf("\n");
}

こんな感じで参照できます。

プログラム

gcc png_dump.c bitstream.c -lpng

以下のページでも動作を確認できます。PNG ファイルを放り込むと内部で png_dump が動きます。

2008/09/01(Mon) テスト用 PNG ファイル生成

[]テスト用 PNG ファイル生成

PNG 画像の処理に色々と問題があるので、テストを綿密にやろうと

テスト用の PNG ファイルを作ってみました。

パレット形式かビットマップ形式か、何色使うかといったパターンを

手で作るのはやってられないので、プログラムで生成する事にします。

png_test.php

GD を使うと楽ですね。

<?php

$width  = 8;
$height = 8;

$im = imagecreatetruecolor($width, $height); /* bitmap */
// $im = imagecreate($width, $height);          /* palette */

$colors = array();
$colors []= imagecolorallocate($im, 255, 0, 0); // red
$colors []= imagecolorallocate($im, 0, 255, 0); // green
$colors []= imagecolorallocate($im, 0, 0, 255); // blue
$colors []= imagecolorallocate($im, 255,255,0); // yellow

for ($y=0 ; $y < $height ; $y++) {
    for ($x=0 ; $x < $width ; $x++) {
        $i = ($x + $y * $width) % 4;
        imagesetpixel($im, $x, $y, $colors[$i]);
    }
}

header("Content-type: image/png");
imagepng($im);

png_dump.c

とりあえず、何も考えずに dump してみる。

% ./a.out  ~/lang/php/16x16palette.png
png_filename=/home/yoya/lang/php/16x16palette.png
png_buff.data_len=94
(width, height)=(8,8) bpp=2 color_type=3(PALETTE) palette_num=4
y=0: 1b 1b 24 00 80 11 24 00
y=1: 1b 1b 00 00 00 00 00 00
y=2: 1b 1b 00 00 00 00 00 00
y=3: 1b 1b 00 00 00 00 00 00
y=4: 1b 1b 00 00 00 00 00 00
y=5: 1b 1b 00 00 00 00 00 00
y=6: 1b 1b 00 00 00 00 00 00
y=7: 1b 1b 00 00 00 00 00 00

ナルホド。

1b = 00011011 = 00 01 10 11 = 0 1 2 3

って事か。

吸い出したイメージ配列は bpp の bit width で並んでるようです。

png_dump.c 修正版

ビット処理を書くのが面倒なので、 swfed で作った bitstream.c を使いまわしました。

for (y=0; y < png_height; y++) {
    unsigned char *linedata = image_data[y];
    bitstream_t *bs = bitstream_open();
    bitstream_input(bs, linedata, png_get_rowbytes(png_ptr, png_info));
    printf("y=%lu: ", y);
    for (x=0; x < png_width; x++) {
        int colorindex = bitstream_getbits(bs, bpp);
        printf("%02x  ", colorindex);
    }
    bitstream_close(bs);
    printf("\n");
}

実行結果

% ./a.out 16x16palette.png
png_filename=16x16palette.png
png_buff.data_len=94
(width, height)=(8,8) bpp=2 color_type=3(PALETTE) palette_num=4
y=0: 00  01  02  03  00  01  02  03
y=1: 00  01  02  03  00  01  02  03
y=2: 00  01  02  03  00  01  02  03
y=3: 00  01  02  03  00  01  02  03
y=4: 00  01  02  03  00  01  02  03
y=5: 00  01  02  03  00  01  02  03
y=6: 00  01  02  03  00  01  02  03
y=7: 00  01  02  03  00  01  02  03

よし、完璧。(゜∇゜)

コンパイル方法

% gcc -Wall -W png_dump.c -lpng bitstream.c

使い方は上の通り。

追記 (2011/12/19)

imagemagick palette png」で検索された方はこちらも参考にどうぞ。