Flash SWF 画像入れ替え(PHP 編)
前回の課題のうち、ファイルサイズの更新処理と CWS の圧縮処理を入れて、 JPEG画像入れ替えまで実装してみた。
- JPEG 入れ替え
- その他諸々
CWS の圧縮で問題発生
PHP Warning: gzuncompress(): buffer error in /home/yoya/prog/flash/FlashSWF.php on line 42
google で探しても解決した例が見つからないので、php のソースを読んでみた。
(yum で PHP 5.1.6 (cli) を使っているが、)とりあえず最新版の 5.2.5 を取得。
- php の中にはメッセージがない
% pwd /home/yoya/src/php-5.2.5 % grep "buffer error" * */* */*/* %
- zlib の中を探す
% grep "buffer error" *.c zutil.c:"buffer error", /* Z_BUF_ERROR (-5) */ zutil.c (メッセージを定義してる場所) const char * const z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ "file error", /* Z_ERRNO (-1) */ "stream error", /* Z_STREAM_ERROR (-2) */ "data error", /* Z_DATA_ERROR (-3) */ "insufficient memory", /* Z_MEM_ERROR (-4) */ "buffer error", /* Z_BUF_ERROR (-5) */ "incompatible version",/* Z_VERSION_ERROR (-6) */ ""}; #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
- compress.c (実際に出力する場所)
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. <略> if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; err = deflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { deflateEnd(&stream); return err == Z_OK ? Z_BUF_ERROR : err;
伸張する時に長さを指定するけど、実際に伸張したらその長さを超えちゃったってだけか…
つまり、ファイル長フィールドの更新に失敗してると… ○rz
chara.swf と(それを read して write した) output.swf はファイルサイズが同じなんだけど。(そうなるように圧縮率を調整したし)
- chara.swf
addr : 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0x00000: 4357 5306 0048 2c00 789c 9cb9 6b5c 5259 CWS H, x k\RY ~~~~~~~~
- output.swf
addr : 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0x00000: 4357 5306 a86f 2800 789c 9cb9 6b5c 5259 CWS o( x k\RY ~~~~~~~~
確かに駄目だ
圧縮失敗の原因:
if ($magic == 'CWS') {
movie_and_body = gzcompress($movie_and_body, 6);
}
<略>
$this->_header['filelength'] = strlen($header_without_length) + 4 + strlen($movie_and_body);
えーっと… ファイル長フィールドには伸張した時のファイルサイズを入れないと駄目なのに、圧縮後のファイルサイズを入れてました…
そりゃ、伸張した時にバッファも足りなくなるさ… ○rz
$this->_header['filelength'] = strlen($header_without_length) + 4 + strlen($movie_and_body);
<略>
if ($magic == 'CWS') {
movie_and_body = gzcompress($movie_and_body, 6);
}
こうしないと。