These pages are written by only Japanese.

Welcom to My Diary.com
最新の日記タイトル一覧カテゴリ別タイトル一覧トップへ戻る〜

こんばんわ♪ 現在は3月29日(金)20時33分。 8時を過ぎてしましました。


hns - 日記自動生成システム - Version 2.19.5 (色々 Fixed)

先月 2008年07月 来月
01 2 3 04 05
06 07 08 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Namazu for hns による簡易全文検索です。
詳細は 詳細指定/ヘルプをご参照下さい。
検索式:

2008年07月11日(金)

swfed Lossless 画像対応

予定より一日遅れて、parse & build 処理実装完了。

実行結果:

php swfdump.phps  5791.swf
<略>
[12397] tag=DefineBitsLossless2(36)  length=9938
        image_id=1136  format=5  width=160  height=160
        argb bitmap exists
<略>
[12748] tag=DefineBitsLossless2(36)  length=2471
        image_id=1196  format=5  width=80  height=80
        argb bitmap exists
<略>

プログラム:

mkdir -p ~/public_html/diary/data/2008/07/11/swfed
cp config.m4  swfed.c php_swfed.h \
     swf_*.? jpeg_segment.? bitstream.? swf*.phps \
     ~/public_html/diary/data/2008/07/11/swfed/.

修正:

ビットマップデータ部は zlib 圧縮がかかっているので、 それの伸張処理を入れました。

2008年07月14日(月)

(ファイルでなく)配列変数で PNGデータを libpng に渡す方法

これ の続き
libpng で(ファイルストリームでなく)配列変数から直接PNGデータを 読み書きする方法がようやく分かったので、その顛末。

調査:

libpng の使い方のページを探しても、ファイルポインタを渡すのばかりで メモリオブジェクトを直接渡すサンプルプログラムが殆ど見つかりません。 その上、見つけたモノもオーバーフロウの対策が入ってない(ように見える)ので、 libpng.txt を見直すことにしました。
libpng にある入出力はpng_read() や png_write() を通して処理されます。
現行では fread() や fwrite() を呼ぶだけです。FILE * は png_struct
内部に記憶され、png_init_io() を経由して初期化されます。
I/O 命令を変更したいなら、png_init_io() を呼ぶ代わりに実行時に
png_set_read_fn() と png_set_write_fn() 関数を通してライブラリ指定
のコールバックを設定することができます。
という事ですが、
png_set_read_fn(png_structp read_ptr,
                voidp read_io_ptr, png_rw_ptr read_data_fn)
png_set_write_fn(png_structp write_ptr,
                  voidp write_io_ptr, png_rw_ptr write_data_fn,
                  png_flush_ptr output_flush_fn);
voidp read_io_ptr = png_get_io_ptr(read_ptr);
voidp write_io_ptr = png_get_io_ptr(write_ptr);

void user_read_data(png_structp png_ptr,
                    png_bytep data, png_size_t length);
void user_write_data(png_structp png_ptr,
                     png_bytep data, png_size_t length);
void user_flush_data(png_structp png_ptr);
API群を見てもいまいちピンと来ないので、 「png_set_write_fn」で検索したところ以下のページを発見。
png_get_io_ptrによって、png_set_read_fun/png_set_write_funで与えた引数を
png_ptrで示されるコンテキストオブジェクトから取得できるので、それを
ストリームへのポインタにキャストして仕事をまっとうしているわけです。
あー。なるほど。
libpng.txt にも同じ意味の事が書いてありますが、 こういう説明の仕方でないと自分には分からないのです。^^;
static void png_default_write_data(png_structp png_ptr,png_bytep data,png_size_
t length)
{
        OSErr   err;
        long    llong=length;
        short   refNum=((MyPNGFileRec *)png_ptr->io_ptr)->refNum;

        err=FSWrite(refNum,&llong,data);
        if (err!=noErr)
        {
                png_error(png_ptr,"Write Error");
        }
}
なるほど。なるほど。
コンテキストオブジェクトに汎用ポインタで任意の構造体データを渡せるので 最大長も一緒に渡してカスタム関数でオフセットと長さの比較をすれば、 オーバーフロウを防御できそうです。

