PDF Добавить текст и выровнять - PullRequest
1 голос
/ 22 сентября 2011

Я занимаюсь разработкой веб-приложения, которое отображает файлы PDF и позволяет пользователям заказывать копии документов.Мы хотим добавить текст, такой как «неоплаченный» или «образец», на лету, когда отображается PDF.Я сделал это с помощью itextsharp.Однако изображения страниц легко отделяются от текста водяного знака и извлекаются с помощью различных бесплатных программ.

Как добавить водяной знак на страницы в PDF, но сгладить изображения страниц и водяной знак так, чтобы водяной знак стал частью изображения страницы PDF, предотвращая тем самым удаление водяного знака (если только человекхочет использовать фотошоп)?

Ответы [ 2 ]

2 голосов
/ 22 сентября 2011

На вашем месте я бы пошел по другому пути.Используя iTextSharp (или другую библиотеку), извлеките каждую страницу данного документа в папку.Затем используйте какую-нибудь программу (Ghostscript, Photoshop, возможно, GIMP), которую вы можете пакетировать и конвертировать каждую страницу в изображение.Затем напишите наложенный текст на изображения.Наконец, используйте iTextSharp, чтобы объединить все изображения в каждой папке обратно в PDF.

Я знаю, это звучит как боль, но вам придется делать это только один раз для каждого документа, который я предполагаю.

Если вы не хотите идти по этому пути, позвольте мне рассказать о том, что вам нужно сделать для извлечения изображений.Большая часть кода ниже взята из этого поста .В конце кода я сохраняю изображения на рабочий стол.Поскольку у вас есть необработанные байты, вы также можете легко закачать их в объект System.Drawing.Image и записать их обратно в новый объект PdfWriter, который звучит так, как будто вы с ним знакомы.Ниже представлено полнофункциональное приложение WinForms с таргетингом на iTextSharp 5.1.1.0

Option Explicit On
Option Strict On

Imports iTextSharp.text
Imports iTextSharp.text.pdf
Imports System.IO
Imports System.Runtime.InteropServices

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ''//File to process
        Dim InputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "SampleImage.pdf")

        ''//Bind a reader to our PDF
        Dim R As New PdfReader(InputFile)

        ''//Setup some variable to use below
        Dim bytes() As Byte
        Dim obj As PdfObject
        Dim pd As PdfDictionary
        Dim filter, width, height, bpp As String
        Dim pixelFormat As System.Drawing.Imaging.PixelFormat
        Dim bmp As System.Drawing.Bitmap
        Dim bmd As System.Drawing.Imaging.BitmapData

        ''//Loop through all of the references in the file
        Dim xo = R.XrefSize
        For I = 0 To xo - 1
            ''//Get the object
            obj = R.GetPdfObject(I)
            ''//Make sure we have something and that it is a stream
            If (obj IsNot Nothing) AndAlso obj.IsStream() Then
                ''//Case it to a dictionary object
                pd = DirectCast(obj, PdfDictionary)
                ''//See if it has a subtype property that is set to /IMAGE
                If pd.Contains(PdfName.SUBTYPE) AndAlso pd.Get(PdfName.SUBTYPE).ToString() = PdfName.IMAGE.ToString() Then
                    ''//Grab various properties of the image
                    filter = pd.Get(PdfName.FILTER).ToString()
                    width = pd.Get(PdfName.WIDTH).ToString()
                    height = pd.Get(PdfName.HEIGHT).ToString()
                    bpp = pd.Get(PdfName.BITSPERCOMPONENT).ToString()

                    ''//Grab the raw bytes of the image
                    bytes = PdfReader.GetStreamBytesRaw(DirectCast(obj, PRStream))

                    ''//Images can be encoded in various ways. /DCTDECODE is the simplest because its essentially JPEG and can be treated as such.
                    ''//If your PDFs contain the other types you will need to figure out how to handle those on your own
                    Select Case filter
                        Case PdfName.ASCII85DECODE.ToString()
                            Throw New NotImplementedException("Decoding this filter has not been implemented")
                        Case PdfName.ASCIIHEXDECODE.ToString()
                            Throw New NotImplementedException("Decoding this filter has not been implemented")
                        Case PdfName.FLATEDECODE.ToString()
                            ''//This code from /676026/izvlechenie-izobrazhenii-s-pomoschy-itextsharp#676034
                            bytes = pdf.PdfReader.FlateDecode(bytes, True)
                            Select Case Integer.Parse(bpp)
                                Case 1
                                    pixelFormat = Drawing.Imaging.PixelFormat.Format1bppIndexed
                                Case 24
                                    pixelFormat = Drawing.Imaging.PixelFormat.Format24bppRgb
                                Case Else
                                    Throw New Exception("Unknown pixel format " + bpp)
                            End Select
                            bmp = New System.Drawing.Bitmap(Int32.Parse(width), Int32.Parse(height), pixelFormat)
                            bmd = bmp.LockBits(New System.Drawing.Rectangle(0, 0, Int32.Parse(width), Int32.Parse(height)), System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat)
                            Marshal.Copy(bytes, 0, bmd.Scan0, bytes.Length)
                            bmp.UnlockBits(bmd)
                            Using ms As New MemoryStream
                                bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg)
                                bytes = ms.GetBuffer()
                            End Using
                        Case PdfName.LZWDECODE.ToString()
                            Throw New NotImplementedException("Decoding this filter has not been implemented")
                        Case PdfName.RUNLENGTHDECODE.ToString()
                            Throw New NotImplementedException("Decoding this filter has not been implemented")
                        Case PdfName.DCTDECODE.ToString()
                            ''//Bytes should be raw JPEG so they should not need to be decoded, hopefully
                        Case PdfName.CCITTFAXDECODE.ToString()
                            Throw New NotImplementedException("Decoding this filter has not been implemented")
                        Case PdfName.JBIG2DECODE.ToString()
                            Throw New NotImplementedException("Decoding this filter has not been implemented")
                        Case PdfName.JPXDECODE.ToString()
                            Throw New NotImplementedException("Decoding this filter has not been implemented")
                        Case Else
                            Throw New ApplicationException("Unknown filter found : " & filter)
                    End Select

                    ''//At this points the byte array should contain a valid JPEG byte data, write to disk
                    My.Computer.FileSystem.WriteAllBytes(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), I & ".jpg"), bytes, False)
                End If
            End If

        Next

        Me.Close()
    End Sub
End Class
.
1 голос
/ 22 сентября 2011

Вся страница должна быть представлена ​​в виде изображения.В противном случае у вас есть «текстовые объекты» (отдельные слова / буквы текста) и объект водяного знака (наложенное изображение), которые всегда будут отдельными / отдельными частями страницы.

...