首页 新闻 会员 周边 捐助

ITextSharp如何取到pdf中的第一页的内容,并以图片的形式输出的问题。

0
悬赏园豆:100 [已解决问题] 解决于 2012-11-15 13:33

iTextSharp第三方控件把图片文字生成pdf,我想用ITextSharp提供的函数和属性,获取pdf第一页的内容,并且能够以图片的形式输出,有哪位朋友可以解决这个问题吗?

小弟感激不尽!

DRenTeng的主页 DRenTeng | 初学一级 | 园豆:118
提问于:2012-11-14 21:02
< >
分享
最佳答案
0

iTextSharp的主要目的是用来生成pdf的, 虽然它也有pdf读取功能, 但是要转换成图片就有点超出它的定位了.

你可以用ghostscript, 这是一个免费的组件, 虽然封装形式我觉得比较垃圾, 但是胜在免费...

而且别人已经写好了二次封装的类, 无非就是多下载一个类的代码, 其实用起来还好.

先去下载ghostscript:  http://downloads.sourceforge.net/ghostscript/gs864w32.exe?use_mirror=garr

下完之后安装, 从安装目录的bin子目录下把gsdll32.dll 复制到自己项目的debug文件夹下(跟最终的exe文件同一目录)

然后下载一个二次封装的converter类, (稍后我试下能不能直接把代码贴出来, 或者我发你邮箱)

在mainForm中调用这个converter类:

        private void Form1_Load(object sender, EventArgs e)
        {
            ConvertSingleImage("d:\\b.pdf");
        }

        private bool ConvertSingleImage(string filename)
        {
            var converter = new PdfToImage.PDFConvert();
            //Setup the converter
            converter.OutputToMultipleFile = true;
            converter.FirstPageToConvert = -1;
            converter.LastPageToConvert = -1;
            converter.FitPage = true;
            converter.JPEGQuality = 10;
            converter.OutputFormat = "png16m";
            System.IO.FileInfo input = new FileInfo(filename);
            string output = string.Format("{0}\\{1}{2}", input.Directory, input.Name, ".png");
            //If the output file exist alrady be sure to add a random name at the end until is unique!
            while (File.Exists(output))
            {
                output = output.Replace(".png", string.Format("{1}{0}", ".png", DateTime.Now.Ticks));
            }
            return converter.Convert(input.FullName, output);
        }

 

这里的ConvertSingleImage函数原则上不用做任何修改, 它会在pdf的同目录下生成图片, 每页一张.

主调函数我直接放在formLoad中了, 你视情况修改即可.

收获园豆:100
夏狼哉 | 小虾三级 |园豆:833 | 2012-11-14 23:46
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections;
using System.IO;

namespace PdfToImage
{
    /// <summary>
    /// Create by : TaGoH
    /// URL of the last version: http://www.codeproject.com/KB/cs/GhostScriptUseWithCSharp.aspx
    /// Description:
    /// Class to convert a pdf to an image using GhostScript DLL
    /// A big Credit for this code go to:Rangel Avulso he made me start with the project!
    /// </summary>
    /// <see cref="http://www.codeproject.com/KB/cs/GhostScriptUseWithCSharp.aspx"/>
    /// <seealso cref="http://www.hrangel.com.br/index.php/2006/12/04/converter-pdf-para-imagem-jpeg-em-c/"/>
    public class PDFConvert
    {
        #region Static
        /// <summary>The name of the DLL i'm using to work</summary>
        public const string GhostScriptDLLName = "gsdll32.dll";
        /// <summary>Use to check for default transformation</summary>
        private static bool useSimpleAnsiConversion = true;
        /// <summary>Thanks to     tchu_2000 to remind that u should never hardcode strings! :)</summary>
        private const string GS_OutputFileFormat = "-sOutputFile={0}";
        private const string GS_DeviceFormat = "-sDEVICE={0}";
        private const string GS_FirstParameter = "pdf2img";
        private const string GS_ResolutionXFormat = "-r{0}";
        private const string GS_ResolutionXYFormat = "-r{0}x{1}";
        private const string GS_GraphicsAlphaBits = "-dGraphicsAlphaBits={0}";
        private const string GS_TextAlphaBits = "-dTextAlphaBits={0}";
        private const string GS_FirstPageFormat = "-dFirstPage={0}";
        private const string GS_LastPageFormat = "-dLastPage={0}";
        private const string GS_FitPage = "-dPDFFitPage";
        private const string GS_PageSizeFormat = "-g{0}x{1}";
        private const string GS_DefaultPaperSize = "-sPAPERSIZE={0}";
        private const string GS_JpegQualityFormat = "-dJPEGQ={0}";
        private const string GS_RenderingThreads = "-dNumRenderingThreads={0}";
        private const string GS_Fixed1stParameter = "-dNOPAUSE";
        private const string GS_Fixed2ndParameter = "-dBATCH";
        private const string GS_Fixed3rdParameter = "-dSAFER";
        private const string GS_FixedMedia = "-dFIXEDMEDIA";
        private const string GS_QuiteOperation = "-q";
        private const string GS_StandardOutputDevice = "-";
        private const string GS_MultiplePageCharacter = "%";
        //Thanks to davalv for this font related options
        //http://www.codeproject.com/script/Membership/View.aspx?mid=3255201
        private const string GS_FontPath = "-sFONTPATH={0}";
        private const string GS_NoPlatformFonts = "-dNOPLATFONTS";
        private const string GS_NoFontMap = "-dNOFONTMAP";
        private const string GS_FontMap = "-sFONTMAP={0}";
        private const string GS_SubstitutionFont = "-sSUBSTFONT={0}";
        private const string GS_FCOFontFile = "-sFCOfontfile={0}";
        private const string GS_FAPIFontMap = "-sFAPIfontmap={0}";
        private const string GS_NoPrecompiledFonts = "-dNOCCFONTS";
        /// <summary>Mutex used to be sure that the DLL is not called twice</summary>
        private static System.Threading.Mutex mutex;
        #endregion
        #region Windows Import
        /// <summary>Needed to copy memory from one location to another, used to fill the struct</summary>
        /// <param name="Destination"></param>
        /// <param name="Source"></param>
        /// <param name="Length"></param>
        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        static extern void CopyMemory(IntPtr Destination, IntPtr Source, uint Length);
        #endregion
        #region GhostScript Import

