C#でPDFにQRコードやバーコードを描画する

# はじめに

PDFsharpとZXing.Netを組み合わせて、PDFファイルにQRコードやバーコードを描画する方法を紹介します。

# 準備

プロジェクトに以下のnugetパッケージを導入します。

- ZXing.Net
    - 1D/2Dコードをエンコード・デコードするためのライブラリ
    - Apache-2.0 license

https://www.nuget.org/packages/ZXing.Net

- PDFsharp
    - PDFを作成・編集するためのライブラリ
    - MIT license

※Window Formsで使用する場合

https://www.nuget.org/packages/PDFsharp-GDI

※WPFで使用する場合

https://www.nuget.org/packages/PDFsharp-WPF

# QRコード・バーコード描画用拡張メソッド

```csharp
using PdfSharp.Drawing;
using ZXing;

public static class PdfSharpExtensions
{
    /// <summary>
    /// QRコードを描画
    /// </summary>
    public static void DrawQrCode(this XGraphics gfx, string code, XBrush color, double x, double y, double width, double height)
    {
        //QRコード設定
        var qrCodeWriter = new BarcodeWriterGeneric()
        {
            Format = BarcodeFormat.QR_CODE,
            Options = { Margin = 0 },
        };

        //描画
        gfx.DrawZXingBase(qrCodeWriter, code, color, x, y, width, height);
    }

    /// <summary>
    /// QRコードを描画
    /// </summary>
    public static void DrawQrCode(this XGraphics gfx, string code, XBrush color, XRect rect)
    {
        gfx.DrawQrCode(code, color, rect.X, rect.Y, rect.Width, rect.Height);
    }

    /// <summary>
    /// バーコード(CODE128)を描画
    /// </summary>
    public static void DrawCode128(this XGraphics gfx, string code, XBrush color, double x, double y, double width, double height)
    {
        //バーコード設定
        var barCodeWriter = new BarcodeWriterGeneric()
        {
            Format = BarcodeFormat.CODE_128,
            Options = { Margin = 0, Height = 1 },
        };

        //描画
        gfx.DrawZXingBase(barCodeWriter, code, color, x, y, width, height);
    }

    /// <summary>
    /// バーコード(CODE128)を描画
    /// </summary>
    public static void DrawCode128(this XGraphics gfx, string code, XBrush color, XRect rect)
    {
        gfx.DrawCode128(code, color, rect.X, rect.Y, rect.Width, rect.Height);
    }

    /// <summary>
    /// 共通メソッド
    /// </summary>
    private static void DrawZXingBase(this XGraphics gfx, BarcodeWriterGeneric barCodeWriter, string code, XBrush color, double x, double y, double width, double height)
    {
        // 引数チェック
        if (string.IsNullOrEmpty(code)) throw new ArgumentNullException("code");

        // 1D/2Dコード生成(BitMatrix)
        var matBarCode = barCodeWriter.Encode(code);

        // ピクセルサイズ計算
        var pixelSizeX = width / (double)matBarCode.Width;
        var pixelSizeY = height / (double)matBarCode.Height;

        // ピクセル描画
        for (int px = 0; px < matBarCode.Width; px++)
        {
            for (int py = 0; py < matBarCode.Height; py++)
            {
                if (matBarCode[px, py])
                {
                    var pixelLocation = new XPoint(x + (px * pixelSizeX), y + (py * pixelSizeY));
                    var pixelRect = new XRect(pixelLocation, new XSize(pixelSizeX, pixelSizeY));
                    gfx.DrawRectangle(color, pixelRect);
                }
            }
        }
    }
}
```

# 使用例

```csharp
public void CreatePdf()
{
    var doc = new PdfDocument();
    var page = doc.AddPage();
    page.Orientation = PageOrientation.Landscape;
    page.Size = PageSize.A5;
    using (var gfx = XGraphics.FromPdfPage(page))
    {
        // QRコード描画
        var loc = new XPoint(XUnit.FromCentimeter(1).Point, XUnit.FromCentimeter(1).Point);
        var size = new XSize(XUnit.FromCentimeter(2).Point, XUnit.FromCentimeter(2).Point);
        var rect = new XRect(loc, size);
        gfx.DrawQrCode("Hello, World!", XBrushes.Black, rect);

        //バーコード(CODE128)描画
        loc = new XPoint(XUnit.FromCentimeter(1).Point, XUnit.FromCentimeter(5).Point);
        size = new XSize(XUnit.FromCentimeter(3).Point, XUnit.FromCentimeter(1).Point);
        rect = new XRect(loc, size);
        gfx.DrawCode128("Hello, World!", XBrushes.Black, rect);
    }
    doc.Save("test.pdf");
}
```

# 出力例

![test.pdf](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916644/98a98c09-b026-1d1d-c4fb-eae447797f13.jpeg)

# 参考文献

https://forum.pdfsharp.net/viewtopic.php?f=2&t=4493