Site icon Tips Note by TAM

ZipファイルをFlash上で解凍する

ZIPで圧縮された画像ファイルをFlash上で解凍し、表示してみます。
テーマとしては古いのですが、ふと思いついたので試してみます。

他にも色々あるのかも知れませんが、主なライブラリは以下の二つのようです。
nocump
FZip

●nocump

まず、zipファイルをバイナリデータとしてロードします。

var load:URLLoader = new URLLoader();
load.dataFormat = URLLoaderDataFormat.BINARY;
load.addEventListener(Event.COMPLETE, loadComplete);
load.load(new URLRequest("zipファイルのパス"));

2行目、データフォーマットをBINARYにしておくのがポイントです。

次に、nochumpのライブラリを使用し、解凍します。

var zipFile:ZipFile = new ZipFile(loader.data);
for (var i:int = 0; i < zipFile.entries.length; i++) {
    var entry:ZipEntry = zipFile.entries[i];
    trace(entry.size); //ファイルサイズ
    trace(entry.name); //ファイルの名前
    var byte:ByteArray = zipFile.getInput(entry); //ファイルのByteArrayデータ
}

解凍し取り出したbyteArrayデータを使用して、画像をロードします。

var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, jpegLoadComplete);
loader.loadBytes(byte); //byteは取り出したbyteArrayデータ
this.addChild(loader);

以上でzip圧縮されたファイルから画像を取り出すことが出来ます。

欠点としては、解凍処理が走っている間は、他の全ての処理が止まってしまい、
ローディングのアニメーションすら動かなくなってしまうことです。
処理も遅いため、数メガのファイルを処理されると、数十秒間画面が固まってしまいます。
これではちょっと実用には向かないと思います。

この処理の遅さを改善されている方がいましたが、その通りにするとエラーが出てしまいます。
zipファイルのプレビュー | 水玉製作所

と、いうのも、この方は、ByteArrayクラスのinflate()を使用しているのですが、
この関数はAIRのアップデートに伴って廃止されました。
変わりに、uncompress()という関数に変更されています。
この部分を変更して対応しても、別の箇所でエラーが出てしまいます。

(Error: Error #2058: 圧縮データの解凍時にエラーが発生しました。)

そのため、遅い状態で使うしかないというのが現状だと思います。

参考サイト:
ActionScript 3.0 でZIPの圧縮と解凍 (Unknown Quality)
GRAM | グラム » ZipされたJPEGを扱う(複数)

●FZip

こちらは、zipファイルのロードと解凍を一度に処理してくれます。

var zip:FZip = new FZip();
zip.addEventListener(Event.COMPLETE, onComplete);
zip.load(new URLRequest("zipファイルのパス"));

function onComplete(e:Event):void {
    for (var i:int = 0; i < zip.getFileCount(); i++) {
        trace(zip.getFileAt(i).filename); //ファイル名
        trace(zip.getFileAt(i).sizeUncompressed); //ファイルサイズ
        trace(zip.getFileAt(i).date); //ファイルの更新日
        var byte:ByteArray = zip.getFileAt(i).content; //ファイルのByteArrayデータ
    }
}

ただし、ライブラリをそのまま使おうとするとエラーが発生しました。
これも前述のinflate()を使用しているためでした。
ですので、ライブラリ内のその部分をuncompress()に変更します。

[FZipFile.as]

//574行目
_content.deflate(); → _content.compress();
//599行目
_content.inflate(); → _content.uncompress();

あと、通常のzipファイルは読み込み時にエラーが出てしまいます。
この辺はよくわかっていないのですが、Alder32とかいうものを足す必要があるみたいです。
ダウンロードしたファイルのtoolsフォルダの中に、pythonとjavaのツールが入っていますので、
好きな方を実行して付加して下さい。
(pythonの場合はファイルの上にzipファイルをドロップすることで実行できました)

あとは、前述のnocumpと同じように取り出したbyteArrayデータを使用して画像をロードすれば完了です。

きっちりと測定はしていないので体感でしかないのですが、こちらの方が圧倒的に処理は早いです。
nocumpの場合数十秒かかっていたものが、数秒で出来るくらいに違いました。

ただし、こちらも解凍中は一切の処理が止まるようで、ローディングのアニメーションなどを表示させることは出来ません。

参考サイト:
[AS3]zip解凍 : Jinten Blog
FACEs: flashでmp3をzipで固めたのを読みこんで再生

●まとめ

FZipの方が圧倒的に処理が早いですが、zipファイルに特殊な加工をしなければいけないのが難点です。
また、解凍中はどちらもメモリをそこそこ食ってしまい、実用にはなかなか難しいかもしれません。
zipに圧縮する事で大幅にサイズを小さく出来る、というのなら検討してもいいかもしれません。

※利用の際はライセンスにご注意下さい。