代码之家  ›  专栏  ›  技术社区  ›  Nickso

使用itextsharpes压缩pdf图像会导致内存不足

  •  1
  • Nickso  · 技术社区  · 6 年前

    我把代码放在这个线程中: PDF Compression with iTextSharp

    im有一个异常“内存不足”,pdf im处理有47个图像,每个图像的权重不同,使pdf为16.5mb。

    代码相同:

    public void ReduceResolution(PdfReader reader, long quality)
    {
        int n = reader.XrefSize;
        for (int i = 0; i < n; i++)
        {
            PdfObject obj = reader.GetPdfObject(i);
            if (obj == null || !obj.IsStream()) { continue; }
    
            PdfDictionary dict = (PdfDictionary)PdfReader.GetPdfObject(obj);
            PdfName subType = (PdfName)PdfReader.GetPdfObject(
              dict.Get(PdfName.SUBTYPE)
            );
            if (!PdfName.IMAGE.Equals(subType)) { continue; }
    
            PRStream stream = (PRStream)obj;
            try
            {
                PdfImageObject image = new PdfImageObject(stream);
                PdfName filter = (PdfName)image.Get(PdfName.FILTER);
                if (
                  PdfName.JBIG2DECODE.Equals(filter)
                  || PdfName.JPXDECODE.Equals(filter)
                  || PdfName.CCITTFAXDECODE.Equals(filter)
                  || PdfName.FLATEDECODE.Equals(filter)
                ) continue;
    
                System.Drawing.Image img = image.GetDrawingImage();
                if (img == null) continue;
    
                var ll = ImageToByteArray(img);
                int width = img.Width;
                int height = img.Height;
                using (System.Drawing.Bitmap dotnetImg =
                   new System.Drawing.Bitmap(img))
                {
                    // set codec to jpeg type => jpeg index codec is "1"
                    System.Drawing.Imaging.ImageCodecInfo codec =
                    System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[1];
                    // set parameters for image quality
                    System.Drawing.Imaging.EncoderParameters eParams =
                     new System.Drawing.Imaging.EncoderParameters(1);
                    eParams.Param[0] =
                     new System.Drawing.Imaging.EncoderParameter(
                       System.Drawing.Imaging.Encoder.Quality, quality
                    );
                    using (MemoryStream msImg = new MemoryStream())
                    {
                        dotnetImg.Save(msImg, codec, eParams);
                        msImg.Position = 0;
                        stream.SetData(msImg.ToArray());
                        stream.SetData(
                         msImg.ToArray(), false, PRStream.BEST_COMPRESSION
                        );
                        stream.Put(PdfName.TYPE, PdfName.XOBJECT);
                        stream.Put(PdfName.SUBTYPE, PdfName.IMAGE);
                        stream.Put(PdfName.FILTER, filter);
                        stream.Put(PdfName.FILTER, PdfName.DCTDECODE);
                        stream.Put(PdfName.WIDTH, new PdfNumber(width));
                        stream.Put(PdfName.HEIGHT, new PdfNumber(height));
                        stream.Put(PdfName.BITSPERCOMPONENT, new PdfNumber(8));
                        stream.Put(PdfName.COLORSPACE, PdfName.DEVICERGB);
                    }
                }
            }
            catch(Exception ex)
            {
                // throw ex;
                // iText[Sharp] can't handle all image types...
            }
            finally
            {
                // may or may not help      
                reader.RemoveUnusedObjects();
            }
        }
    }
    

    它发生在第一个映像之后,第二个映像似乎是x个足够大的字节,导致异常。

    有什么方法可以避免这种类型的错误,是什么导致的?

    0 回复  |  直到 6 年前