« 2007年1月 | トップページ | 2007年3月 »

2007年2月18日 (日)

圧縮されたSWFの書き出し

Flash SWF書き出しの覚書4

SWFではバージョン6以降で圧縮をサポートした模様。

SWFバージョン8の仕様書p.17に軽く説明があるだけだが、ZLIBを使って圧縮すべしとのこと。

ポイントは

・ファイルの頭に書き出す3バイトのシグニチャをFWS(非圧縮)からCWS(圧縮あり)にかえる
・ヘッダ部のFileLengthは、『圧縮前のファイルサイズ』を書き込む
・FileLengthの直後(先頭から8バイト目移行)から圧縮する


さっそくJavaで実装してみた。
最初に試した標準ライブラリのGZIPOutputStreamではうまくいかないが、同じく標準ライブラリのjava.util.zip.DeflaterOutputStreamで書き出してみたところ無事FlashPlayerで再生が可能になった。

恐ろしくサックリ動いたがこれで良いのかな?恐るべしJavaの標準ライブラリ。

2月 18, 2007 Java, SWF書き出し | | コメント (0) | トラックバック (0)

2007年2月15日 (木)

SWF書き出しで、パスの隙間があると

先日から開発しているFlashのSWF書き出しツールの覚書3

Javaで使うShapeはfloatで定義されているが、SWFはTWIPという不思議な単位で座標を定義している。

 TWIP=1/20ピクセル。

と考えてほぼ問題ない。


で、SWFで図形を描く時は、TWIPの変化分で表現していく。つまり行き先を指定する lineTo( x , y ) ではなく、移動分を指定する line( dx ,dy ) で描いていくような感覚。

その時に、Shapeの線や曲線を、前回の座標との差で描いていくと、殆ど問題なく図形が出来上がる。。が微妙に表示が崩れることがある。

A_1


これは、どうやらTWIPでパスの最後の点が正しく始点に戻っていない(つまり正しく閉じていない)時に起こる現象らしい。

とりあえずStyleChangeRecordで最初に点を移動する時に、始点として記憶し、ShapeのclosePathの時、閉じるための EdgeRecord を現在の点から原点に向けて描いてあげると正しく閉じて、変な状態が無くなりました。

他にもいくつも解決法が考えられるので、もっと正しい方法があるかもしれませんのであしからず。。

2月 15, 2007 SWF書き出し | | コメント (1) | トラックバック (0)

2007年2月14日 (水)

3次のベジェから2次のベジェ(B-Spline)に変換

FlashのSWF書き出しの覚書2

FlashのSWFでは3次のベジェが使えないため、表題のごとく

 3次のベジェから2次のベジェ(B-Spline)に変換

する必要があります。

で、WEBを探したのですが正しい方法が見つからず、ひとまず適当な変換を大急ぎ(約1時間)で実装し、やれやれと思ってたところ。。。ふとSWFの仕様書をよく読んだら、変換の仕方について書いてありました
(T_T)

詳しくはこちらをご覧下さい(英語です)
http://steve.hollasch.net/cgindex/curves/cbez-quadspline.html

大まかに説明すると、
1.3次のベジェC1の2本のコントロールの交点を2次のベジェのコントロールとして曲線C2を作る。
2.C2が、元の曲線C1を十分に近似できているか評価する
3.近似できていない場合は、元のC1をさらに二つに分割して、それぞれを再帰的に1の処理に当てはめる

というようなところでしょうか。評価の方式としては、C1の中点と、C2の中点の距離をチェックする方式を推奨しているようです。


私の実装は、面倒なので自動で2分割してました(ある問題があった時だけ再帰的に分割しています)
惜しいのですが、必要以上に点数が増えるので、改めて実装しなおそうと思います。


■追記
http://developer.apple.com/textfonts/TTRefMan/RM08/appendixE.html
にはもっとはるかに詳しく書いてありました

~・~・~・~・

ちなみに2次から3次の数学的に正しく変換できるようです。
SWFの仕様書によると、2次のコントロールポイントを2/3の長さに切って二つに分ければ、良いだけのようです。

2月 14, 2007 Java, SWF書き出し | | コメント (0) | トラックバック (0)

Flash SWFの書き出し(覚書)

ここ二日ほど訳あってJavaでSWF(Flash)を書き出すプログラムを書いています。

ほいで、誰のためとも無く覚書程度に書いておきます。

...

■SWFファイルフォーマット仕様書の取得

 SWFの仕様書(英語版)は全てAdobeから無料で提供されています(2007/2/14現在)

http://www.adobe.com/licensing/developer/

 Macromedia Flash (SWF) and Flash Video (FLV) File Format Specification (Version 8)

