web-dev-qa-db-ja.com

c#itextsharp PDF各ページに透かしを入れて作成

Itextsharp(JavaのitextのC#ポート)を使用して、各ページに透かしの入った多数のPDFドキュメントをプログラムで作成しようとしています。

PdfStamperを使用してドキュメントを作成した後、これを行うことができます。ただし、これはドキュメントを開いて開き直してから、各ページに透かしの入った新しいドキュメントを作成する必要があるようです。

ドキュメント作成中にこれを行う方法はありますか?

29
tim harrison

それを掘り下げた後、最良の方法は、作成された各ページに透かしを追加することであるとわかりました。これを行うには、新しいクラスを作成し、次のようにIPdfPageEventインターフェイスを実装しました。

    class PdfWriterEvents : IPdfPageEvent
    {
        string watermarkText = string.Empty;

        public PdfWriterEvents(string watermark) 
        {
            watermarkText = watermark;
        }

        public void OnOpenDocument(PdfWriter writer, Document document) { }
        public void OnCloseDocument(PdfWriter writer, Document document) { }
        public void OnStartPage(PdfWriter writer, Document document) {
            float fontSize = 80;
            float xPosition = 300;
            float yPosition = 400;
            float angle = 45;
            try
            {
                PdfContentByte under = writer.DirectContentUnder;
                BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
                under.BeginText();
                under.SetColorFill(BaseColor.LIGHT_GRAY);
                under.SetFontAndSize(baseFont, fontSize);
                under.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, xPosition, yPosition, angle);
                under.EndText();
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
            }
        }
        public void OnEndPage(PdfWriter writer, Document document) { }
        public void OnParagraph(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title) { }
        public void OnChapterEnd(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title) { }
        public void OnSectionEnd(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) { }

    }
}

このオブジェクトは、次のようにイベントを処理するために登録されます。

PdfWriter docWriter = PdfWriter.GetInstance(document, new FileStream(outputLocation, FileMode.Create));
PdfWriterEvents writerEvent = new PdfWriterEvents(watermark);
docWriter.PageEvent = writerEvent;
41
tim harrison

ティムのソリューションは非常に素晴らしいように見えますが、私は次のコードを使用して同じことを実行できました(おそらくそうです)

    private byte[] AddWatermark(byte[] bytes, BaseFont bf)
    {
        using(var ms = new MemoryStream(10 * 1024))
        {
            using(var reader = new PdfReader(bytes))
            using(var stamper = new PdfStamper(reader, ms))
            {
                int times = reader.NumberOfPages;
                for (int i = 1; i <= times; i++)
                {
                    var dc = stamper.GetOverContent(i);
                    PdfHelper.AddWaterMark(dc, AppName, bf, 48, 35, new BaseColor(70, 70, 255), reader.GetPageSizeWithRotation(i));
                }
                stamper.Close();
            }
            return ms.ToArray();
        }
    }

    public static void AddWaterMark(PdfContentByte dc, string text, BaseFont font, float fontSize, float angle, BaseColor color, Rectangle realPageSize, Rectangle rect = null)
    {
        var gstate = new PdfGState { FillOpacity = 0.1f, StrokeOpacity = 0.3f };
        dc.SaveState();
        dc.SetGState(gstate);
        dc.SetColorFill(color);
        dc.BeginText();
        dc.SetFontAndSize(font, fontSize);
        var ps = rect ?? realPageSize; /*dc.PdfDocument.PageSize is not always correct*/
        var x = (ps.Right + ps.Left) / 2;
        var y = (ps.Bottom + ps.Top) / 2;
        dc.ShowTextAligned(Element.ALIGN_CENTER, text, x, y, angle);
        dc.EndText();
        dc.RestoreState();
    }

これにより、バイト配列として提供されるPDFドキュメントのすべてのページに透かしが追加されます。

(PDFの作成中に行う必要はありません。)

横向きと縦向きの両方で機能しているようで、おそらく向きが混在しているドキュメントでも機能します。

乾杯! :)

17
NoOne
string WatermarkLocation = "D:\\Images\\superseded.png";

    Document document = new Document();
    PdfReader pdfReader = new PdfReader(FileLocation);
    PdfStamper stamp = new PdfStamper(pdfReader, new FileStream(FileLocation.Replace(".pdf", "[temp][file].pdf"), FileMode.Create));

    iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(WatermarkLocation);
    img.SetAbsolutePosition(125, 300); // set the position in the document where you want the watermark to appear (0,0 = bottom left corner of the page)



    PdfContentByte waterMark;
    for (int page = 1; page <= pdfReader.NumberOfPages; page++)
    {
        waterMark = stamp.GetOverContent(page);
        waterMark.AddImage(img);
    }
    stamp.FormFlattening = true;
    stamp.Close();

    // now delete the original file and rename the temp file to the original file
    File.Delete(FileLocation);
    File.Move(FileLocation.Replace(".pdf", "[temp][file].pdf"), FileLocation);
6
kirk

最初のソリューションを使用しました。最初はうまく動作しませんでした。すべてのパブリックボイドの下に、継承メンバーを非表示にするつもりであるという緑色のアンダーラインが表示されます。

基本的に、PagePageEventHelperを既に追加していることに気付き、基本的にOnStartPageのコードを切り取りました。また!何らかの理由で、私は自分のパブリックをすべて無効にしなければなりませんでした。

  public override void OnStartPage(PdfWriter writer, Document document)
        {
            if (condition)
            {
                string watermarkText = "-whatever you want your watermark to say-";
                float fontSize = 80;
                float xPosition = 300;
                float yPosition = 400;
                float angle = 45;
                try
                {
                    PdfContentByte under = writer.DirectContentUnder;
                    BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
                    under.BeginText();
                    under.SetColorFill(iTextSharp.text.pdf.CMYKColor.LIGHT_GRAY);
                    under.SetFontAndSize(baseFont, fontSize);
                    under.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, xPosition, yPosition, angle);
                    under.EndText();
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine(ex.Message);
                }
            }
        }
4
Connor Williams

作成後、各ページに透かしを配置することはできませんか?

3
plinth

はい、ウォーターマーククラスはもうないようです-奇妙です。しかし、iTextSharp 5.3に変換する過程で、新しいドキュメントに透かしを追加する簡単な方法を見つけました。

MemoryStream mem = new MemoryStream();

Document document = new Document();

PdfWriter writer = PdfWriter.GetInstance(document, mem);

PdfContentByte cb = writer.DirectContent;

document.Open();

document.NewPage();

Image watermark = Image.GetInstance(WATERMARK_URI);

watermark.SetAbsolutePosition(80, 200);

document.Add(watermark);

BaseFont bf = BaseFont.CreateFont(FONT, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);

cb.BeginText();

...

cb.EndText();

document.Close();
2
Curt

ITextSharpでは、プログラムで透かしを追加できるはずです。

Watermark watermark = new Watermark(Image.getInstance("watermark.jpg"), 200, 420);
document.Add(watermark);
1
James