モブ沢工房

プログラミングとかLinux関連(特にOSSのグラフィックツール関連)とかレトロゲームとか3Dプリンタやら日曜大工等、色々。

MyPaintにPolyfilltoolを実装しています

MyPaint私家版にさらにPolyfilltoolを実装ッ!(途中)

イデアとしてはこうです。

「brushlibを弄ってポリゴンフィルを付けるのは面倒だが、pycairoで描いてそのサーフェスをgdk.pixbufに変換しさらにそれをmypaintのレイヤのメソッドload_surface_from_pixbufで流しこめば簡単に出来るのではないか?」

…と思って、思い立ったらガマンできない堪え性のないワタクシ *1は早速着手しました。

と思ったんですが、着想はよかったものの、中々上手く行かず。pycairo、gtk、そしてmypaintのクラス群と、分からない要素の数々がオイラを責め立てる…

しかし数日間の苦闘の後!!

遂に!!

遂にレイヤに描画することに成功しました!!!

f:id:dothiko:20160313141327j:plain

まだUIは作ってないけどグラデも出来る!

f:id:dothiko:20160313143914j:plain

Cairoにはメッシュグラデも実装されており、UIさえ作ればグフフのフっと…*2

とりあえず描画部分のコードだけ置いときますね(´・ω・`)

MyPaintソースの様々な部分からのコピペ多し…

            sx, sy, ex, ey = self._get_maximum_rect(None)
            sx = int(sx)
            sy = int(sy)
            w = int(ex-sx+1)
            h = int(ey-sy+1)
            surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
            cr = cairo.Context(surf)
            _draw_node_polygon(cr, None, self.nodes, ox=sx, oy=sy,
                    color=self.foreground_color)
            surf.flush()
            pixbuf = Gdk.pixbuf_get_from_surface(surf, 0, 0, w, h)
            layer = lib.layer.PaintingLayer(name='')
            layer.load_surface_from_pixbuf(pixbuf, int(sx), int(sy))
            del surf, cr

            tiles = set()
            tiles.update(layer.get_tile_coords())
            rootstack = self.doc.model.layer_stack
            dstlayer= rootstack.deepget(rootstack.current_path)
            dstsurf = dstlayer._surface
            for tx, ty in tiles:
                with dstsurf.tile_request(tx, ty, readonly=False) as dst:
                    layer.composite_tile(dst, True, tx, ty, mipmap_level=0)

            bbox = tuple(dstlayer.get_full_redraw_bbox())
            dstlayer.root.layer_content_changed(dstlayer, *bbox)

これが出来ると何が良いのか?と申しますと、かつてgimpがメインだった頃一時期凝っていた「パス塗り」が、gimpよりも遥かに簡単に手間なく出来てしまう点。

あと、このpixbuf変換 + レイヤ操作をマスターすれば…OpenCVを使った何らかの操作すら可能だろう…ということ…!!(利根川幸雄風

*1:いや〜この性格、マジに物理学者とかでなくてよかったですな…地球破壊爆弾とか思いついたらどうなっちゃうんだろ。オイラの頭が悪かったことに地球人類は感謝しなければならないと思う

*2:思ったんだけどまだpycairoでは対応してないみたい orz