mieki256's diary



2019/11/02() [n年前の日記]

#1 [kivy][python] Kivyのcanvasに描画した図形をファイル保存

Kivy の canvas に描画した図形を画像ファイルとして保存できるかどうか調べたり。

Kivy の Widget には、export_to_png() というメソッドがあって、ソレを使えば pngファイルとしてWidget内の様子を画像保存できる模様。

動作確認環境は、Windows10 x64 1903 + Python 2.7.17 32bit + Kivy 1.11.1。

動作確認。 :

以下のように表示されるスクリプトを書いて動作確認。

02_canvas2.ss01.png

  • Drawをクリックすると図形を描画。
  • Save をクリックすると、output.png という画像ファイル名で見た目を保存。

ソースは以下。

_02_canvas2.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.graphics import Ellipse
from kivy.graphics import Line
from kivy.graphics import Rectangle
from kivy.graphics import Color
from kivy.graphics import Translate
from kivy.graphics.texture import Texture
from kivy.properties import ObjectProperty
from kivy.lang import Builder

from kivy.config import Config
Config.set('graphics', 'width', '512')
Config.set('graphics', 'height', '512')

output_filename = "./output.png"

# my.kv
Builder.load_string('''
#:kivy 1.11.1
<MyWidget>:
    BoxLayout:
        size: root.size
        orientation: "vertical"

        MyPaintImage:
            id: myimage
            texture: self.texture_image
            size_hint_y: 0.9

            canvas.before:
                Color:
                    rgba: 0, 0, 0, 1
                Rectangle:
                    pos: self.pos
                    size: self.size

        BoxLayout:
            size_hint_y: 0.1

            Button:
                id: btn_draw
                text: "Draw"
                on_press: myimage.draw_shapes()

            Button:
                id: btn_save
                text: "Save"
                on_press: myimage.save_canvas_image()
''')


class MyPaintImage(Image):
    texture_image = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(MyPaintImage, self).__init__(**kwargs)
        self.texture_image = Texture.create(size=self.size)

    def draw_shapes(self):
        bx, by = self.pos
        with self.canvas:
            Translate(bx, by)

            Color(0.1, 0.4, 0.1)
            Rectangle(pos=(0, 0), size=self.size)

            Color(0, 0.75, 0)
            Rectangle(pos=(16, 64), size=(300, 200))

            poslist = [
                32, 32,
                480, 420,
                480, 32,
            ]
            Color(1, 0, 0, .3)
            Line(points=poslist, width=6, close='True')

            Color(0, .5, 1, 0.5)
            Ellipse(pos=(76, 50), size=(360, 360))

            Translate(-bx, -by)

    def save_canvas_image(self):
        self.export_to_png(filename=output_filename, scale=1.0)
        print("save %s" % output_filename)


class MyWidget(Widget):
    def __init__(self, **kwargs):
        super(MyWidget, self).__init__(**kwargs)


class MyApp(App):
    def __init__(self, **kwargs):
        super(MyApp, self).__init__(**kwargs)
        self.title = 'Simple Graphics Test 2'

    def build(self):
        return MyWidget()


if __name__ == '__main__':
    MyApp().run()

  • 今回は、.kv ファイルを .py の中に含めて記述してみた。Builder.load_string(''' ... ''') の中に、.kv の内容が記述されている。
  • .kv の中で、自作クラスを記述することもできるらしい。今回、MyPaintImage を作っているけれど、そのクラス名も記述できている。
  • draw_shapes() が、canvas に図形を描画している部分。
  • save_canvas_image() が、その Widget の見た目を画像保存してる部分。
  • draw_shapes() の中で Translate(x, y) が呼ばれているけど、これをしておかないと、その Widget の位置ではなく、ウインドウ全体の位置で描画されてしまう。図形を描画し終わったら、元の位置に戻すための Translate(x, y) を呼ぶ。

Save をクリックして保存されたpngファイルは以下。

output.png

ちゃんと保存されてるっぽい。