        /// <summary>Create a new instance of Ghostscript. This instance is passed to most other gsapi functions. The caller_handle will be provided to callback functions.
        ///  At this stage, Ghostscript supports only one instance. </summary>
        /// <param name="pinstance"></param>
        /// <param name="caller_handle"></param>
        /// <returns></returns>
        [DllImport(GhostScriptDLLName, EntryPoint = "gsapi_new_instance")]
        private static extern int gsapi_new_instance(out IntPtr pinstance, IntPtr caller_handle);

        /// <summary>This is the important function that will perform the conversion</summary>
        /// <param name="instance"></param>
        /// <param name="argc"></param>
        /// <param name="argv"></param>
        /// <returns></returns>
        [DllImport("gsdll32.dll", EntryPoint = "gsapi_init_with_args")]
        private static extern int gsapi_init_with_args(IntPtr instance, int argc, IntPtr argv);
        /// <summary>
        /// Exit the interpreter. This must be called on shutdown if gsapi_init_with_args() has been called, and just before gsapi_delete_instance(). 
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        [DllImport("gsdll32.dll", EntryPoint = "gsapi_exit")]
        private static extern int gsapi_exit(IntPtr instance);

        /// <summary>
        /// Destroy an instance of Ghostscript. Before you call this, Ghostscript must have finished. If Ghostscript has been initialised, you must call gsapi_exit before gsapi_delete_instance. 
        /// </summary>
        /// <param name="instance"></param>
        [DllImport("gsdll32.dll", EntryPoint = "gsapi_delete_instance")]
        private static extern void gsapi_delete_instance(IntPtr instance);
        /// <summary>Get info about the version of Ghostscript i'm using</summary>
        /// <param name="pGSRevisionInfo"></param>
        /// <param name="intLen"></param>
        /// <returns></returns>
        [DllImport("gsdll32.dll", EntryPoint = "gsapi_revision")]
        private static extern int gsapi_revision(ref GS_Revision pGSRevisionInfo, int intLen);
        /// <summary>Use a different I/O</summary>
        /// <param name="lngGSInstance"></param>
        /// <param name="gsdll_stdin">Function that menage the Standard INPUT</param>
        /// <param name="gsdll_stdout">Function that menage the Standard OUTPUT</param>
        /// <param name="gsdll_stderr">Function that menage the Standard ERROR output</param>
        /// <returns></returns>
        [DllImport("gsdll32.dll", EntryPoint = "gsapi_set_stdio")]
        private static extern int gsapi_set_stdio(IntPtr lngGSInstance, StdioCallBack gsdll_stdin, StdioCallBack gsdll_stdout, StdioCallBack gsdll_stderr);

        #endregion
        #region Const
        const int e_Quit = -101;
        const int e_NeedInput = -106;
        #endregion
        #region Variables
        private string _sDeviceFormat;
        private string _sParametersUsed;

        private int _iWidth;
        private int _iHeight;
        private int _iResolutionX;
        private int _iResolutionY;
        private int _iJPEGQuality;
        /// <summary>The first page to convert in image</summary>
        private int _iFirstPageToConvert = -1;
        /// <summary>The last page to conver in an image</summary>
        private int _iLastPageToConvert = -1;
        /// <summary>This parameter is used to control subsample antialiasing of graphics</summary>
        private int _iGraphicsAlphaBit = -1;
        /// <summary>This parameter is used to control subsample antialiasing of text</summary>
        private int _iTextAlphaBit = -1;
        /// <summary>In how many thread i should perform the conversion</summary>
        /// <remarks>This is a Major innovation since 8.63 NEVER use it with previous version!</remarks>
        private int _iRenderingThreads = -1;

        /// <summary>In how many thread i should perform the conversion</summary>
        /// <remarks>This is a Major innovation since 8.63 NEVER use it with previous version!</remarks>
        /// <value>Set it to 0 made the program set it to Environment.ProcessorCount HT machine could want to perform a check for this..</value>
        public int RenderingThreads
        {
            get { return _iRenderingThreads; }
            set
            {
                if (value == 0)
                    _iRenderingThreads = Environment.ProcessorCount;
                else
                    _iRenderingThreads = value;
            }
        }
        private bool _bFitPage;
        private bool _bThrowOnlyException = false;
        private bool _bRedirectIO = false;
        private bool _bForcePageSize = false;
        /// <summary>The pagesize of the output</summary>
        private string _sDefaultPageSize;
        private IntPtr _objHandle;
        /// <summary>If true i will try to output everypage to a different file!</summary>
        private bool _didOutputToMultipleFile = false;

