1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

pythonでQRコードをdxfファイルとして描画、保存する

Last updated at Posted at 2022-09-24

ezdxfnayuki/QR-Code-generatorを使用してQRコードをdxfファイルとして描画し、保存することを目的とする。

サンプルコード→https://github.com/kmgk/QRcode-as-dxf

実行環境

  • OS: Windows 10
  • Python: v3.10.7

使用するライブラリ

  • ezdxf
    • 名前の通りdxfファイルの作成や編集を行う
    • pip install ezdxf
  • nayuki/QR-Code-generator
    • 文字列からQRコードを作成することが出来る
    • PyPIでqrcodegenとして公開されているが、今回はローカルにダウンロードして使用
    • 以下このライブラリはqrcodegenとして表記
  • matplotlib
    • 必須ではないが作成したdxfを保存せず確認することが可能
    • pip install matplotlib

文字列からQRコードを作成する

qrcodegenのQrCode.encode_textを使用することで文字列からQRコードを作成することができる。第二引数にはエラー訂正レベルを指定する必要があり、Low(7%)、Medium(15%)、Quartile(25%)、High(30%)の四種類の中から選ぶことができる。レベルを上げればQRコードが汚れていても読み取れる可能性が上がるが、QRコードのサイズが大きくなり読み取り時間も多くかかる。

from qrcodegen import *
qr = QrCode.encode_text("こんにちは", QrCode.Ecc.LOW)

get_size()でQRコードのサイズ(縦横のドット数)、get_module(x,y)で(x,y)におけるQRコードの色が黒か白かをboolで取得できる(Trueは黒)。

qr.get_size() # 21
qr.get_module(1, 1) # False

これらを組み合わせて、QRコードの情報を1つずつ取得していく。以下はQRコードの左上からドットの色を出力していくサンプル。あとはdxfにこれらの情報をオブジェクトとして書き出せばよい。

# create QR Code
qr = QrCode.encode_text("QR Code as DXF", QrCode.Ecc.MEDIUM)

for y in range(qr.get_size()):
    for x in range(qr.get_size()):
        print(qr.get_module(x, y))

QRコードをポリライン、ハッチで表現する

様々なやり方があるが、本稿ではQRコードを1ドットずつポリラインとハッチを組み合わせて描画していく。ドットはポリラインで閉じた正方形を描画し、その中をハッチで埋めることでドットを表現する。以下は一つのドットをポリラインとハッチで作成するサンプル。

import ezdxf
# dxfドキュメントを作成
doc = ezdxf.new("R2018", setup=True)
msp = doc.modelspace()
# ポリラインの作成
dot_polyline = msp.add_lwpolyline([(0,0), (1,0), (1,1), (0,1), (0,0)], close=True)
# ハッチの定義
dot_hatch = msp.add_hatch()
# ポリラインに合わせてハッチを作成
dot_hatch.paths.add_polyline_path(
    dot_polyline.get_points(format="xyb"), is_closed=True
)

image.png

あとは生成したQRコードの情報をdxfに1つずつ描画していくだけ。dxfのアドオンとmatplotlibを使用してdxfを保存せずに確認することができる。注意点として、QRコードをforで1つずつ読み取るときは左上から読み取るが、インデックスは(x,y)=(0,0)からスタートするためmsp.add_lwpolyline([(x,y),(x+1,y),(x+1,y+1),(x,y+1),(x,y)], close=True)で作成するとQRコードが上下逆になる。dxfファイルとして保存するにはdoc.saveas("qrcode.dxf")を使用する。

from qrcodegen import *
import ezdxf
import matplotlib.pyplot as plt
from ezdxf.addons.drawing import RenderContext, Frontend
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend


def main():
    # create dxf document
    doc = ezdxf.new("R2018", setup=True)
    msp = doc.modelspace()

    # create QR Code
    qr = QrCode.encode_text("QR Code as DXF", QrCode.Ecc.MEDIUM)

    for y in range(qr.get_size()):
        for x in range(qr.get_size()):
            if qr.get_module(x, y):
                # create polyline
                dot_polyline = msp.add_lwpolyline(
                    [
                        (x, qr.get_size() - y - 1),
                        (x + 1, qr.get_size() - y - 1),
                        (x + 1, qr.get_size() - y),
                        (x, qr.get_size() - y),
                        (x, qr.get_size() - y - 1),
                    ],
                    close=True,
                )
                # define hatch
                dot_hatch = msp.add_hatch()
                # create hatch from polyline
                dot_hatch.paths.add_polyline_path(
                    dot_polyline.get_points(format="xyb"), is_closed=True
                )

    # save as dxf
    doc.saveas("qrcode.dxf")

    # show dxf as picture
    fig = plt.figure()
    ax = fig.add_axes([0, 0, 1, 1])
    ctx = RenderContext(doc)
    out = MatplotlibBackend(ax)
    Frontend(ctx, out).draw_layout(msp, finalize=True)
    plt.show()


if __name__ == "__main__":
    main()

image.png

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?