GdkPixbufを高速にリサイズ(cairo)


GdkPixbufのサイズ変更を、元画像500x500px から 出力画像100x100~10x10pxで行うと、どうやらとても遅くなるようです。



GDK_POINTER_MOTION_HINT_MASK を使わずに motion-notify-eventをそのまま再描画に投げている私も悪いのですが。
とはいえ GDK_POINTER_MOTION_HINT_MASK はGtk3で思った通りにならず、アプリケーションがフリーズするようになっていました。

将来的には描画前のレンダリングをマルチスレッド化するつもりではいます。しかしシングルスレッドだと競合などを考えずに済み楽であるため、どうにもならなくなるまではシングルスレッドで行くつもりです。

というわけで、単純にリサイズ機能を高速化して対応。このあたりも、cairo任せにするといろいろオブジェクトを確保するコストを考えてもずっと早いのではないかというカンが当たった感じです。


なお、 gdk_pixbuf_scale_simple()をそのまま、画質を GDK_INTERP_HYPER からバイリニア指定に変えるのは試してみましたが、ほとんど効果なしでした。

なお画質は不明。見た目にわからないですし悪くないですが、アプリケーションが将来的に画質を指定するようになったら、リサイズ機能を見直そうと思います。

呼び出し例は以下。
====
/*

 
GdkPixbuf *pb = gdk_pixbuf_scale_simple(

 

 

 
pixbuf,

 
 
 
(int)w, (int)h,
 
 
 
GDK_INTERP_HYPER);
*/

 
GdkPixbuf *pb = _pv_copy_new_pixbuf_scale(
 
 
 
pixbuf,
 
 
 
(int)w, (int)h);
====

実装は以下。
====
static GdkPixbuf *_pv_copy_new_pixbuf_scale(GdkPixbuf *pb_src, double w_dst, double h_dst)
{
 
cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w_dst, h_dst);
 
pv_assert(surface);
 
cairo_t *cr = cairo_create (surface);
 
pv_assert(cr);

 
double w_src = gdk_pixbuf_get_width(pb_src);
 
double h_src = gdk_pixbuf_get_height(pb_src);

 
cairo_matrix_t m = {
 
 
w_dst/w_src, 0,
 
 
0, h_dst/h_src,
 
 
0, 0,
 
};
 
cairo_set_matrix(cr, &m);

 
gdk_cairo_set_source_pixbuf (cr, pb_src, 0, 0);
 
cairo_paint (cr);

 
GdkPixbuf *pb = gdk_pixbuf_get_from_surface(surface, 0, 0, w_dst, h_dst);
 
pv_assert(pb);

 
cairo_surface_destroy (surface);
 
cairo_destroy (cr);

 
return pb;
}
====

作ったPixbufは呼び出し元で開放しましょう。
以上です。

Linuxコマンドライン上でSVGベクタ画像をJPG等へラスタライズ変換する

 Linuxコマンドライン上でSVGベクタ画像をJPG等へラスタライズ変換することができるが、上手く変換されない場合がある。   以前作った魔法陣イラスト素材をイラスト素材ストックサイトへ登録しようと思い立ち、改めて素材用にラスタライズ変換をかけようとした。   ラスタライズ変換...