PyGObject cairo

こんなページを見つけた。
Ubuntu忘備録: GdkPixbufを高速にリサイズ(cairo)

早くなるなら使ってみようかなと。
comipoli を PyGObject に戻すので Python3 で。

Gjs はリソースの cairo を使うけど PyGObject はモジュールを使う。
Pycairo は Fedora にはデフォルトで入っている。
Pycairo

手持ちの 7952x5304px な巨大画像を同じディレクトリに置いて以下を。

#!/usr/bin/env python3

import gi, sys, cairo, time
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib, GdkPixbuf

class AWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        self.d = Gtk.DrawingArea()
        self.d.connect('draw', self.on_draw)
        self.add(self.d)
        self.pixbuf = GdkPixbuf.Pixbuf.new_from_file('7952x5304.jpg')
        self.resize(600, 300)
        self.show_all()

    def on_draw(self, widget, cr):
        aw = widget.get_allocated_width()
        ah = widget.get_allocated_height()
        # method
        n = time.time()
        buf = self.pixbuf.scale_simple(aw//2, ah, GdkPixbuf.InterpType.HYPER)
        print('method  : {}'.format(time.time() - n))
        Gdk.cairo_set_source_pixbuf(cr, buf, 0, 0)
        cr.paint()
        # function
        i = time.time()
        buf2 = self.pixbuf_scale(self.pixbuf, aw//2, ah)
        print('function: {}'.format(time.time() - i))
        Gdk.cairo_set_source_pixbuf(cr, buf2, aw//2, 0)
        cr.paint()

    def pixbuf_scale(self, pixbuf, w, h):
        with cairo.ImageSurface(cairo.Format.ARGB32, w, h) as surface:
            cr = cairo.Context(surface)
            pw = pixbuf.get_width()
            ph = pixbuf.get_height()
            matrix = cairo.Matrix(w/pw, 0, 0, h/ph, 0, 0)
            cr.set_matrix(matrix)
            Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0)
            cr.paint()
            return Gdk.pixbuf_get_from_surface(surface, 0, 0, w, h)

class AApplication(Gtk.Application):
    __gtype_name__ = 'AApplication'
    def __init__(self):
        GLib.set_prgname('AApplication')
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        AWindow(self)
    
    def do_activate(self):
        self.props.active_window.present()

AApplication().run(sys.argv)

結果

三倍以上遅いんですけど、Python だからだろうか?
ちなみにこのマシンは i5-6500(skylake) 3.2GHz と内蔵グラフィックです。
このスペックでも 0.05 秒でリサイズできるのだから scale_simple で充分かと。