テストコード:

typedef struct my_png_buffer_ {
    unsigned char *data;
    unsigned long data_len;
    unsigned long data_offset;
} my_png_buffer;

void png_memread_func(png_structp png_ptr, png_bytep buf, png_size_t size){
    my_png_buffer *png_buff = (my_png_buffer *)png_get_io_ptr(png_ptr);
    if (png_buff->data_offset + size <= png_buff->data_len) {
        memcpy(buf, png_buff->data + png_buff->data_offset, size);
        png_buff->data_offset += size;
    } else {
        png_error(png_ptr,"png_mem_read_func failed");
    }
}

void png_data_read(png_structp png_ptr, my_png_buffer *png_buff) {
    png_set_read_fn(png_ptr, (png_voidp) png_buff,
                    (png_rw_ptr)png_memread_func);
}
こんな感じでいいかな。

結果:

正常なファイル。(3x3 の青い画像)
% ./a.out cyan_3x3.PNG
png_filename=cyan_3x3.PNG
png_buff.data_len=152
(width, height)=(3,3) bpp=8 color_type=2
異常なファイル1 (バッファオーバーフロウ)
% ./a.out cyan_3x3-cut.PNG
png_filename=cyan_3x2-cut.PNG
png_buff.data_len=91
libpng error: png_mem_read_func failed
アボートしました
ファイルの後ろを少し削ったファイルを渡したところ、 長さチェックで弾いてくれました。よしっ。

ついでに:

↑ここで紹介されてた異常なファイル (何かの攻撃用らしい)
% ./a.out pngtest.png
png_filename=pngtest.png
png_buff.data_len=8574
libpng error: PNG unsigned integer out of range.
アボートしました
ふむ。完璧。
続く

swfed 要望

Lossless 対応が一息ついたら、こちらに取り掛かる予定です。

2008年07月16日(水)

メールが届かない。

今朝から awm.jp にメールが届かなくなっていたので、調査。

ディスク溢れ:

メールは /var/spool/ に貯めてますが、 /var を 100% 使い切ってました。
# du -sk *
	<略>
3724    php-pear
2402880 yum
/var/cache/yum が多すぎるので /awm/yum_cache を作って、そこに退避。

named が動いていない:

named が死んでいたので restart したのですが起動しません。 原因は、named.pid を格納するフォルダの所有者が root になっていた事。 あれ、以前は named だったはずなのに…
とりあえず、chown named して解決。

PNGデータのdump

前回のコード ではヘッダ情報の表示をしましたが、 今度は画像データも吸い出してみました。

プログラム:

    image_data = (png_bytepp) malloc(png_height * sizeof(png_bytep));
    for (y=0; y < png_height; y++) {
        image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, info_ptr));
    }
    png_read_image(png_ptr, image_data);
    for (y=0; y < png_height; y++) {
        printf("y=%lu: ", y);
        for (x=0; x < png_width; x++) {
            printf("%02x%02x%02x  ",
                   image_data[y][3*x],
                   image_data[y][3*x+1],
                   image_data[y][3*x+2]);
        }
        printf("\n");
    }

実行結果:

% ./png_dump  cyan_3x3.PNG
png_filename=cyan_3x3.PNG
png_buff.data_len=152
(width, height)=(3,3) bpp=8 color_type=2
y=0: 00ffff  00ffff  00ffff
y=1: 00ffff  00ffff  00ffff
y=2: 00ffff  00ffff  00ffff
%

課題:

depth8 の RGB データ以外のファイルを食わせた場合に どうなるのかは分かりません。
1pixel 3byte 決めうちにしてるので、多分ダメそうですが。^^;

