田舎人の書斎作ったり、試したり、書き留めたり。

iTextSharpでPDFに「印刷したときだけ表示される」透かしを入れる(C#)

公開

この記事は2022年に書いたものです。ソフトウェアのバージョンや配布状況など、いまとは異なる場合があります。

試した環境

言語
C#(.NET Framework)
ライブラリ
iTextSharp(NuGet)

PDFに、印刷したときだけ透かしが入るようにしたいと思ったところ、情報が少なく思いのほか苦戦しました。備忘録を兼ねて、方法を残しておきます。同じことで悩んでいる方の参考になれば幸いです。

準備

言語はC#で、ライブラリにはiTextSharpを使います。iTextSharpはNuGetから入手します。NuGetパッケージの管理画面を開き、検索欄に「itext」と入力すると「iTextSharp」が出てくるので、これをインストールします。なお、現在の最新版はiText 7です。

NuGetパッケージマネージャーでitextを検索したところ

iTextSharpをインストールするところ

コード

インストールできたら、次のコードで印刷時だけ表示される透かしを入れられます。

ポイントはレイヤー(PdfLayer)の設定です。Viewをtrueにすると、画面上でも常に透かしが表示されます。逆に、印刷時だけ透かしを消すこともできるようですが、私の用途では不要だったので試していません。

引数には、元のPDFのパス、出力するPDFのパス、透かしの文字列を渡しています。使いやすいように調整してください。

using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

public static void SetWatermark(string inputFilePath, string outputFilePath, string watermarkText)
{
    PdfReader pdfReader = null;
    PdfStamper pdfStamper = null;
    try
    {
        pdfReader = new PdfReader(inputFilePath);
        pdfStamper = new PdfStamper(pdfReader, new FileStream(outputFilePath, FileMode.Create));
        int total = pdfReader.NumberOfPages + 1;
        Rectangle pageSize = pdfReader.GetPageSize(1);
        float width = pageSize.Width;
        float height = pageSize.Height;

        // フォントの準備(選ぶフォントによっては日本語が表示できなかった)
        string fontFolder = Environment.SystemDirectory.Replace("system32", "fonts");
        string fontName = fontFolder + "\\msgothic.ttc,0";
        BaseFont baseFont = BaseFont.CreateFont(fontName, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        float fontSize = 80.0f;

        // レイヤーの設定:画面では見えず、印刷時だけ表示させる
        PdfLayer layer = new PdfLayer("watermark", pdfStamper.Writer);
        layer.OnPanel = true;
        layer.On = true;
        layer.SetPrint("watermark", true); // false にするとこのレイヤーは印刷されない
        layer.View = false;                // true にすると画面でも透かしが表示される
        pdfStamper.Writer.AddToBody(layer.PdfObject, layer.Ref);

        PdfGState gs = new PdfGState();
        gs.FillOpacity = 0.4f; // 透かしの不透明度

        for (int i = 1; i < total; i++)
        {
            PdfContentByte content = pdfStamper.GetOverContent(i);
            content.BeginLayer(layer);
            content.SetGState(gs);
            content.BeginText();
            content.SetColorFill(BaseColor.BLACK);
            content.SetFontAndSize(baseFont, fontSize);
            content.SetTextMatrix(0, 0);
            content.ShowTextAligned(Element.ALIGN_CENTER, watermarkText, width / 2, height / 2, 45);
            content.EndText();
            content.EndLayer();
        }
    }
    finally
    {
        pdfStamper?.Close();
        pdfReader?.Close();
    }
}

これで、Adobeの有料ライセンスを使わなくても、PDFに透かしを入れられます。

日本語の情報がほとんど見つからず、Stack Overflowで英語の質問を読みあさって、ようやくこの方法にたどり着きました。