【问题标题】:How to convert PDF pages to PNG using Ghostscript Wrapper VB.NET?如何使用 Ghostscript Wrapper VB.NET 将 PDF 页面转换为 PNG?
【发布时间】:2016-02-17 13:03:22
【问题描述】:

我正在尝试使用以下解决方案将数字签名的 PDF 转换为 PNG:Simple VB.Net Wrapper for Ghostscript Dll。它对我也不起作用。我正在使用 Ghostscript 9.18 32 位。

首先,源代码进入这部分的InOutErrCallBack方法:

gsapi_init_with_args(InstanceHndl, NumArgs + 1, Args)

当这种情况发生时,执行冻结。发生这种情况后,下一次调用 RunGS 方法在这部分返回 false:

If gsapi_new_instance(InstanceHndl, IntPtr.Zero) <> 0 Then
    Return False
    Exit Function
End If

gsapi_new_instance 的返回值为-100: Ghostscript API - Return codes

gswin32.dll 位于 C:\Windows\System32 和 BIN 项目文件夹中。

我的参数序列:

Dim outputImgPath As String
outputImgPath = "C:\Download\DocumentosV2\Protocolo\Pronunciamento\" + Guid.NewGuid.ToString("N") + ".png"

Dim args() As String = { _
    "-dNOPAUSE", _
    "-dBATCH", _
    "-dSAFER", _
    "-dQUIET", _
    "-sDEVICE=png16m", _
    String.Format("-r{0}", resolucao), _
    "-dTextAlphaBits=2", _
    "-dGraphicsAlphaBits=2", _
    String.Format("-dFirstPage={0}", pageNumber), _
    String.Format("-dLastPage={0}", pageNumber), _
    String.Format("-sOutputFile={0}", outputImgPath), _
    "-f", _
    pdfPath _
    }

更新

@kens 建议我提出一些论点。因此,我将其删除以进行测试。

我的完整代码:

Imports PdfSharp
Imports System
Imports System.Collections
Imports System.IO
Imports System.Text
Imports System.Runtime.InteropServices
Imports System.Drawing
Imports PdfSharp.Pdf
Imports PdfSharp.Pdf.IO
Imports PdfSharp.Drawing

