顶部的iText戳图像并不总是有效 [英] iText stamp image on top not always working

查看:73
本文介绍了顶部的iText戳图像并不总是有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用iTextSharp在PDF的每一页上放置图像和一些文本.这对于某些PDF而言是完美的,但对其他PDF而言则不是.奇怪的是,例如在我使用Word 2010的另存为pdf"功能创建的PDF上,它无法正常工作.我使用GetOverContent,应该将所有内容放在最上面.

I am using iTextSharp to place an image and some text on every page of a PDF. This works perfectly for some PDF's but not for others. Strangely enough it does not work for instance on a PDF I created with Word 2010's 'Save as pdf' function. I use GetOverContent, which should everything on top.

使用Acrobat,我可以看到已经添加了我的图层.因此它必须在文字一词下.

With Acrobat I can see that my layer has been added. So it must be under the word text somewhere.

如何为邮票设置z-index?

How can I set a z-index for my stamp?

有没有一种方法(工具)可以清楚地查看PDF中的对象?我发现Acrobat在这方面并没有真正的帮助,但也许我需要培训;-)

And is there a way (tool) to see clearly what objects are in a PDF? I find Acrobat not really helpfull in that regard, but maybe I need training ;-)

无法正常工作的示例PDF 此处. (链接已更新)

Example not working PDF here. (link updated)

在这里加盖代码,PDF来自数据库,并存储在数据库中:

Stamping code here, PDF comes from database and is stored in database:

Protected Sub cbTekening_Callback(source As Object, e As DevExpress.Web.CallbackEventArgs) Handles cbTekening.Callback
    Dim document As New iTextSharp.text.Document()
    Dim intTekID As Integer

    Try

        Dim fieldValues As List(Of Object) = gridTekeningen.GetSelectedFieldValues(New String() {"TekeningID"})

        For Each item As Object In fieldValues
            Using ms As MemoryStream = New MemoryStream()
                intTekID = item

                Dim pdfr = New PdfReader(GetPDFFromDatabase(intTekID).ToArray())

                Dim pdfs As New iTextSharp.text.pdf.PdfStamper(pdfr, ms)

                Dim image__1 As iTextSharp.text.Image = iTextSharp.text.Image.GetInstance(New System.Uri(Session("ORG_Website") & Session("ORG_Tekeninglogo")))
                Dim image__2 As iTextSharp.text.Image = iTextSharp.text.Image.GetInstance(New System.Uri(Session("ORG_Website") & "Images/contactid_" & Session("ContactID") & ".png"))
                Dim rect As Rectangle

                Dim PageCount As Integer = pdfr.NumberOfPages
                Dim content As iTextSharp.text.pdf.PdfContentByte
                For x = 1 To PageCount
                    rect = pdfr.GetPageSize(x)
                    content = pdfs.GetOverContent(x)

                    image__1.SetAbsolutePosition(50.0F, 50.0F)
                    image__1.ScalePercent(30.0F, 30.0F)
                    image__2.SetAbsolutePosition(100.0F, 100.0F)
                    image__2.ScalePercent(30.0F, 30.0F)
                    Content.AddImage(image__1)
                    Content.AddImage(image__2)
                    Dim layer As New PdfLayer("Goedkeurlaag" & x.ToString, pdfs.Writer)
                    'Tell the cb that the next commands should be "bound" to this new layer
                    Content.BeginLayer(layer)
                    Content.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 20)

                    Dim strWatermerkText1 As String = Session("ORG_Tekeningtekst")
                    Dim strWatermerkText2 As String = Format(Now, "dd-MM-yyyy")
                    Dim strWatermerkText3 As String = Session("VolNaam")

                    Content.SetColorFill(BaseColor.RED)
                    Content.BeginText()
                    Content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText3, 60, 160, 0.0F)
                    Content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText2, 60, 185, 0.0F)
                    Content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText1, 60, 210, 0.0F)
                    Content.EndText()

                    '// Close the layer
                    Content.EndLayer()                
                Next

                pdfs.Close()
                StoreToDatabase(ms, intTekID)

            End Using
        Next item

        imgPubliceerTekening.ClientVisible = False
        gridTekeningen.DataBind()

    Catch ex As Exception

    End Try
End Sub

推荐答案

使其可运行

通过删除所有数据库和会话对象访问权限,使您的示例可独立运行.另外,我将其翻译为C#,这对我来说更自然.作为图像,我使用了我们各自的stackoverflow化身,而作为文本,则使用了会话对象键或格式字符串,您的代码可从该字符串中导出字符串值:

Making it runnable

I made your example self-contained and runnable by removing all database and session object access. Additionally I translated it to C# which comes more naturally to me. As images I used our respective stackoverflow avatars and as texts the session object keys or format strings from which your code derives the string values:

