[Armadillo:06685] Re: GDK 画像表示の縮小でのメモリ問題
MasakiAoyama
email@hidden
2011年 1月 31日 (月) 13:09:02 JST
青山です。
> - g_pixbuf_base_image: 原寸サイズの元イメージのpixbuf (global 変数)
> - pixbuf: gdk_pixbuf_render_to_drawable用の一時的な pixbuf
>
> という用途に使おうとしているわけですよね?
>
> たぶん image_expose_event() の中で毎回 pixbuf を生成していては、速度的
> に遅いため、一時的なバッファとしての pixbuf を引数で渡しているのだと想
> 像しました。ところが、gdk_pixbuf_scale_simple()は、スケールしたpixbuf
webに転がってる画像表示の参考ソースから見よう見まねでやりました。
pixbuf = gdk_pixbuf_new_from_file("image.xpm", &err);
g_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
GTK_SIGNAL_FUNC(expose_event), pixbuf);
としておいて、
gtk_widget_queue_draw (GTK_WIDGET(drawing_area));
を呼んだら、
gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
が呼ばれて、引数dataをpixbufのポインタに入れて再描画する。という。
GdkPixbuf *pixbuf = (GdkPixbuf *)data;
gdk_pixbuf_render_to_drawable (pixbuf, widget->window,
widget->style->fg_gc[GTK_STATE_NORMAL],
0, 0, 0, 0,
gdk_pixbuf_get_width(pixbuf),
gdk_pixbuf_get_height(pixbuf),
GDK_RGB_DITHER_NORMAL, 0, 0);
gdk_pixbuf_new_from_fileで作成したpixbufの領域をg_signal_connectで関連づ
けといて、expose_event内で使ってるってことですね。
> であれば、scale する時に新しい pixbuf を生成しない gdk_pixbuf_scalel()
> を使うというのはどうでしょうか? 新しく pixbuf を生成しない、つまりメモ
やってみました。
gdk_pixbuf_scale(g_pixbuf_base_image, pixbuf,
0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 0, 0,
(IMAGE_WIDTH/IMAGE_BASE_WIDTH),
(IMAGE_HEIGHT/IMAGE_BASE_HEIGHT), GDK_INTERP_NEAREST);
これでうまく行きました。
> ちなみに、scale しないのであれば、わざわざ一時的な pixbuf に copy しな
> くても、gdk_pixbuf_render_to_drawable() でオフセットを指定すれば
> widget->window に直接 g_pixbuf_base_image の一部を書き込むことが
> できますよ。オフセットは第4引数と第5引数です。
これも確認できました。gdk_pixbuf_copy_areaを使わずに済ませますね。
無駄なアクション減らせて、「本来こうするべき」な形になりました。
どうもありがとうございました。
以上
Yasushi SHOJI <email@hidden> wrote:
> At Fri, 28 Jan 2011 14:15:39 +0900,
> MasakiAoyama wrote:
> >
> > 先ほどのソースで、gdk_pixbuf_render_to_drawableのあとに
> >
> > gdk_pixbuf_unref (pixbuf);
> >
> > とだけ書いてたら落ちるので、てっきりやったらいかんのかと思ってしまってま
> > したが、
> > gdk_pixbuf_scale_simpleのときは新しく作ってるから解放がいるが、
> > gdk_pixbuf_copy_areaのときはやらなくていい(表示に使っているのをそのまま
> > 使っている?)
> > ってことだったんですね。
>
> その通りですね。
>
> image_expose_event()をどのように呼び出しているか分らないので、なんとも
> 言えませんが適当に考えてみました。コードの中には g_pixbuf_base_image,
> pixbuf という二つの変数があり、それぞれ
>
> - g_pixbuf_base_image: 原寸サイズの元イメージのpixbuf (global 変数)
> - pixbuf: gdk_pixbuf_render_to_drawable用の一時的な pixbuf
>
> という用途に使おうとしているわけですよね?
>
> たぶん image_expose_event() の中で毎回 pixbuf を生成していては、速度的
> に遅いため、一時的なバッファとしての pixbuf を引数で渡しているのだと想
> 像しました。ところが、gdk_pixbuf_scale_simple()は、スケールしたpixbuf
> のコピーを新しく生成し、その pixbuf へのアドレスを戻してしまうため、今
> 回のリークに繋っています。
>
> 逆に gdk_pixbuf_copy_area() では、渡された元 pixbuf の一部を、書き込み
> 先 pixbuf にコピーするという処理をします。そのため、新しい pixbuf が生
> 成されるわけではありません。それなのに、unref してしまうと次の expose
> 時に unref された pixbuf を使おうとして落ると思います。
>
> であれば、scale する時に新しい pixbuf を生成しない gdk_pixbuf_scalel()
> を使うというのはどうでしょうか? 新しく pixbuf を生成しない、つまりメモ
> リの確保を行なわないので処理が(ほんの少しだけ)早くなりますし、copy 時と
> 同じように「渡された pixbuf を一時的なバッファとして使う」ことができる
> のではないでしょうか?
>
> ちなみに、scale しないのであれば、わざわざ一時的な pixbuf に copy しな
> くても、gdk_pixbuf_render_to_drawable() でオフセットを指定すれば
> widget->window に直接 g_pixbuf_base_image の一部を書き込むことが
> できますよ。オフセットは第4引数と第5引数です。
>
> scale しながら drawable に書く処理は、前に探したときになかったように記
> 憶しています。間違ってたらごめんなさい。
> --
> yashi
>
> _______________________________________________
> armadillo mailing list
> email@hidden
> http://lists.atmark-techno.com/cgi-bin/mailman/listinfo/armadillo
----------------------------------
株式会社 レイトロン 新事業推進部
青山 真樹 email@hidden
armadillo メーリングリストの案内