        private System.Diagnostics.Process myProcess;
        public StringBuilder output;
        //public string output;
        //private List<byte> outputBytes;
        //public string error;
        #region Fonts related variables thanks to devalv
        private List<string> _sFontPath = new List<string>();
        private bool _bDisablePlatformFonts = false;
        private bool _bDisableFontMap = false;
        private List<string> _sFontMap = new List<string>();
        private string _sSubstitutionFont;
        private string _sFCOFontFile;
        private string _sFAPIFontMap;
        private bool _bDisablePrecompiledFonts = false;
        #endregion
        #endregion
        #region Proprieties
        /// <summary>
        /// What format to use to convert
        /// is suggested to use png256 instead of jpeg for document!
        /// they are smaller and better suited!
        /// </summary>
        /// <see cref="http://pages.cs.wisc.edu/~ghost/doc/cvs/Devices.htm"/>
        public string OutputFormat
        {
            get { return _sDeviceFormat; }
            set { _sDeviceFormat = value; }
        }

        /// <summary>The pagesize of the output</summary>
        /// <remarks>Without this parameter the output should be letter, complain to USA for this :) if the document specify a different size it will take precedece over this!</remarks>
        /// <see cref="http://pages.cs.wisc.edu/~ghost/doc/cvs/Use.htm#Known_paper_sizes"/>
        public string DefaultPageSize
        {
            get { return _sDefaultPageSize; }
            set { _sDefaultPageSize = value; }
        }

        /// <summary>If set to true and page default page size will force the rendering in that output format</summary>
        public bool ForcePageSize
        {
            get { return _bForcePageSize; }
            set { _bForcePageSize = value; }
        }

        public string ParametersUsed
        {
            get { return _sParametersUsed; }
            set { _sParametersUsed = value; }
        }

        public int Width
        {
            get { return _iWidth; }
            set { _iWidth = value; }
        }

        public int Height
        {
            get { return _iHeight; }
            set { _iHeight = value; }
        }

        public int ResolutionX
        {
            get { return _iResolutionX; }
            set { _iResolutionX = value; }
        }

        public int ResolutionY
        {
            get { return _iResolutionY; }
            set { _iResolutionY = value; }
        }

        /// <summary>This parameter is used to control subsample antialiasing of graphics</summary>
        /// <value>Value MUST BE below or equal 0 if not set, or 1,2,or 4 NO OTHER VALUES!</value>
        /// <see cref="http://pages.cs.wisc.edu/~ghost/doc/cvs/Use.htm"/>
        public int GraphicsAlphaBit
        {
            get { return _iGraphicsAlphaBit; }
            set
            {
                if ((value > 4) | (value == 3))
                    throw new ArgumentOutOfRangeException("The Graphics Alpha Bit must have a value between 1 2 and 4, or <= 0 if not set");
                _iGraphicsAlphaBit = value;
            }
        }
        /// <summary>This parameter is used to control subsample antialiasing of text</summary>
        /// <value>Value MUST BE below or equal 0 if not set, or 1,2,or 4 NO OTHER VALUES!</value>
        /// <see cref="http://pages.cs.wisc.edu/~ghost/doc/cvs/Use.htm"/>
        public int TextAlphaBit
        {
            get { return _iTextAlphaBit; }
            set
            {
                if ((value > 4) | (value == 3))
                    throw new ArgumentOutOfRangeException("The Text Alpha Bit must have a value between 1 2 and 4, or <= 0 if not set");
                _iTextAlphaBit = value;
            }
        }

        public Boolean FitPage
        {
            get { return _bFitPage; }
            set { _bFitPage = value; }
        }
        /// <summary>Quality of compression of JPG</summary>
        public int JPEGQuality
        {
            get { return _iJPEGQuality; }
            set { _iJPEGQuality = value; }
        }
        /// <summary>The first page to convert in image</summary>
        public int FirstPageToConvert
        {
            get { return _iFirstPageToConvert; }
            set { _iFirstPageToConvert = value; }
        }
        /// <summary>The last page to conver in an image</summary>
        public int LastPageToConvert
        {
            get { return _iLastPageToConvert; }
            set { _iLastPageToConvert = value; }
        }
        /// <summary>Set to True if u want the program to never display Messagebox
        /// but otherwise throw exception</summary>
        public Boolean ThrowOnlyException
        {
            get { return _bThrowOnlyException; }
            set { _bThrowOnlyException = value; }
        }
        /// <summary>[NOT WORKING]If i should redirect the Output of Ghostscript library somewhere</summary>
        /// <remarks>NOT WORKING!!!</remarks>
        public bool RedirectIO
        {
            get { return _bRedirectIO; }
            set { _bRedirectIO = value; }
        }
        /// <summary>If true i will try to output everypage to a different file!</summary>
        public bool OutputToMultipleFile
        {
            get { return _didOutputToMultipleFile; }
            set { _didOutputToMultipleFile = value; }
        }
        /// <summary>
        /// If set to true the library will use a mutex to be sure that the library is never called twice at the same time!
        /// </summary>
        public bool UseMutex
        {
            get { return mutex != null; }
            set
            {
                if (!value)//if i don't want to use it
                {
                    if (mutex != null)//if it exist
                    {   //close and delete it
                        mutex.ReleaseMutex();
                        mutex.Close();
                        mutex = null;
                    }
                }
                else//If i want to use mutex create it if it doesn't exist
                {
                    if (mutex == null)
                        mutex = new System.Threading.Mutex(false, "MutexGhostscript");
                }
            }
        }

        #region Fonts related thanks to devalv
        public List<string> FontPath
        {
            get { return _sFontPath; }
            set { _sFontPath = value; }
        }

        public bool DisablePlatformFonts
        {
            get { return _bDisablePlatformFonts; }
            set { _bDisablePlatformFonts = value; }
        }

        public bool DisableFontMap
        {
            get { return _bDisableFontMap; }
            set { _bDisableFontMap = value; }
        }

        public List<string> FontMap
        {
            get { return _sFontMap; }
            set { _sFontMap = value; }
        }

        public string SubstitutionFont
        {
            get { return _sSubstitutionFont; }
            set { _sSubstitutionFont = value; }
        }

