2012-01-17 16 views
1

Cairo image surfaceを使用する小さなPyGIプロジェクトがあります。これをsurface patternで拡大縮小し、Gtk.DrawingAreaでレンダリングします。Gtk.DrawingAreaまたはCairoパターンの内容をディスク上の画像に保存します。

スケールのバージョンをPNGファイルに書きたいと思います。私は元の表面からSurface.write_to_png()で書き込もうとしましたが、元のサイズ(つまりスケールされていない)だけを書き込むので、そこにこだわっています。

私はGtk.DrawingAreaからレンダリングされたイメージを取り出してディスクに書き込むことができたと思っていましたが、PyGIでこれを行う方法はわかりませんでした(これはGTK + 2でのみ可能です - save gtk.DrawingArea to file )。だから私は私のスケール画像をディスクに書き込む方法を理解しようとしています。

ここで表面を作成するコードがあります、それをスケールアップし、それをレンダリング:

def on_drawingarea1_draw (self, widget, ctx, data=None): 

    # 'widget' is a Gtk.DrawingArea 
    # 'ctx' is the Cairo context 

    text = self.ui.entry1.get_text() 
    if text == '': 
     return 

    # Get the data and encode it into the image 
    version, size, im = qrencode.encode(text) 
    im = im.convert('RGBA') # Cairo expects RGB 

    # Create a pixel array from the PIL image 
    bytearr = array.array('B', im.tostring()) 
    height, width = im.size 

    # Convert the PIL image to a Cairo surface 
    self.surface = cairo.ImageSurface.create_for_data(bytearr, 
               cairo.FORMAT_ARGB32, 
               width, height, 
               width * 4) 

    # Scale the image 
    imgpat = cairo.SurfacePattern(self.surface) 

    scaler = cairo.Matrix() 
    scaler.scale(1.0/self.scale_factor, 1.0/self.scale_factor) 
    imgpat.set_matrix(scaler) 
    ctx.set_source(imgpat) 

    # Render the image 
    ctx.paint() 

そしてここでは、PNGファイルに表面を書き込むためのコードです:

def on_toolbuttonSave_clicked(self, widget, data=None): 
    if not self.surface: 
     return 

    # The following two lines did not seem to work 
    # ctx = cairo.Context(self.surface) 
    # ctx.scale(self.scale_factor, self.scale_factor) 

    self.surface.write_to_png('/tmp/test.png') 

ので書き込みサーフェスはスケーリングされていないイメージを作成し、cairo.SurfacePatternにも書き込みメソッドはありません。

私の最後の手段は、gtk.DrawingAreaでレンダリングされたスケーリングされたイメージをフェッチし、GtkPixbuf.Pixbufまたは新しいサーフェスに配置し、それをディスクに書き込みます。 pixbufのアプローチはGTK + 2では動作しているようでしたが、GTK + 3では動作しませんでした。

どのようにスケーリングされたイメージをディスクに書き込むことができますか?

答えて

4

[OK]を、私は方法を見つけた:

Gtk.DrawingAreaGtk.Windowから派生したことを思い出し、私はGdkPixbuf.Pixbufに描画領域の内容を取得するにはGdk.pixbuf_get_from_window()機能を使用することができますを入力し、GdkPixbuf.Pixbuf.savev()関数を使用して、pixbufをディスク上のイメージとして書き込みます。

def drawing_area_write(self): 
    # drawingarea1 is a Gtk.DrawingArea 
    window = self.ui.drawingarea1.get_window() 

    # Some code to get the coordinates for the image, which is centered in the 
    # in the drawing area. You can ignore it for the purpose of this example 
    src_x, src_y = self.get_centered_coordinates(self.ui.drawingarea1, 
               self.surface) 
    image_height = self.surface.get_height() * self.scale_factor 
    image_width = self.surface.get_width() * self.scale_factor 

    # Fetch what we rendered on the drawing area into a pixbuf 
    pixbuf = Gdk.pixbuf_get_from_window(window, src_x, src_y, 
             image_width, image_height) 

    # Write the pixbuf as a PNG image to disk 
    pixbuf.savev('/tmp/testimage.png', 'png', [], []) 

これは動作しますが、まだ誰かがこれを確認することができるかどうかを確認するために素敵なことだろう正しい方法であるか、他の選択肢があるかどうかを確認します。

0

私は、描画イベントのハンドラに渡されるCairoコンテキストを使用して別のアプローチを見つけましたが、親ウィンドウのうちDrawingAreaよりも大きい領域を取得しました。

PixBufを使いましたが、最初にDrawingAreaのqueue_draw()メソッドを呼び出し、完全なレンダリングを強制して、イベントが処理されるのを待っていました。ドローハンドラを持っていました)。さもなければ、得られた画像は部分的に延伸されないことがある。

関連する問題