の中の

 Begin the licensing process for the File Format Specification .

 という部分をクリックして、登録すればダウンロードが可能となります。

 PDFで300ページ近くありますが、本気で作る気であれば印刷した方が良いでしょう。

 私はホッチキスで小分けにして閉じて、その都度、必要な部分だけをペラペラ見るようにしています。


■ByteとBit演算のユーティリティを準備

 まず、この手の書き出し処理でお約束の「リトルエンディアン」が出てきます。基本的に1バイト以上のデータ(32bit int型など)はリトルエンディアンで書き出すようです。
リトルエンディアンはそこらで説明されているのでそちらを参考にしてください。

 次はBit演算、フラグとして1bitを書き出したり、4bitや15bitなど任意のビット数で、数値を書き出せる必要があります。

 仕様書にはTYPEとして色々出てきますが大まかに紹介すると

 UI8 なら Unsigned Int 8 (bit) 負号なしINT
 SI16 なら Signed Int 16(bit) 負号付きINT

 UB[1]なら 負号なしのフラグ 0,1
 UB[4]なら 4ビットで表現される負号なしの数値(0~15)
 SB[5]なら 5ビットで表現される負号ありの数値(-16~15かな?)


□負号なしと負号付き

 UB[2]、SB[5]などのとき、Javaであれば >>> と >> をうまく使い分ければ簡単に実装できます。もちろん & , | <<などのビット演算はフル活用しますが。


□その他の型

 RECTなどの型が多々出てきます。

 SWFの仕様を全部カバーするつもりでなければ、あらかじめ全部実装しても殆ど無駄になりますので、必要になったら実装していった方が良いでしょう。


□Byte Align

 UI8などのTYPEは Byte Align(1バイトの境界で必ず分ける)しますが、UB[1]などの場合は、ビットをつなげて行きます。

 SWFのタグはUI16で始まるのでByteAlignされますが、曲線などを定義するShape RecordsはUB[n],SB[n]などのビット書き出しが続くため、次のShape Recordsにいく時もByte Alignされません。私はここでこけました。


■SWFTOOLSを取得

 SWFTOOLSの中のSWFDUMPというソフトを使うとSWFを書き出したあと、Flashなどを使わずに内容をチェックすることが出来ます。
http://www.swftools.org/


■書き出しサンプルの用意

 SWF書き出しの第一目標は、超簡単なSWFファイルを生成して目標どおりに動くかどうかを試すことではないでしょうか。しかし、意外に何を書き出したらよいか悩みます(悩みました)。一発目ではなかなか動かず、どこがいけないのか原因不明になります(数時間苦しみました)。

 仕様書を一生懸命読んでも解決の糸口が見つからず苦しんでいたところ、「もしや」と思い、仕様書の最後を見たら「A Simple Macromdeia Flash(SWF)File Dissected」なるおまけを発見。

 ここには非常にシンプルなSWFフォーマットのサンプルデータとその16進ダンプが書かれております。また1Byteずつどうしてそうなるのかを書いてあるため、これの通りに書き出すことを最初の目標にすると、ドツボにはまることが無くなるのではないでしょうか。

※これに気づかなかったら数日無駄にしていたかもしれません。


□FillStyle0/1

 FillStyle0を使うとFlash8上に読み込み(インポート)した時、理由は今のところ理解していませんが「塗り」が消えてしまいます(FlashPlayerでは見える場合もあります)。FillStyle1を使うとFlash上でもみえます。

2007/02/19 追記

曲線の進行方向の左側を塗る場合にFillStyle0、右側を塗る場合にFillStyle1を使うらしい(SWF8仕様書p.147)。

但し、FlashPlayerではFillStyle0/1の違いが表示に影響を与えていないように思われる。

一方で、Flash8に読み込んだ場合は、Fill Style 0/1の意味を厳密に区別しているようで、正しく左右を指定してないと表示が壊れてしまう。上記のFillStyle1で成功したのは、たまたま曲線の進行方向と一致したようです。

曲線の回転方向を意識して作り直します。。

□曲線

 Flashでは意外にも、2次のベジェ曲線?(B-スプライン?コントロールポイント1つのヤツ)しか対応していません。Illustratorのような3次のベジェ(コントロールポイント2つ)で出来たデータはうまいこと2次のベジェに変換して書き出す必要があるようです。


■あとは根性?

 最低限のSWFが問題なく書き出せたら、後は必要な機能をガンガン組み込んでいくだけではないでしょうか。
画像処理が分かっていて、英語がソコソコ読めて、ビット演算に慣れていれば、一週間でそれなりのSWFを書き出せるようになると思います。もちろん仕様をフルにカバーするのは死ぬほど大変でしょうが。。

2月 14, 2007 Java, SWF書き出し | | コメント (0) | トラックバック (0)