        public string FCOFontFile
        {
            get { return _sFCOFontFile; }
            set { _sFCOFontFile = value; }
        }

        public string FAPIFontMap
        {
            get { return _sFAPIFontMap; }
            set { _sFAPIFontMap = value; }
        }

        public bool DisablePrecompiledFonts
        {
            get { return _bDisablePrecompiledFonts; }
            set { _bDisablePrecompiledFonts = value; }
        }
        #endregion
        #endregion
        #region Init
        public PDFConvert(IntPtr objHandle)
        {
            _objHandle = objHandle;
        }

        public PDFConvert()
        {
            _objHandle = IntPtr.Zero;
        }
        #endregion

        #region Convert
        /// <summary>Convert a single file!</summary>
        /// <param name="inputFile">The file PDf to convert</param>
        /// <param name="outputFile">The image file that will be created</param>
        /// <remarks>You must pass all the parameter for the conversion
        /// as Proprieties of this class</remarks>
        /// <returns>True if the conversion succed!</returns>
        public bool Convert(string inputFile, string outputFile)
        {
            return Convert(inputFile, outputFile, _bThrowOnlyException, null);
        }

        /// <summary>Convert a single file!</summary>
        /// <param name="inputFile">The file PDf to convert</param>
        /// <param name="outputFile">The image file that will be created</param>
        /// <param name="parameters">You must pass all the parameter for the conversion here</param>
        /// <remarks>Thanks to     tchu_2000 for the help!</remarks>
        /// <returns>True if the conversion succed!</returns>
        public bool Convert(string inputFile, string outputFile, string parameters)
        {
            return Convert(inputFile, outputFile, _bThrowOnlyException, parameters);
        }

        /// <summary>Convert a single file!</summary>
        /// <param name="inputFile">The file PDf to convert</param>
        /// <param name="outputFile">The image file that will be created</param>
        /// <param name="throwException">if the function should throw an exception
        /// or display a message box</param>
        /// <remarks>You must pass all the parameter for the conversion
        /// as Proprieties of this class</remarks>
        /// <returns>True if the conversion succed!</returns>
        private bool Convert(string inputFile, string outputFile, bool throwException, string options)
        {
            #region Check Input
            //Avoid to work when the file doesn't exist
            if (string.IsNullOrEmpty(inputFile))
                throw new ArgumentNullException("inputFile");
            if (!System.IO.File.Exists(inputFile))
                throw new ArgumentException(string.Format("The file :'{0}' doesn't exist", inputFile), "inputFile");
            if (string.IsNullOrEmpty(_sDeviceFormat))
                throw new ArgumentNullException("Device");
            //be sure that if i specify multiple page outpage i added the % to the filename!
            #endregion
            //If i create a Mutex it means i want to protect concurrent access to the library
            if (mutex != null) mutex.WaitOne();
            bool result = false;
            try
            {
                result = ExecuteGhostscriptCommand(GetGeneratedArgs(inputFile, outputFile, options));
            }
            finally { if (mutex != null) mutex.ReleaseMutex(); }
            return result;
        }

        /// <summary>Print a file</summary>
        /// <param name="inputFile">THe file to print</param>
        /// <param name="printParametersFile">The file with the configuration of the printer</param>
        /// <returns>True if i send the work to the printer queue</returns>
        public bool Print(string inputFile, string printParametersFile)
        {
            #region Check Input
            //Avoid to work when the file doesn't exist
            if (string.IsNullOrEmpty(inputFile))
                throw new ArgumentNullException("inputFile");
            if (!System.IO.File.Exists(inputFile))
                throw new ArgumentException(string.Format("The file :'{0}' doesn't exist", inputFile), "inputFile");
            //Avoid to work when the file doesn't exist
            if (string.IsNullOrEmpty(printParametersFile))
                throw new ArgumentNullException("printParametersFile");
            if (!System.IO.File.Exists(printParametersFile))
                throw new ArgumentException(string.Format("The file :'{0}' doesn't exist", printParametersFile), "printParametersFile");
            #endregion
            // Example : gswin32.exe" -dNOPAUSE -dBATCH -dFirstPage=1 -dLastPage=1 setup.ps mio.pdf -c quit
            List<string> args = new List<string>(7);
            args.Add("printPdf");
            args.Add("-dNOPAUSE");
            args.Add("-dBATCH");
            if (_iFirstPageToConvert > 0)
                args.Add(string.Format("-dFirstPage={0}", _iFirstPageToConvert));
            if ((_iLastPageToConvert > 0) && (_iLastPageToConvert >= _iFirstPageToConvert))
                args.Add(string.Format("-dLastPage={0}", _iLastPageToConvert));
            args.Add(printParametersFile);
            args.Add(inputFile);
            bool result = false;
            if (mutex != null) mutex.WaitOne();
            try { result = ExecuteGhostscriptCommand(args.ToArray()); }
            finally { if (mutex != null) mutex.ReleaseMutex(); }
            return result;
        }