void AddStamps(string OrigFile, string ResultFile)
{
    Document document = new Document();

    using (MemoryStream ms = new MemoryStream())
    {
        PdfReader pdfr = new PdfReader(OrigFile);
        PdfStamper pdfs = new PdfStamper(pdfr, ms);

        Image image__1 = Image.GetInstance(new System.Uri("https://www.gravatar.com/avatar/6bc6e4a08a5683b6f4ef8a8eb5117114?s=48&d=identicon&r=PG"));
        Image image__2 = Image.GetInstance(new System.Uri("https://www.gravatar.com/avatar/53d3aae5c986ca57f01016f5e0be82de?s=32&d=identicon&r=PG&f=1"));
        Rectangle rect;

        int PageCount = pdfr.NumberOfPages;
        PdfContentByte content;
        for (int x = 1; x <= PageCount; x++)
        {
            rect = pdfr.GetPageSize(x);
            content = pdfs.GetOverContent(x);

            image__1.SetAbsolutePosition(50.0F, 50.0F);
            image__1.ScalePercent(30.0F, 30.0F);
            image__2.SetAbsolutePosition(100.0F, 100.0F);
            image__2.ScalePercent(30.0F, 30.0F);
            content.AddImage(image__1);
            content.AddImage(image__2);
            PdfLayer layer = new PdfLayer("Goedkeurlaag", pdfs.Writer);
            content.BeginLayer(layer);
            content.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 20);

            String strWatermerkText1 = "ORG_Tekeningtekst";
            String strWatermerkText2 = "dd-MM-yyyy";
            String strWatermerkText3 = "VolNaam";

            content.SetColorFill(BaseColor.RED);
            content.BeginText();
            content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText3, 60, 160, 0.0F);
            content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText2, 60, 185, 0.0F);
            content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText1, 60, 210, 0.0F);
            content.EndText();

            content.EndLayer();
        }

        pdfs.Close();
        File.WriteAllBytes(ResultFile, ms.ToArray());
    }
}

运行

将此方法应用于您的示例文件,结果如下所示:

Running it

Applying this method to your sample file the result looks like this:

即在每个页面上都清晰可见以下图章:

i.e. on each page the following stamp is clearly visible:

由于该戳记在示例文档中清晰可见,并且此处的VB到C#的翻译相当真实,因此问题是由您未提及的某些因素引起的,例如

As the stamp is clearly visible on your sample document and the translation VB to C# here was fairly faithful, the issue is caused by some factor you did not mention, e.g.

  • 发生某些异常(可能是在数据库访问期间或由于数据库或会话返回的某些null值)而被您

Catch ex As Exception

End Try

空捕获块.

您的图像是完全透明的,您的文本为空.

your images are completely transparent and your text is empty.

因此它必须在文字一词下.

So it must be under the word text somewhere.

如果将内容添加到pdfs.GetOverContent(x),则将其添加到该页面的现有内容之后,并且由于PDF不知道z轴,因此以后绘制的任何内容都覆盖了先前绘制的内容.您的新内容只能由

If you add content to pdfs.GetOverContent(x), it is added after the existing content of that page, and as PDF does not know a z axis, any content drawn later covers content drawn earlier. Your new content can only be covered by

  • 以后添加了新内容,或者
  • 注释内容,因为按规范的所有注释都在所有常规内容之上.

(或者,当然可以在屏幕外……)

(Or, of course, it can be off-screen...)

与此同时,OP提供了一个不同的示例文档,并且将上面的代码应用于该文档确实不会产生可见的图章.

The OP meanwhile has supplied a different sample document, and applying the code above to it indeed does not result in visible stamps.

但是原因已经在上面暗示了:

或者当然可以在屏幕外...

OP的代码隐式假定坐标系原点位于页面的左下方.虽然通常是这种情况,但不一定如此!

The OP's code implicitly assumes that the coordinate system origin is in the lower left of the page. While this is often the case, it does not have to be so!

OP的代码已获取页面的媒体框:

The OP's code already fetches the media box of the page:

rect = pdfr.GetPageSize(x)

检查此介质盒中的文档,发现其左下角为(0,-836.64001),右上角为(1207.68005,0).因此,原点位于左上角,OP使用的所有坐标都位于可见页面的上方.

Inspecting this media box for the document at hand, one sees that its lower left corner is (0, -836.64001) and its top right corner is (1207.68005, 0). Thus, the origin is in the top left corner and all the coordinates the OP used are above the visible page.

如果将以下C#代码中的相应行替换为:

If one replaces the corresponding lines in the C# code above by:

image__1.SetAbsolutePosition(rect.Left + 50.0F, rect.Bottom + 50.0F);
...
image__2.SetAbsolutePosition(rect.Left + 100.0F, rect.Bottom + 100.0F);
...
content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText3, rect.Left + 60, rect.Bottom + 160, 0.0F);
content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText2, rect.Left + 60, rect.Bottom + 185, 0.0F);
content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText1, rect.Left + 60, rect.Bottom + 210, 0.0F);

再一次获得所需的印章:

one again gets the desired stamps:

这篇关于顶部的iText戳图像并不总是有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