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 --- 2025.