        /// <summary>Execute a Ghostscript command with a certain list of arguments</summary>
        /// <param name="sArgs">The list of the arguments</param>
        /// <returns>true if it succed, false otherwise</returns>
        private bool ExecuteGhostscriptCommand(string[] sArgs)
        {
            #region Variables
            int intReturn, intCounter, intElementCount;
            //The pointer to the current istance of the dll
            IntPtr intGSInstanceHandle = IntPtr.Zero;
            object[] aAnsiArgs;
            IntPtr[] aPtrArgs;
            GCHandle[] aGCHandle;
            IntPtr callerHandle, intptrArgs;
            GCHandle gchandleArgs;
            #endregion
            #region Convert Unicode strings to null terminated ANSI byte arrays
            // Convert the Unicode strings to null terminated ANSI byte arrays
            // then get pointers to the byte arrays.
            intElementCount = sArgs.Length;
            aAnsiArgs = new object[intElementCount];
            aPtrArgs = new IntPtr[intElementCount];
            aGCHandle = new GCHandle[intElementCount];
            //Convert the parameters
            for (intCounter = 0; intCounter < intElementCount; intCounter++)
            {
                aAnsiArgs[intCounter] = StringToAnsiZ(sArgs[intCounter]);
                aGCHandle[intCounter] = GCHandle.Alloc(aAnsiArgs[intCounter], GCHandleType.Pinned);
                aPtrArgs[intCounter] = aGCHandle[intCounter].AddrOfPinnedObject();
            }
            gchandleArgs = GCHandle.Alloc(aPtrArgs, GCHandleType.Pinned);
            intptrArgs = gchandleArgs.AddrOfPinnedObject();
            #endregion
            #region Create a new istance of the library!
            intReturn = -1;
            try
            {
                intReturn = gsapi_new_instance(out intGSInstanceHandle, _objHandle);
                //Be sure that we create an istance!
                if (intReturn < 0)
                {
                    ClearParameters(ref aGCHandle, ref gchandleArgs);
                    throw new ApplicationException("I can't create a new istance of Ghostscript please verify no other istance are running!");
                }
            }
            catch (BadImageFormatException formatException)//99.9% of time i'm just loading a 32bit dll in a 64bit enviroment!
            {
                ClearParameters(ref aGCHandle, ref gchandleArgs);
                //Check if i'm in a 64bit enviroment or a 32bit
                if (IntPtr.Size == 8) // 8 * 8 = 64
                {
                    throw new ApplicationException(string.Format("The gsdll32.dll you provide is not compatible with the current architecture that is 64bit," +
                    "Please download any version above version 8.64 from the original website in the 64bit or x64 or AMD64 version!"));
                }
                else if (IntPtr.Size == 4) // 4 * 8 = 32
                {
                    throw new ApplicationException(string.Format("The gsdll32.dll you provide is not compatible with the current architecture that is 32bit," +
                    "Please download any version above version 8.64 from the original website in the 32bit or x86 or i386 version!"));
                }
            }
            catch (DllNotFoundException ex)//in this case the dll we r using isn't the dll we expect
            {
                ClearParameters(ref aGCHandle, ref gchandleArgs);
                throw new ApplicationException("The gsdll32.dll wasn't found in default dlls search path" +
                    "or is not in correct version (doesn't expose the required methods). Please download " +
                    "at least the version 8.64 from the original website");
            }
            callerHandle = IntPtr.Zero;//remove unwanter handler
            #endregion
            #region Capture the I/O
            //Not working
            if (_bRedirectIO)
            {
                StdioCallBack stdinCallback = new StdioCallBack(gsdll_stdin);
                StdioCallBack stdoutCallback = new StdioCallBack(gsdll_stdout);
                StdioCallBack stderrCallback = new StdioCallBack(gsdll_stderr);
                intReturn = gsapi_set_stdio(intGSInstanceHandle, stdinCallback, stdoutCallback, stderrCallback);
                if (output == null) output = new StringBuilder();
                else output.Remove(0, output.Length);
                myProcess = System.Diagnostics.Process.GetCurrentProcess();
                myProcess.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(SaveOutputToImage);
            }
            #endregion
            intReturn = -1;//if nothing change it there is an error!
            //Ok now is time to call the interesting method
            try { intReturn = gsapi_init_with_args(intGSInstanceHandle, intElementCount, intptrArgs); }
            catch (Exception ex)
            {
                throw new ApplicationException(ex.Message, ex);
            }
            finally//No matter what happen i MUST close the istance!
            {   //free all the memory
                ClearParameters(ref aGCHandle, ref gchandleArgs);
                gsapi_exit(intGSInstanceHandle);//Close the istance
                gsapi_delete_instance(intGSInstanceHandle);//delete it
                //In case i was looking for output now stop
                if ((myProcess != null) && (_bRedirectIO)) myProcess.OutputDataReceived -= new System.Diagnostics.DataReceivedEventHandler(SaveOutputToImage);
            }
            //Conversion was successfull if return code was 0 or e_Quit
            return (intReturn == 0) | (intReturn == e_Quit);//e_Quit = -101
        }

        /// <summary>Remove the memory allocated</summary>
        /// <param name="aGCHandle"></param>
        /// <param name="gchandleArgs"></param>
        private void ClearParameters(ref GCHandle[] aGCHandle, ref GCHandle gchandleArgs)
        {
            for (int intCounter = 0; intCounter < aGCHandle.Length; intCounter++)
                aGCHandle[intCounter].Free();
            gchandleArgs.Free();
        }
        #region Test (code not used)
        void SaveOutputToImage(object sender, System.Diagnostics.DataReceivedEventArgs e)
        {
            output.Append(e.Data);
        }

        //public System.Drawing.Image Convert(string inputFile)
        //{
        //    _bRedirectIO = true;
        //    if (Convert(inputFile, "%stdout", _bThrowOnlyException))
        //    {
        //        if ((output != null) && (output.Length > 0))
        //        {
        //            //StringReader sr = new StringReader(output.ToString());
        //            //MemoryStream ms = new MemoryStream(UTF8Encoding.Default.GetBytes(output.ToString()));
        //            System.Drawing.Image returnImage = System.Drawing.Image.FromStream(myProcess.StandardOutput.BaseStream).Clone() as System.Drawing.Image;
        //            //ms.Close();
        //            return returnImage;
        //        }
        //    }
        //    return null;
        //}
        #endregion
        #endregion

