Paepoi » PyGObject Tips » GdkPixbuf(PyGObject) Tips
GdkPixbuf(PyGObject) Tips
# 最終更新日 2019.09.14
新規追加。
単純に変換だけを行なうなら下記 pixbuf を savev してください。
init 内で読み込んでもいいのですが非同期にしないと全部完了するまで表示されません。
XPM 画像は GIMP 等で作成できるメタデータの画像形式です。
つまり文字列、配列内を Python の list としてコピペすればソースコードに埋め込み可能。
新規追加。
画像の変換とリサイズ
筆者が Gedit Plugin a_href_picture でやっている縮小画像作成です。単純に変換だけを行なうなら下記 pixbuf を savev してください。
#!/usr/bin/env python3 import gi, os gi.require_version('GdkPixbuf', '2.0') from gi.repository import GdkPixbuf # 同一ディレクトリにある画像ファイル名と縮小後の最大サイズを指定 FILENAME = '刀.jpg' MAX_SIZE = 300 pixbuf = GdkPixbuf.Pixbuf.new_from_file(FILENAME) aw = ah = MAX_SIZE w = pixbuf.get_width() h = pixbuf.get_height() if w > aw or h > ah: cleate = True if (aw * h) > (ah * w): width = w * ah // h height = ah else: width = aw height = h * aw // w smallpix = pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.BILINEAR) # jpeg と png を変換して保存 # 圧縮率は GIMP エクスポートのデフォルト値に合わせています name, ext = os.path.splitext(FILENAME) lext = ext.lower() if lext == '.jpg' or lext == '.jpeg': smallpath = f'{name}-{width}x{height}.png' smallpix.savev(smallpath, 'png', ['compression'], ['9']) elif lext == '.png': smallpath = f'{name}-{width}x{height}.jpeg' smallpix.savev(smallpath, 'jpeg', ['quality'], ['85'])
ZIP ファイル内画像の読み込み
筆者が Comipoli というアプリでやっている ZIP 内の画像読み込みです。init 内で読み込んでもいいのですが非同期にしないと全部完了するまで表示されません。
#!/usr/bin/env python3 import sys, re, gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GLib, Gio, GdkPixbuf ZIPFILENAME = '愛知JK.zip' class Win(Gtk.ApplicationWindow): ''' zipfile, subprocess モジュールを使ってもいいです そちらは Comipoli macOS 版でやっています GSubprocess は直接 input_stream を得られるのでコチラを利用 ''' def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title='Py') self.fbox = Gtk.FlowBox( valign=Gtk.Align.START, max_children_per_line=10, homogeneous=True, selection_mode=Gtk.SelectionMode.BROWSE) # ファイル名リストの作成 self.namelist = [] sp = Gio.Subprocess.new(['zipinfo', '-1', ZIPFILENAME], Gio.SubprocessFlags.STDOUT_PIPE) istream = sp.get_stdout_pipe() dstream = Gio.DataInputStream(base_stream=istream) while True: line = dstream.read_line_utf8()[0] if line == None: break if re.search('\.(jpe?g|png|gif)$', line, re.I): self.namelist.append(line) self.namelist.sort() # scroll = Gtk.ScrolledWindow(child=self.fbox) self.add(scroll) self.resize(300, 200) self.show_all() # 非同期読み込み開始 self.generator = self.add_thumbnail() GLib.idle_add(self.idle_function) def idle_function(self): try: next(self.generator) return True except StopIteration: return False def add_thumbnail(self): for name in self.namelist: ename = self._zip_escape(name) cmd_array = ['unzip', '-pj', ZIPFILENAME, ename] sp = Gio.Subprocess.new(cmd_array, Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_MERGE) sp.wait_check_async(None, self._on_wait) stream = sp.get_stdout_pipe() p = GdkPixbuf.Pixbuf.new_from_stream_at_scale(stream, 100, 100, True) image = Gtk.Image(pixbuf=p, visible=True) self.fbox.add(image) yield 1 def _zip_escape(self, filename): ''' unzip は以下をエスケープする必要あり ''' ESCAPE = '[]*?!^-\\' res = '' for s in filename: if s in ESCAPE: res += '\\' res += s return res def _on_wait(self, proc, res): ''' wait については fork wait で検索 ''' proc.wait_check_finish(res) class App(Gtk.Application): def __init__(self): Gtk.Application.__init__(self) def do_startup(self): Gtk.Application.do_startup(self) Win(self) def do_activate(self): self.props.active_window.present() app = App() app.run(sys.argv)
XPM 画像をソースに埋め込む
筆者が以前 Clipoli というアプリを作っていた時にやっていた手法です。XPM 画像は GIMP 等で作成できるメタデータの画像形式です。
つまり文字列、配列内を Python の list としてコピペすればソースコードに埋め込み可能。
#!/usr/bin/env python3 import gi, sys gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GLib, GdkPixbuf ICON = [ "32 32 3 1", " c None", ". c #000000", "+ c #FFFFFF", " ", " ............ ", " .++++++++++. ", " .++++++++++. ...... ", " .++++++++++. .++++. ", " .++++++++++. .++++. ", " .++++...+++. .++++. ", " .++++....... .++++. ", " .++++. .++++. ", " .++++. .++++. ", " .++++. .++++. ...... ", " .++++. .++++. .++++. ", " .++++. .++++. .++++. ", " .++++. .++++. .++++. ", " .++++. .++++. ...... ", " .++++. .++++. ", " .++++. .++++. ...... ", " .++++. .++++. .++++. ", " .++++. .++++. .++++. ", " .++++. .++++. .++++. ", " .++++. .++++. .++++. ", " .++++. .++++. .++++. ", " .++++. .++++. .++++. ", " .++++. .++++. .++++. ", " .++++....... .++++. .++++. ", " .++++...+++. .++++. .++++. ", " .++++++++++. .++++. .++++. ", " .++++++++++. .++++. .++++. ", " .++++++++++. .++++. .++++. ", " .++++++++++. .++++. .++++. ", " ............ ...... ...... ", " "] class Win(Gtk.ApplicationWindow): ''' Alt+A でボタンが押されるのが解る ''' def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title='Py') # Icon as XPM data pixbuf = GdkPixbuf.Pixbuf.new_from_xpm_data(ICON) image = Gtk.Image(pixbuf=pixbuf) self.add(image) self.show_all() class App(Gtk.Application): def __init__(self): Gtk.Application.__init__(self) def do_startup(self): Gtk.Application.do_startup(self) Win(self) def do_activate(self): self.props.active_window.present() app = App() app.run(sys.argv)
Copyright(C) sasakima-nao All rights reserved 2002 --- 2024.