gzip, zip

zip 書庫の中にある画像を表示したい。
もちろん展開ファイルを作らずメモリ内でやりくり。

って Gjs ではどうすればいいんだ?
Java なら ZipInputStream という便利なクラスがあるんだが。

ホイール欲しい ハンドル欲しい ? データ圧縮 zlib と gzip と zip (zlib で zip にアクセスする)

zlib でできるっぽい、サイト名が関係なさすぎでワロタ。
Gio で zlib はアクセスできるはず。

Projects/Vala/GIOCompressionSample – GNOME Wiki!

Vala コードだけど gir なら同様に扱えるはず。
ということでこんなコードを書いてみた。

#!/usr/bin/gjs

const Gtk = imports.gi.Gtk;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const GdkPixbuf = imports.gi.GdkPixbuf;

//const PATH = "akazukin.zip";
const PATH = "akazukin.gz";

const UnzipTestWin = new Lang.Class({
    Name: 'UnzipTestWin',
    Extends: Gtk.ApplicationWindow,

    _init: function(app) {
        this.parent({
            application: app
        });
        // Read gzip file
        let source = Gio.File.new_for_path(PATH);
        let stream = source.read(null);
        let converter = new Gio.ZlibDecompressor({
            //format: Gio.ZlibCompressorFormat.RAW
            format: Gio.ZlibCompressorFormat.GZIP
        });
        let cnv_stream = new Gio.ConverterInputStream ({
            base_stream: stream,
            converter: converter
        });
        // Create Pixbuf
        let pixbuf = GdkPixbuf.Pixbuf.new_from_stream(cnv_stream, null);
        let image = new Gtk.Image({
            pixbuf: pixbuf
        });
        this.add(image);
        this.show_all();
    }
});

const UnzipApp = new Lang.Class({
    Name: 'UnzipApp',
    Extends: Gtk.Application,

    _init: function() {
        GLib.set_prgname("UnzipApp");
        this.parent({
            application_id: 'org.sasakima.unzip',
            flags: Gio.ApplicationFlags.FLAGS_NONE
        });
    },
    vfunc_activate: function() {
        new UnzipTestWin(this);
    }
});
let application = new UnzipApp();
application.run(null);

gzip は上手くいったけど zip はダメだ。
そんなに甘くはなかった、いや筆者が無知なだけかも。
てか gzip は普通 tar とセットだ、tar も展開しないと…

いや違うだろ、zip でなきゃ意味が無いんだ。
何を作ろうとしているかバレバレ臭いのは気にしない。

ええい面倒だ、Python3 の zipfile を使ってしまえ!
スクリプト言語の速度で大丈夫かな?試してみるべ。

#!/usr/bin/env python3

import sys, zipfile, gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GLib, GdkPixbuf

PATH = "なえコレ.zip";

class UnzipTestWin(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        fbox = Gtk.FlowBox(valign=Gtk.Align.START, min_children_per_line=5)
        datas = []
        # unzip
        with zipfile.ZipFile(PATH) as f:
            l = f.namelist()
            for name in l:
                d = f.read(name)
                datas.append(d)
        for data in datas:
            stream = Gio.MemoryInputStream.new_from_data(data)
            p = GdkPixbuf.Pixbuf.new_from_stream(stream)
            minp = p.scale_simple(80, 100, GdkPixbuf.InterpType.BILINEAR)
            image = Gtk.Image(pixbuf=minp)
            fbox.add(image)
        self.add(fbox)
        self.show_all()


class UnzipApp(Gtk.Application):
    def __init__(self):
        GLib.set_prgname("UnzipApp");
        Gtk.Application.__init__(
            self,
            application_id="apps.test.naecore",
            flags=Gio.ApplicationFlags.FLAGS_NONE )

    def do_activate(self):
        UnzipTestWin(self)

app = UnzipApp()
app.run(sys.argv)

naekore

なんだ一瞬だった。
これなら速度も問題ないし簡単だし Python で作ることにしよう。
しかし PyGObject でもプロパティ指定がすっかり Gjs 風になってしまった。