        #region Accessory Functions
        /// <summary>This function create the list of parameters to pass to the dll with parameters given directly from the program</summary>
        /// <param name="inputFile"></param>
        /// <param name="outputFile"></param>
        /// <param name="otherParameters">The other parameters i could be interested</param>
        /// <remarks>Be very Cautious using this! code provided and modified from tchu_2000</remarks>
        /// <returns></returns>
        private string[] GetGeneratedArgs(string inputFile, string outputFile, string otherParameters)
        {
            if (!string.IsNullOrEmpty(otherParameters))
                return GetGeneratedArgs(inputFile, outputFile, otherParameters.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries));
            else
                return GetGeneratedArgs(inputFile, outputFile, (string[])null);
        }

        /// <summary>This function create the list of parameters to pass to the dll</summary>
        /// <param name="inputFile">the file to convert</param>
        /// <param name="outputFile">where to write the image</param>
        /// <returns>the list of the arguments</returns>
        private string[] GetGeneratedArgs(string inputFile, string outputFile, string[] presetParameters)
        {
            string[] args;
            ArrayList lstExtraArgs = new ArrayList();
            //ok if i haven't been passed a list of parameters create my own
            if ((presetParameters == null) || (presetParameters.Length == 0))
            {
                #region Parameters
                //Ok now check argument per argument and compile them
                //If i want a jpeg i can set also quality
                if (_sDeviceFormat == "jpeg" && _iJPEGQuality > 0 && _iJPEGQuality < 101)
                    lstExtraArgs.Add(string.Format(GS_JpegQualityFormat, _iJPEGQuality));
                //if i provide size it will override the paper size
                if (_iWidth > 0 && _iHeight > 0)
                    lstExtraArgs.Add(string.Format(GS_PageSizeFormat, _iWidth, _iHeight));
                else//otherwise if aviable use the papersize
                {
                    if (!string.IsNullOrEmpty(_sDefaultPageSize))
                    {
                        lstExtraArgs.Add(string.Format(GS_DefaultPaperSize, _sDefaultPageSize));
                        //It have no meaning to set it if the default page is not set!
                        if (_bForcePageSize)
                            lstExtraArgs.Add(GS_FixedMedia);
                    }
                }

                //not set antialiasing settings
                if (_iGraphicsAlphaBit > 0)
                    lstExtraArgs.Add(string.Format(GS_GraphicsAlphaBits, _iGraphicsAlphaBit));
                if (_iTextAlphaBit > 0)
                    lstExtraArgs.Add(string.Format(GS_TextAlphaBits, _iTextAlphaBit));
                //Should i try to fit?
                if (_bFitPage) lstExtraArgs.Add(GS_FitPage);
                //Do i have a forced resolution?
                if (_iResolutionX > 0)
                {
                    if (_iResolutionY > 0)
                        lstExtraArgs.Add(String.Format(GS_ResolutionXYFormat, _iResolutionX, _iResolutionY));
                    else
                        lstExtraArgs.Add(String.Format(GS_ResolutionXFormat, _iResolutionX));
                }
                if (_iFirstPageToConvert > 0)
                    lstExtraArgs.Add(String.Format(GS_FirstPageFormat, _iFirstPageToConvert));
                if (_iLastPageToConvert > 0)
                {
                    if ((_iFirstPageToConvert > 0) && (_iFirstPageToConvert > _iLastPageToConvert))
                        throw new ArgumentOutOfRangeException(string.Format("The 1st page to convert ({0}) can't be after then the last one ({1})", _iFirstPageToConvert, _iLastPageToConvert));
                    lstExtraArgs.Add(String.Format(GS_LastPageFormat, _iLastPageToConvert));
                }
                //Set in how many threads i want to do the work
                if (_iRenderingThreads > 0)
                    lstExtraArgs.Add(String.Format(GS_RenderingThreads, _iRenderingThreads));

                //If i want to redirect write it to the standard output!
                if (_bRedirectIO)
                {
                    //In this case you must also use the -q switch to prevent Ghostscript
                    //from writing messages to standard output which become
                    //mixed with the intended output stream. 
                    //outputFile = GS_StandardOutputDevice;
                    //lstExtraArgs.Add(GS_QuiteOperation);
                }
                #region Fonts
                if ((_sFontPath != null) && (_sFontPath.Count > 0))
                    lstExtraArgs.Add(String.Format(GS_FontPath, String.Join(";", _sFontPath.ToArray())));
                if (_bDisablePlatformFonts)
                    lstExtraArgs.Add(GS_NoPlatformFonts);
                if (_bDisableFontMap)
                    lstExtraArgs.Add(GS_NoFontMap);
                if ((_sFontMap != null) && (_sFontMap.Count > 0))
                    lstExtraArgs.Add(String.Format(GS_FontMap, String.Join(";", _sFontMap.ToArray())));
                if (!string.IsNullOrEmpty(_sSubstitutionFont))
                    lstExtraArgs.Add(string.Format(GS_SubstitutionFont, _sSubstitutionFont));
                if (!string.IsNullOrEmpty(_sFCOFontFile))
                    lstExtraArgs.Add(string.Format(GS_FCOFontFile, _sFCOFontFile));
                if (!string.IsNullOrEmpty(_sFAPIFontMap))
                {
                    lstExtraArgs.Add(string.Format(GS_FAPIFontMap, _sFAPIFontMap));
                }
                if (_bDisablePrecompiledFonts)
                    lstExtraArgs.Add(GS_NoPrecompiledFonts);
                #endregion
                #endregion
                int iFixedCount = 7;//This are the mandatory options
                int iExtraArgsCount = lstExtraArgs.Count;
                args = new string[iFixedCount + lstExtraArgs.Count];
                args[1] = GS_Fixed1stParameter;//"-dNOPAUSE";//I don't want interruptions
                args[2] = GS_Fixed2ndParameter;//"-dBATCH";//stop after
                args[3] = GS_Fixed3rdParameter;//"-dSAFER";
                args[4] = string.Format(GS_DeviceFormat, _sDeviceFormat);//what kind of export format i should provide
                //For a complete list watch here:
                //http://pages.cs.wisc.edu/~ghost/doc/cvs/Devices.htm
                //Fill the remaining parameters
                for (int i = 0; i < iExtraArgsCount; i++)
                    args[5 + i] = (string)lstExtraArgs[i];
            }
            else
            {//3 arguments MUST be added 0 (meaningless) and at the end the output and the inputfile
                args = new string[presetParameters.Length + 3];
                //now use the parameters i receive (thanks CrucialBT to point this out!)
                //and thanks to Barbara who pointout that i was skipping the last parameter
                for (int i = 1; i <= presetParameters.Length; i++)
                    args[i] = presetParameters[i - 1];
            }
            args[0] = GS_FirstParameter;//this parameter have little real use
            //Now check if i want to update to 1 file per page i have to be sure do add % to the output filename
            if ((_didOutputToMultipleFile) && (!outputFile.Contains(GS_MultiplePageCharacter)))
            {// Thanks to Spillie to show me the error!
                int lastDotIndex = outputFile.LastIndexOf('.');
                if (lastDotIndex > 0)
                    outputFile = outputFile.Insert(lastDotIndex, "%d");
            }
            //Ok now save them to be shown 4 debug use
            _sParametersUsed = string.Empty;
            //Copy all the args except the 1st that is useless and the last 2
            for (int i = 1; i < args.Length - 2; i++)
                _sParametersUsed += " " + args[i];
            //Fill outputfile and inputfile as last 2 arguments!
            args[args.Length - 2] = string.Format(GS_OutputFileFormat, outputFile);
            args[args.Length - 1] = string.Format("{0}", inputFile);

            _sParametersUsed += " " + string.Format(GS_OutputFileFormat, string.Format("\"{0}\"", outputFile))
            + " " + string.Format("\"{0}\"", inputFile);
            return args;
        }

