おたくのテクノ

ピアノ男(notピアノ弾き)のブログ

犬を回せる(pythonでsvgにラスタ画像を埋め込む方法)

svgにラスタ画像を埋め込みたい!

 SVGとはベクターイメージ用の形式ですが、時にpngとかのラスターイメージを埋め込みたい場合もあると思います。実際埋め込むことができます。イラレをお使いの奥様方でしたら、ラスターイメージが含まれてようがsvgで書き出しできるっちゅうことはご存知やと思います。

今回は、pythonsvgにラスタ画像を埋め込む方法を書いときます。備忘録ですね。

 

svgwriteは便利や!

環境を教えときます。python3.x.xです。あと、SVGデータを扱うため、「svgwrite」というパッケジを使います。リンク先はドキュメントなので、よく読んどけばいいです。入れ方?しらん、どうせpip install svgwriteやろ!?

全体像

まず、普通にコード丸ごと載せときますわ!いうてもめっちゃ短い!

import base64
import svgwrite
import os

with open("inu.png", "rb") as f:
	b64dog = base64.b64encode(f.read())

dwg = svgwrite.Drawing(filename='inu.svg')
dog = dwg.add(dwg.image('data:image/png;base64,' + b64dog.decode("ascii"), insert=(0,0), size=(300, 250)))
dwg.save()

svgwriteは当然使うので当然importします。osは画像ファイル開くんで使います。base64はあとで使います。そしたら、それ以降を説明していきますね。

 

svgwriteを使う部分

SVGそのものについては、defghi1977さんのまとめが超まとまっててありがたいので、そちらで学んどきましょう。ここでは、svgwriteでどうsvgを作るかという話をします。まず、

dwg = svgwrite.Drawing(filename='inu.svg')

ってやってsvg要素を作ります。filenameのとこに出力ファイル名をいれときます。カンマ入れて後にsize=(200, 300)ってやることでビューポートをwidth=200, height=300にできたりとかもします。ドキュメントに書いてます。

では、作ったsvg要素に画像を入れます。画像ですが、とりあえず書いてるコードと同じ階層にinu.pngを用意しました。

f:id:oldskoolrave:20171020231909p:plain

inu.pngです。ペットアンブレラ付きです。さて、svg要素にどうやってinu.pngを追加しますか。

dog = dwg.add(dwg.image('inu.png', insert=(0,0), size=(300, 250)))

俺は雰囲気でpythonをやっているから正確な説明ができなくてアレですが、さっきdwgという大枠のSVG要素を作ったと思います。その中に丸とか三角とか四角とか画像とかをdwg.add()で追加していくわけですね。

その中のdwg.imageはその名の通りImageオブジェクトを作ります。'inu.png'は犬の画像で、つまり入れたい画像のパスを入力するわけですね。insert=(x,y)は座標(入れる画像の左上がくる場所)、sizeはそのまんまサイズです。sizeについては少しハマりポイントがあるんですが、ここでは言及しません。

あとは、dwg.save()で.svgが生成されます。

ところで、'inu.png'とパスを指定するのには問題があります。何故なら、inu.pngが置いてる場所が変わっちゃうと、当然inu.pngが見つからんのでSVG側ではワンちゃんが表示されんくなります。

.svgと同じ階層にinu.pngを置いておけばいいのですが、それはあまりにも面倒です。どうしたらええねん?

ありがとうbase64

幸いにも、バイナリデータをASCII文字列にエンコードできるbase64っちゅうやつがいます。実際、イラレとかでもラスタ画像を埋め込みにしてSVGを吐き出した場合、ラスタ画像はbase64エンコードされた状態でSVGに埋め込まれています。そしたら、その通りやりましょう。

with open("inu.png", "rb") as f:
	b64dog = base64.b64encode(f.read())

with構文を使うと、close()とかいうお片づけを勝手にやってくれるので便利でいいですね。読み込んだ画像を、b64encodeでエンコードするだけです。

あとは、

dog = dwg.add(dwg.image('data:image/png;base64,'+b64dog.decode("ascii"), insert=(0,0), size=(300, 250)))

といった具合に、パスをbase64スタイルにします。data:image/png;base64ちゅうのは、HTMLとかでbase64化された画像を埋め込む時のお作法みたいなんですね。jpegを埋め込む場合は、image/pngのとこをimage/jpegにしてください。

その後ろにbase64化データの文字列を足すのですが、少し注意しておきたいのが、b64encodeされて出てくるのはbytes型なんで、そのままでは死にます。.decode("ascii")するとstr型になるのでそうしときましょう。asciiじゃなくてもいいと思う、知らん

 

これで、めでたくsvgに犬pngが埋め込まれました。

ただ、あんまファイルサイズがデカいpngとかは埋め込まんのが吉かもしれませんね。知らん。

犬をsvgに埋め込めると、嬉しい点ですが、例えばsvgはアニメーションができますので、犬を回せます。

(環境によっては回ってないかもしれません、回ってなかったらスマソ)

犬が回って何が嬉しいのかようわからんが、犬が回ってよかったね!