'''
''' http://www.geekscrapbook.com/2009/11/16/c-method-to-add-an-image-to-a-pdf/
'''
Public Class PDF2Image2PDF
    Inherits Simp.Net.Infra.SimpComponent

    Private SyncRoot As New Object

    'Converte cada página do PDF em imagem
    Public Function Pdf2Png(ByVal pdfPath As String, ByVal resolucao As Int32) As Image()

        Dim outputImgPath As String
        Dim pageCount As Integer

        Dim objPdfReader As New iTextSharp.text.pdf.PdfReader(pdfPath)
        pageCount = objPdfReader.NumberOfPages()

        Dim objImages As New ArrayList

        For pageNumber As Int32 = 1 To pageCount
            outputImgPath = "C:/Download/DocumentosV2/Protocolo/Pronunciamento/" + Guid.NewGuid.ToString("N") + ".png"
            Dim objFileStream As FileStream
            Dim objMemoryStream As MemoryStream

            'Dim args() As String = { _
            '    "-dNOPAUSE", _
            '    "-dBATCH", _
            '    "-dSAFER", _
            '    "-dQUIET", _
            '    "-sDEVICE=png16m", _
            '    String.Format("-r{0}", resolucao), _
            '    "-dTextAlphaBits=2", _
            '    "-dGraphicsAlphaBits=2", _
            '    String.Format("-dFirstPage={0}", pageNumber), _
            '    String.Format("-dLastPage={0}", pageNumber), _
            '    String.Format("-sOutputFile={0}", outputImgPath), _
            '    "-f", _
            '    pdfPath _
            '    }

            Dim args() As String = { _
                "-dNOPAUSE", _
                "-dBATCH", _
                "-sDEVICE=png16m", _
                String.Format("-dFirstPage={0}", pageNumber), _
                String.Format("-dLastPage={0}", pageNumber), _
                String.Format("-sOutputFile={0}", outputImgPath), _
                Replace(pdfPath, "\", "/") _
                }

            If GhostscriptDllLib.RunGS(args) Then
                If File.Exists(outputImgPath) Then
                    objFileStream = New FileStream(outputImgPath, FileMode.Open)
                    Dim length As Int32 = objFileStream.Length
                    Dim bytes(length) As Byte
                    objFileStream.Read(bytes, 0, length)
                    objFileStream.Close()

                    objMemoryStream = New MemoryStream(bytes, False)

                    objImages.Add(Image.FromStream(objMemoryStream))
                Else
                    Throw New InvalidOperationException("Erro ao converter páginas do PDF em imagens PNG")
                End If
            Else
                Throw New InvalidOperationException("Erro ao converter páginas do PDF em imagens PNG")
            End If

        Next

        Return CType(objImages.ToArray(GetType(Image)), Image())

    End Function

    'Converte cada imagem do vetor em uma página do PDF
    Public Function Images2PDF(ByVal imagens() As Image) As PdfDocument
        Dim pdf As PdfDocument
        Dim gfx As XGraphics
        Dim ximg As XImage

        pdf = New PdfDocument

        For Each img As Image In imagens
            pdf.AddPage(New PdfPage)
            gfx = XGraphics.FromPdfPage(pdf.Pages.Item(0))
            ximg = XImage.FromGdiPlusImage(img)

            gfx.DrawImage(ximg, 0, 0)

            ximg.Dispose()
            gfx.Dispose()

        Next

        Return pdf
    End Function

End Class

调用者代码:

Public Sub DownloadPeticionamento(ByVal sender As System.Object, ByVal e As System.web.UI.ImageClickEventArgs)
    Dim imagem As ImageButton = DirectCast(sender, ImageButton)
    Dim pdfPath As String = imagem.DescriptionUrl

    Dim objPdfPeticionamento As New Simp.Net.Negocio.PDF2Image2PDF

    Dim objImages() As Image
    Dim objPdfDoc As PdfDocument
    objImages = objPdfPeticionamento.Pdf2Png(pdfPath, 600)

    objPdfDoc = objPdfPeticionamento.Images2PDF(objImages)
    objPdfDoc.Save(Me.Page.Response.OutputStream, True)

End Sub

我在命令行中对此进行测试:

gswin32c -dNOPAUSE -dBATCH -sDEVICE=png16m -sOutputFile=C:/Download/DocumentosV2/Protocolo/Pronunciamento/fb21872746b64f8fb31b3764b5444e2e.png C:/Upload/DocumentosV2/Protocolo/Pronunciamento/3_0_404702190_2016_10081288_230_0_f1f09b4b38ac49a8a3e5576f6041eea3.pdf

通过命令行,转换 pdf。命令行输出:

C:\Documents and Settings\leandro.ferreira>gswin32c -dNOPAUSE -dBATCH -sDEVICE=png16m -dFirstPage=1 -dLastPage=1 -sOutputFile=C:/Download/DocumentosV2/Protocolo/Pronunciamento/fb21872746b64f8fb31b3764b5444e2e.png C:/Upload/DocumentosV2/Protocolo/Pronunciamento/3_0_404702190_2016_10081288_230_0_f1f09b4b38ac49a8a3e5576f6041eea3.pdf
GPL Ghostscript 9.16 (2015-03-30)
Copyright (C) 2015 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Processing pages 1 through 1.
Page 1
Can't find (or can't open) font file %rom%Resource/Font/Arial-BoldMT.
Can't find (or can't open) font file Arial-BoldMT.
Can't find (or can't open) font file %rom%Resource/Font/Arial-BoldMT.
Can't find (or can't open) font file Arial-BoldMT.
Querying operating system for font files...
Didn't find this font on the system!
Substituting font Helvetica-Bold for Arial-BoldMT.
Loading NimbusSan-Bol font from %rom%Resource/Font/NimbusSan-Bol... 4047240 2487522 8937716 7603550 3 done.
Can't find (or can't open) font file %rom%Resource/Font/ArialMT.
Can't find (or can't open) font file ArialMT.
Can't find (or can't open) font file %rom%Resource/Font/ArialMT.
Can't find (or can't open) font file ArialMT.
Didn't find this font on the system!
Substituting font Helvetica for ArialMT.
Loading NimbusSan-Reg font from %rom%Resource/Font/NimbusSan-Reg... 4080352 2580805 9014744 7662839 3 done.

C:\Documents and Settings\leandro.ferreira>

【问题讨论】:

    标签: asp.net vb.net pdf dllimport ghostscript


    【解决方案1】:

    -100 只是“致命错误”,即发生了非常糟糕的事情。更多信息通常会打印到 stdout 或 stderr,当然设置 -dQUIET 会抑制大部分信息......

    由于您返回 -100,几乎可以肯定您对 Ghostscript 的参数在某些方面不正确。

    在调试问题时,您应该做的第一件事就是尝试简化问题,因此请移除您毫无疑问需要的所有开关。

    所以首先要做的是删除 -dQUIET,捕获所有 stdout/stderr 输出并告诉我们它说了什么。

    除此之外,请注意以下几点:

    您不需要“-f”,因为该开关的唯一目的是终止您未使用的 -c。

    您没有给出“resolucao”、“pageNumber”或“pdfPath”的值,因此无法知道这些值是否有效(或合理)。您为 outputImgPath 指定的路径很长,并且包含反斜杠字符。我建议改用正斜杠“/”,因为反斜杠用于开始转义,并且可能会产生您可能意想不到的结果。

    您也使用过 -dSAFER,您了解指定 this 的含义吗?如果没有,请将其删除并重试。

    创建字符串 'args' 后将其打印出来。至少这会给你一些你可以从命令行尝试的东西,并且可能意味着其他人有一些机会重现你的问题。

    最后;请注意,Ghostscript 是根据 Affero 通用公共许可证分发的,请务必阅读许可证并确保您遵守其中包含的条款。

    【讨论】:

    • 谢谢你的回答,@kens。 pdfPath 是具有多页的数字签名 PDF,因此 pageNumber 在此 pdf 的第一页和最后一页之间变化。我删除了-f-dQUIET-dSAFER-r-dTextAlphaBits-dGraphicsAlphaBits-dFirstPage-dLastPage 以调试此代码。这样做,命令行是:gswin32c -dNOPAUSE -dBATCH -sDEVICE=png16m -sOutputFile=C:/Download/DocumentosV2/Protocolo/Pronunciamento/fb21872746b64f8fb31b3764b5444e2e.png C:\Upload\DocumentosV2\Protocolo\Pronunciamento\3_0_404702190_2016_10081288_230_0_f1f09b4b38ac49a8a3e5576f6041eea3.pdf.
    【解决方案2】:

    为了完成这项工作,我修改了Simple VB.Net Wrapper for Ghostscript Dll CallBack:

    Private Function InOutErrCallBack(ByVal handle As IntPtr, _
      ByVal Strz As IntPtr, ByVal Bytes As Integer) As Integer
    
        Dim objString As String
        objString = Marshal.PtrToStringAnsi(Strz, Bytes)
    
        System.Diagnostics.Debug.WriteLine(objString)
    
        Return Bytes
    
    End Function
    

    这会将 Ghostscript 输出写入 Output 窗口的 Visual Studio 2003。我删除了 Ghostscript 中额外的“不必要”参数,例如 -dGraphicsAlphaBits。 asp.net 用户不访问Path.GetTempDir,所以,我需要一个不同的“temp”目录。

    'Converte cada página do PDF em imagem
    Public Function Pdf2Png(ByVal pdfPath As String, ByVal tempDirPath As String, ByVal resolucao As Int32) As Image()
    
        Dim outputImgPath As String
        Dim pageCount As Integer
    
        Dim objPdfReader As New iTextSharp.text.pdf.PdfReader(pdfPath)
        pageCount = objPdfReader.NumberOfPages()
    
        Dim objImages As New ArrayList
    
        For pageNumber As Int32 = 1 To pageCount
            outputImgPath = tempDirPath + Guid.NewGuid.ToString("N") + ".png"
    
            Dim objFileStream As FileStream
            Dim objMemoryStream As MemoryStream
    
            'Dim args() As String = { _
            '    "-dNOPAUSE", _
            '    "-dBATCH", _
            '    "-dSAFER", _
            '    "-dQUIET", _
            '    "-sDEVICE=png16m", _
            '    String.Format("-r{0}", resolucao), _
            '    "-dTextAlphaBits=2", _
            '    "-dGraphicsAlphaBits=2", _
            '    String.Format("-dFirstPage={0}", pageNumber), _
            '    String.Format("-dLastPage={0}", pageNumber), _
            '    String.Format("-sOutputFile={0}", outputImgPath), _
            '    "-f", _
            '    pdfPath _
            '    }
    
            Dim args() As String = { _
                "-dNOPAUSE", _
                "-dBATCH", _
                "-sDEVICE=png16m", _
                String.Format("-dFirstPage={0}", pageNumber), _
                String.Format("-dLastPage={0}", pageNumber), _
                String.Format("-sOutputFile={0}", outputImgPath), _
                Replace(pdfPath, "\", "/") _
                }
    
            If GhostscriptDllLib.RunGS(args) Then
                If File.Exists(outputImgPath) Then
                    objFileStream = New FileStream(outputImgPath, FileMode.Open)
                    Dim length As Int32 = objFileStream.Length
                    Dim bytes(length) As Byte
                    objFileStream.Read(bytes, 0, length)
                    objFileStream.Close()
    
                    objMemoryStream = New MemoryStream(bytes, False)
                    objImages.Add(Image.FromStream(objMemoryStream))
    
                    File.Delete(outputImgPath)
                Else
                    Throw New InvalidOperationException("Erro ao converter páginas do PDF em imagens PNG")
                End If
            Else
                Throw New InvalidOperationException("Erro ao converter páginas do PDF em imagens PNG")
            End If
    
        Next
    
        Return CType(objImages.ToArray(GetType(Image)), Image())
    
    End Function
    

    【讨论】:

      猜你喜欢
      • 2011-09-08
      • 2013-12-27
      • 2016-03-11
      • 2010-11-01
      • 2010-10-27
      • 2017-08-08
      • 1970-01-01
      • 2017-06-02
      • 2014-05-07
      相关资源
      最近更新 更多