        /// <summary>
        /// Convert a Unicode string to a null terminated Ansi string for Ghostscript.
        /// The result is stored in a byte array
        /// </summary>
        /// <param name="str">The parameter i want to convert</param>
        /// <returns>the byte array that contain the string</returns>
        private static byte[] StringToAnsiZ(string str)
        {   //This with Encoding.Default should work also with Chineese Japaneese
            //Thanks to tchu_2000 I18N related patch
            if (str == null) str = String.Empty;
            return Encoding.Default.GetBytes(str);
        }

        /// <summary>Convert a Pointer to a string to a real string</summary>
        /// <param name="strz">the pointer to the string in memory</param>
        /// <returns>The string</returns>
        public static string AnsiZtoString(IntPtr strz)
        {
            if (strz != IntPtr.Zero)
                return Marshal.PtrToStringAnsi(strz);
            else
                return string.Empty;
        }

        /// <summary>Check if i find the DLL that i need to continue!</summary>
        /// <returns>true if i found it</returns>
        public static bool CheckDll()
        {
            return File.Exists(GhostScriptDLLName);
        }
        #endregion
        #region Menage Standard Input & Standard Output
        public int gsdll_stdin(IntPtr intGSInstanceHandle, IntPtr strz, int intBytes)
        {
            // This is dumb code that reads one byte at a time
            // Ghostscript doesn't mind this, it is just very slow
            if (intBytes == 0)
                return 0;
            else
            {
                int ich = Console.Read();
                if (ich == -1)
                    return 0; // EOF
                else
                {
                    byte bch = (byte)ich;
                    GCHandle gcByte = GCHandle.Alloc(bch, GCHandleType.Pinned);
                    IntPtr ptrByte = gcByte.AddrOfPinnedObject();
                    CopyMemory(strz, ptrByte, 1);
                    ptrByte = IntPtr.Zero;
                    gcByte.Free();
                    return 1;
                }
            }
        }

        public int gsdll_stdout(IntPtr intGSInstanceHandle, IntPtr strz, int intBytes)
        {
            // If you can think of a more efficient method, please tell me!
            // We need to convert from a byte buffer to a string
            // First we create a byte array of the appropriate size
            byte[] aByte = new byte[intBytes];
            // Then we get the address of the byte array
            GCHandle gcByte = GCHandle.Alloc(aByte, GCHandleType.Pinned);
            IntPtr ptrByte = gcByte.AddrOfPinnedObject();
            // Then we copy the buffer to the byte array
            CopyMemory(ptrByte, strz, (uint)intBytes);
            // Release the address locking
            ptrByte = IntPtr.Zero;
            gcByte.Free();
            // Then we copy the byte array to a string, character by character
            string str = "";
            for (int i = 0; i < intBytes; i++)
            {
                str += (char)aByte[i];
            }
            // Finally we output the message
            //Console.Write(str);
            output.Append(str);
            return intBytes;
            //if (intBytes > 0)
            //{
            //    Console.Write(Marshal.PtrToStringAnsi(strz));
            //}
            //return 0;
        }