課題。 :

canvasサイズを指定することはできるのだろうか…。例えば、512x512、1024x1024、2048x2048等に決め打ちできれば、画像生成をするためのツールなども作れそうだけど…。

ウインドウサイズを変更すると canvasサイズも変わってしまってゴミが見えてしまうのだけど。texture に図形を描画することができれば、Image に texture を指定することでそういう問題は起きないはず。ただ、texture に図形描画をする方法が分からない。Kivy でそんなことはできるのだろうか…。

#2 [aggdraw][python] aggdrawを試用してみた

Pillow の Image に、アンチエイリアスをかけた状態で図形描画等ができる、aggdraw なるライブラリがあるらしいので少し試用してみたり。

_aggdraw - PyPI
_pytroll/aggdraw: Python package wrapping AGG2 drawing functionality
_AggDraw - aggdraw 1.3.8 documentation

環境は、Windows10 x64 1903 + Python 2.7.17 + Pillow 6.2.1 + aggdraw 1.3.11。

インストールは、以下でいいのかな。たぶん。
pip install aggdraw

aggdrawで描いてみた事例。 :

_01_aggdraw.py
from PIL import Image
import aggdraw
import math


# aggdraw
im = Image.new('RGBA', (512, 512), (255, 255, 255, 255))
d = aggdraw.Draw(im)
pen = aggdraw.Pen((0, 0, 0, 255), 2.0)  # color, width
cx, cy = 256, 256
for i in range(0, 360, 5):
    x = 240 * math.cos(math.radians(i)) + cx
    y = 240 * math.sin(math.radians(i)) + cy
    d.line((cx, cy, x, y), pen)
d.flush()
im.save("./output_aggdraw.png")

出力結果。

output_aggdraw.png
_output_aggdraw.png

アンチエイリアスがかかっている。

ImageDrawで描いてみた事例。 :

Pillow の ImageDraw を使って描いてみた事例。

_02_imagedraw.py
from PIL import Image, ImageDraw
import math


# ImageDraw
im = Image.new("RGBA", (512, 512), (255, 255, 255, 255))
d = ImageDraw.Draw(im)
cx, cy = 256, 256
for i in range(0, 360, 5):
    x = int(240 * math.cos(math.radians(i)) + cx)
    y = int(240 * math.sin(math.radians(i)) + cy)
    d.line((cx, cy, x, y), fill=(0, 0, 0, 255), width=2)
im.save("./output_imagedraw.png")

output_imagedraw.png
_output_imagedraw.png

アンチエイリアスがかかってないのが分かる。

ImageDrawで描いてみた事例その2。 :

Pillow の ImageDraw を使って描いてみた事例。2倍のサイズで描いてから、1/2に縮小してみる。

_03_imagedraw2.py
from PIL import Image, ImageDraw
import math


# ImageDraw
im = Image.new("RGBA", (1024, 1024), (255, 255, 255, 255))
d = ImageDraw.Draw(im)
cx, cy = (256 * 2), (256 * 2)
for i in range(0, 360, 5):
    x = int((240 * 2) * math.cos(math.radians(i)) + cx)
    y = int((240 * 2) * math.sin(math.radians(i)) + cy)
    d.line((cx, cy, x, y), fill=(0, 0, 0, 255), width=(2 * 2))

im.thumbnail((512, 512), Image.ANTIALIAS)
im.save("./output_imagedraw2.png")

output_imagedraw2.png
_output_imagedraw2.png

若干それっぽくアンチエイリアスがかかったような雰囲気にはなっている。

問題点。 :

aggdraw のライセンスがちょっとよくわからない。一般的なライセンスではないようで。

aggdraw が使っている AGG とやらにバグがあったりもするようで、例えば透明度を指定すると色が妙なことになる時もあるっぽい。

_Brush/Pen transparency weirdness - Issue #16 - pytroll/aggdraw

以上、1 日分です。

過去ログ表示

Prev - 2019/11 - Next
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project