2008年07月17日(木)

PHPカンファレンス2008 LT ネタ採用通知

ライトニングトークの採用通知が来ました。 「7/16(火)頃までに」だったので、もしかして忘れられたのかなと心配してました。(汗
さて、今日中に帰宅してデモを作りつつ、発表資料をまとめますか。 ネタはこれ↑

2008年07月18日(金)

swfed Lossless 画像入れ替え一部対応

何となくできました。
ただし、color_type が 8bit RGB でαチャネル無しのみ対応です。

実行結果:

まず入れ替えたい画像を探します。
% php  swfdump.phps 5791.swf
	<略>
[12397] tag=DefineBitsLossless2(36)  length=9938
        image_id=1136  format=5  width=160  height=160
        argb bitmap exists
image_id 1136 の画像を見つけたので、それを入れ替えてみます。
% php  swfreplacepngdata.phps 5791.swf 1136 cyan_3x3.PNG   > tmp.swf
さて、dump して確認。
% php  swfdump.phps 5791.swf
	<略>
[12397] tag=DefineBitsLossless(20)  length=22
        image_id=1136  format=5  width=3  height=3
        xrgb bitmap exists
入れ替わりました… ( ̄― ̄)
後でαチャネル処理も実装しようっと。

プログラム:

メモリチェック:

少なくとも正常系では free 忘れはないようです。
さすが自分。(*'ω'*)

libpng で (ファイルを介さず) PNG データを生成する

↑このサイトを参考にしました。
typedef struct my_png_buffer_ {
    unsigned char *data;
    unsigned long data_len;
    unsigned long data_offset;
} my_png_buffer;

void png_data_write_func(png_structp png_ptr, png_bytep buf, png_size_t size){
    my_png_buffer *png_buff = (my_png_buffer *)png_get_io_ptr(png_ptr);
    unsigned long new_data_len;
    if (png_buff->data_offset + size > png_buff->data_len) {
        new_data_len = 2 * png_buff->data_len;
        if (png_buff->data_offset + size > new_data_len) {
            new_data_len = png_buff->data_offset + size;
        }
        png_buff->data = realloc(png_buff->data, new_data_len);
        if (png_buff->data == NULL) {
            fprintf(stderr, "can't realloc: new_data_len(%lu), data_len(%lu)\n",
                    new_data_len, png_buff->data_len);
            png_error(png_ptr,"png_data_write_func failed");

        }
        png_buff->data_len = new_data_len;
    }
    memcpy(png_buff->data + png_buff->data_offset, buf, size);
    png_buff->data_offset += size;
}

void png_data_write(png_structp png_ptr, my_png_buffer *png_buff) {
    png_set_write_fn(png_ptr, (png_voidp) png_buff,
                     (png_rw_ptr)png_data_write_func, NULL);
}

/* ... */

    my_png_buffer png_buff;
    png_buff.data = NULL;
    png_buff.data_len = 0;
    png_buff.data_offset = 0;
    png_data_write(png_ptr, &png_buff);

    png_write_info(png_ptr, info_ptr);
    png_write_image(png_ptr, image_data);
    png_write_end(png_ptr, info_ptr);

実行結果:

% ./a.out foo.png
png_filename=foo.png
(width, height)=(3,3) bpp=8 color_type=2
png_buff.(data=0x8b9ebf8,data_len=128,data_offset=96)
%
% ./png_dump foo.png
png_filename=foo.png
png_buff.data_len=96
(width, height)=(3,3) bpp=8 color_type=2
y=0: 102030  102030  102030
y=1: 102030  102030  102030
y=2: 102030  102030  102030
出来たー。(*'ω'*)

これで、5 日分だよ〜。

タイトル一覧
カテゴリ分類
Database
JXTA
Java
XML
awm
bookmark
keyword
memo
news
research
Powered by hns-2.19.5, HyperNikkiSystem Project