        public int gsdll_stderr(IntPtr intGSInstanceHandle, IntPtr strz, int intBytes)
        {
            return gsdll_stdout(intGSInstanceHandle, strz, intBytes);
            //Console.Write(Marshal.PtrToStringAnsi(strz));
            //return intBytes;
        }
        #endregion
        #region Menage Revision
        public GhostScriptRevision GetRevision()
        {
            // Check revision number of Ghostscript
            int intReturn;
            GS_Revision udtGSRevInfo = new GS_Revision();
            GhostScriptRevision output;
            GCHandle gcRevision;
            gcRevision = GCHandle.Alloc(udtGSRevInfo, GCHandleType.Pinned);
            intReturn = gsapi_revision(ref udtGSRevInfo, 16);
            output.intRevision = udtGSRevInfo.intRevision;
            output.intRevisionDate = udtGSRevInfo.intRevisionDate;
            output.ProductInformation = AnsiZtoString(udtGSRevInfo.strProduct);
            output.CopyrightInformations = AnsiZtoString(udtGSRevInfo.strCopyright);
            gcRevision.Free();
            return output;
        }
        #endregion
    }

    /// <summary>Delegate used by Ghostscript to perform I/O operations</summary>
    /// <param name="handle"></param>
    /// <param name="strptr"></param>
    /// <param name="count"></param>
    /// <returns></returns>
    public delegate int StdioCallBack(IntPtr handle, IntPtr strptr, int count);

    /// <summary>This struct is filled with the information of the version of this ghostscript</summary>
    /// <remarks>Have the layout defined cuz i will fill it with a kernel copy memory</remarks>
    [StructLayout(LayoutKind.Sequential)]
    struct GS_Revision
    {
        public IntPtr strProduct;
        public IntPtr strCopyright;
        public int intRevision;
        public int intRevisionDate;
    }

    public struct GhostScriptRevision
    {
        public string ProductInformation;
        public string CopyrightInformations;
        public int intRevision;
        public int intRevisionDate;
    }
}
夏狼哉 | 园豆:833 (小虾三级) | 2012-11-14 23:49

@夏狼哉: 279329105@qq.com,非常感谢你的帮助。

DRenTeng | 园豆:118 (初学一级) | 2012-11-15 00:09

@DRenTeng:

不用发邮箱了啊, 这个类的代码不是已经全贴出来了吗? 我原来怀疑这么长能不能全贴出来, 结果证明博客园的回贴还是很强悍的. 你直接复制上面的代码, 一行不用改, 加入项目中即可.  

夏狼哉 | 园豆:833 (小虾三级) | 2012-11-15 08:04

@夏狼哉: 我是在类库中操作,我加入后运行发现抛出异常,我安装后,把那个dll放到我的类库的bin目录中的debug文件夹下,异常是:The gsdll32.dll wasn't found in default dlls search pathor is not in correct version (doesn't expose the required methods). Please download at least the version 8.64 from the original website(说什么方法不公开)?求解。

DRenTeng | 园豆:118 (初学一级) | 2012-11-15 10:22

@DRenTeng: 

你在实际的项目中要怎么做(比如放dll中, 或是其它的什么) , 你以后再慢慢研究, 你现在先新建一个windows form项目, 就按我说的顺序, 先把功能测试通过, 再去看怎么移植的问题.

夏狼哉 | 园豆:833 (小虾三级) | 2012-11-15 10:33

@夏狼哉: 哥们,在window下是可以,但是如何移植到web项目里面呢?谢谢!

DRenTeng | 园豆:118 (初学一级) | 2012-11-15 11:30

@DRenTeng: 

本质上,这个动作需要一个函数库的支持(即下载的ghostscript), 所以要想直接在客户端去做这种转换是不可能的.  如果需要在web上实现, 可以通过如下流程:

1. 用户上传pdf文件到服务器.

2. 服务器生成一组图片, 最后调用打包程序生成一个压缩包.

3. 再通过下载机制让用户把此压缩包下载到本地.

4. 清理服务器上的临时数据, 把用户上传的pdf, 以及刚生成的图片和压缩包都删除.

当然, 也可以考虑在客户端装插件, 直接在客户端转.

夏狼哉 | 园豆:833 (小虾三级) | 2012-11-15 11:34

@夏狼哉: 如果我想直接在web项目中写代码实现生成图片,应该如何做呢?谢谢!

DRenTeng | 园豆:118 (初学一级) | 2012-11-15 11:59

@DRenTeng: 

请参阅我上一个回复......

夏狼哉 | 园豆:833 (小虾三级) | 2012-11-15 12:21

@夏狼哉: 我在winform中写代码可以,但是在web项目中好像不行哦,首先第一个问题就是那个dll文件不知道放哪里?放在那个BLL层(我在这个层写实现逻辑)的bin目录下的debug里面不行,这个如何做呢?就是你上面回复的第二步,生成一组图片那个步骤不知道怎么做,可以给一点提示吗?

DRenTeng | 园豆:118 (初学一级) | 2012-11-15 12:55

@夏狼哉:  朋友,那个pdf转化为图片的代码应该如何在web里面写,可以给个解释一下吗?

DRenTeng | 园豆:118 (初学一级) | 2012-11-15 13:58

@DRenTeng: 

对asp.net项目来说, 有两种做法:

1. 在DllImport中, 写成绝对路径. 例如, 把dll文件拷到c:\dll下, 然后:

  [DllImport(@"c:\dll\gsdll32.dll")]

2. 把dll文件拷到system32目录下.

 

为了程序的可移植性, 建议采用第二种做法.

夏狼哉 | 园豆:833 (小虾三级) | 2012-11-15 14:08

@夏狼哉: 谢谢!

DRenTeng | 园豆:118 (初学一级) | 2012-11-15 14:23

请问PdfToImage 是哪个DLL 中的?

hbgdluck | 园豆:148 (初学一级) | 2013-10-17 14:56
其他回答(1)
0

好东西啊 正要急用,拿走了

hbgdluck | 园豆:148 (初学一级) | 2013-10-17 14:35
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册