Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用ITextSharp将tif转换为pdf时性能不佳_C#_Performance_Itextsharp - Fatal编程技术网

C# 使用ITextSharp将tif转换为pdf时性能不佳

C# 使用ITextSharp将tif转换为pdf时性能不佳,c#,performance,itextsharp,C#,Performance,Itextsharp,摘要:如何减少使用itextsharp将TIF转换为PDF所需的时间 背景:我正在使用C#和itextsharp将一些相当大的tif转换为pdf,我的性能非常差。tif文件约为50kb/件,有些文档最多有150个独立的tif文件(每个文件代表一个页面)。对于一个132页的文档(约6500 kb),转换大约需要13分钟。在转换过程中,它运行的单CPU服务器以100%的速度运行,这让我相信该进程是CPU受限的。输出的pdf文件为3.5 MB。我对尺寸还可以,但花的时间对我来说似乎有点高 代码: pr

摘要:如何减少使用
itextsharp
将TIF转换为PDF所需的时间

背景:我正在使用C#和
itextsharp
将一些相当大的tif转换为pdf,我的性能非常差。tif文件约为50kb/件,有些文档最多有150个独立的tif文件(每个文件代表一个页面)。对于一个132页的文档(约6500 kb),转换大约需要13分钟。在转换过程中,它运行的单CPU服务器以100%的速度运行,这让我相信该进程是CPU受限的。输出的pdf文件为3.5 MB。我对尺寸还可以,但花的时间对我来说似乎有点高

代码:

private void CombineAndConvertTif(IList<FileInfo> inputFiles, FileInfo outputFile)
{
    using (FileStream fs = new FileStream(outputFile.FullName, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
    {
        Document document = new Document(PageSize.A4, 50, 50, 50, 50);
        PdfWriter writer = PdfWriter.GetInstance(document, fs);
        document.Open();
        PdfContentByte cb = writer.DirectContent;

        foreach (FileInfo inputFile in inputFiles)
        {
            using (Bitmap bm = new Bitmap(inputFile.FullName))
            {
                int total = bm.GetFrameCount(FrameDimension.Page);

                for (int k = 0; k < total; ++k)
                {
                    bm.SelectActiveFrame(FrameDimension.Page, k);
                    //Testing shows that this line takes the lion's share (80%) of the time involved.
                    iTextSharp.text.Image img =
                        iTextSharp.text.Image.GetInstance(bm, null, true);
                    img.ScalePercent(72f / 200f * 100);
                    img.SetAbsolutePosition(0, 0);

                    cb.AddImage(img);
                    document.NewPage();
                }
            }
        }

        document.Close();
        writer.Close();
    }

}
private void CombineAndConvertTif(IList inputFiles、FileInfo outputFile)
{
使用(FileStream fs=newfilestream(outputFile.FullName,FileMode.Create,FileAccess.ReadWrite,FileShare.None))
{
文件=新文件(PageSize.A4、50、50、50、50);
PdfWriter writer=PdfWriter.GetInstance(文档,fs);
document.Open();
PdfContentByte cb=writer.DirectContent;
foreach(输入文件中的文件信息输入文件)
{
使用(位图bm=新位图(inputFile.FullName))
{
int total=bm.GetFrameCount(FrameDimension.Page);
对于(整数k=0;k
我遇到了这个问题。我最终使用了AdobeAcrobat的批处理功能,效果很好。我刚刚设置了一个新的批处理过程,将目标文件夹中的所有TIFF转换为写入目标文件夹的PDF,然后启动它。设置起来很容易,但处理时间比我喜欢的要长。它确实完成了任务


遗憾的是,Adobe AutoBAT不是免费的,但你应该考虑它(权衡你的时间来开发一个“免费”的解决方案与软件的成本)。

< p>你正在处理大量的数据,所以如果PDF导出过程很慢,并且你没有使用一个快速的PC,那么你可能会被这种性能所困扰。 在多核系统上加速这一进程最明显的方法是多线程

将代码分为两个阶段。首先,可以将一组图像转换并存储在列表中,然后将列表输出到PDF。根据您所说的文件大小,在处理过程中将整个文档存储在内存中的内存使用情况应该不会有问题

然后,您可以将此过程的第一阶段设置为多线程—您可以为每个需要转换的映像启动一个线程池线程,限制活动线程的数量(粗略地说,每个CPU核心一个线程就足够了—更多的线程对您没有多大好处)。Aln的替代方法是将输入列表拆分为n个列表(同样,每个CPU核心一个列表),然后触发只处理自己列表的线程。这减少了线程开销,但可能会导致一些thred比其他thred提前很长时间完成(如果他们的工作量大大减少的话),因此它的运行速度可能并不总是那么快

通过将其分为两个过程,您还可以通过将所有输入处理和所有输出处理作为单独的阶段来获得性能(即使没有多线程),这可能会减少所涉及的磁盘查找(取决于您的电脑上有多少可用于磁盘缓存的RAM)

请注意,如果您只有一个单核CPU,那么它就没有多大用处(尽管您仍然可以看到进程中I/O受限的部分有所增加,但听起来您主要是CPU受限的)

您还可以尝试使用itextsharp调用以外的其他方法调整位图的大小-我对itextsharp一无所知,但它的图像转换代码可能很慢,或者没有以其他缩放技术可能能够实现的方式使用图形硬件。您还可以设置一些缩放选项,在质量和速度之间进行权衡,您可以尝试

//Testing shows that this line takes the lion's share (80%) of the time involved.
iTextSharp.text.Image img =
  iTextSharp.text.Image.GetInstance(bm, null, true);
这可能是一个愚蠢的建议(现在没有一个大型的测试集在本地进行测试),但请告诉我怀疑的好处:

您在这里循环使用multitiff,一帧接一帧地选择。bm是这张(巨大的,6.5米)图像,在内存中。我对iTextSharp的内部图像处理知之甚少,但也许您可以在这里提供一个单页图像来帮助我?
您是否可以尝试创建一个所需大小的新位图,在其上绘制bm(查看图形对象的选项,以获取与速度相关的属性:例如InterpolationMode),并传入此单个图像,而不是每次调用的巨大对象?

将GetInstance方法参数修改为

GetInstance(bm, ImageFormat.Tiff) 
这可能会提高性能

iTextSharp.text.Image img =  iTextSharp.text.Image.GetInstance(bm, ImageFormat.Tiff);

问题在于iTextSharp完成处理System.Drawing.Image对象所需的时间太长

在我运行的一些测试中,要将速度提高到十分之一秒,您需要将选定的帧保存到内存流中,然后将数据的字节数组直接传递给iTextSharp中的GetInstance方法,请参见下文

bm.SelectActiveFrame(FrameDimension.Page, k);

iTextSharp.text.Image img;
using(System.IO.MemoryStream mem = new System.IO.MemoryStream())
{
    // This jumps all the inbuilt processing iTextSharp will perform
    // This will create a larger pdf though
    bm.Save(mem, System.Drawing.Imaging.ImageFormat.Png);
    img = iTextSharp.text.Image.GetInstance(mem.ToArray());
}

img.ScalePercent(72f / 200f * 100);

我不确定这个问题最初发布时提供了什么,但在将TIFF转换为PDF时,iText 5.x似乎提供了更多功能。在I和ha中还有一个基本代码示例
public static void AddTiff(Document pdfDocument, Rectangle pdfPageSize, String tiffPath)
{
    RandomAccessFileOrArray ra = new RandomAccessFileOrArray(tiffPath);
    int pageCount = TiffImage.GetNumberOfPages(ra);

    for (int i = 1; i <= pageCount; i++) 
    {
        Image img = TiffImage.GetTiffImage(ra, i);

        if (img.ScaledWidth > pdfPageSize.Width || img.ScaledHeight > pdfPageSize.Height)
        {
            if (img.DpiX != 0 && img.DpiY != 0 && img.DpiX != img.DpiY)
            {
                img.ScalePercent(100f);
                float percentX = (pdfPageSize.Width * 100) / img.ScaledWidth;
                float percentY = (pdfPageSize.Height * 100) / img.ScaledHeight;

                img.ScalePercent(percentX, percentY);
                img.WidthPercentage = 0;
            }
            else
            {
                img.ScaleToFit(pdfPageSize.Width, pdfPageSize.Height);
            }
        }

        Rectangle pageRect = new Rectangle(0, 0, img.ScaledWidth, img.ScaledHeight);

        pdfDocument.SetPageSize(pageRect);
        pdfDocument.SetMargins(0, 0, 0, 0);
        pdfDocument.NewPage();
        pdfDocument.Add(img);
    }
}
private static void CombineAndConvertTif(FileInfo inputFile, FileInfo outputFile)
    {
        Encoder myEncoder = Encoder.Quality;
        EncoderParameters myEncoderParameters = new EncoderParameters(1);
        EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
        myEncoderParameters.Param[0] = myEncoderParameter;
        ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);

        Console.Write("Converting {0} to {1}... ", inputFile.Name, outputFile.Name);
        Stopwatch sw = Stopwatch.StartNew();

        using (
            FileStream fs = new FileStream(
                outputFile.FullName, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
        {
            Document document = new Document(PageSize.A4, 50, 50, 50, 50);

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

            writer.CompressionLevel = 100;
            writer.SetFullCompression();

            document.Open();
            PdfContentByte cb = writer.DirectContent;

            using (Bitmap bm = new Bitmap(inputFile.FullName))
            {
                int pages = bm.GetFrameCount(FrameDimension.Page);

                for (int currentPage = 0; currentPage < pages; ++currentPage)
                {
                    bm.SelectActiveFrame(FrameDimension.Page, currentPage);
                    bm.SetResolution(96, 96);

                    Image img;
                    if (QualityMode == QualityMode.Slow)
                    {
                        #region Low speed, smaller files
                        img = iTextSharp.text.Image.GetInstance(bm, null, true);
                        #endregion
                    }
                    else
                    {
                        #region Fast speed, bigger files
                        using (MemoryStream mem = new MemoryStream())
                        {
                            bm.Save(mem, jgpEncoder, myEncoderParameters);
                            img = Image.GetInstance(mem.ToArray());
                        }
                        #endregion
                    }

                    img.ScalePercent(72f / 200f * 100);
                    img.SetAbsolutePosition(0, 0);

                    cb.AddImage(img);
                    document.NewPage();
                }
            }

            document.Close();
            writer.Close();
        }

        sw.Stop();
        Console.WriteLine(" time: {0}", sw.Elapsed);
    }
    internal enum QualityMode
{
    /// <summary>
    /// Process images quickly but
    /// produces bigger PDFs
    /// </summary>
    Fast,
    /// <summary>
    /// Process images slower but
    /// produces smaller PDFs
    /// </summary>
    Slow
}