【问题标题】:Extract Image from a particular page in PDF从 PDF 中的特定页面提取图像
【发布时间】:2016-06-22 23:51:23
【问题描述】:

我想从 PDF 文件中提取图像。我尝试使用以下代码,它完美地从 PDF 中提取了 jpeg 图像。问题是如何从特定页面中提取图像,例如第 1 页或其他页面。我不想阅读整个 PDF 来搜索图片。

有什么建议吗?

图像提取代码:

private void List<System.Drawing.Image> ExtractImages(String PDFSourcePath)
        {
            List<System.Drawing.Image> ImgList = new List<System.Drawing.Image>();

            iTextSharp.text.pdf.RandomAccessFileOrArray RAFObj = null;
            iTextSharp.text.pdf.PdfReader PDFReaderObj = null;
            iTextSharp.text.pdf.PdfObject PDFObj = null;
            iTextSharp.text.pdf.PdfStream PDFStremObj = null;

            try
            {
                RAFObj = new iTextSharp.text.pdf.RandomAccessFileOrArray(PDFSourcePath);
                PDFReaderObj = new iTextSharp.text.pdf.PdfReader(RAFObj, null);

                for (int i = 0; i <= PDFReaderObj.XrefSize - 1; i++)
                {
                    PDFObj = PDFReaderObj.GetPdfObject(i);

                    if ((PDFObj != null) && PDFObj.IsStream())
                    {
                        PDFStremObj = (iTextSharp.text.pdf.PdfStream)PDFObj;
                        iTextSharp.text.pdf.PdfObject subtype = PDFStremObj.Get(iTextSharp.text.pdf.PdfName.SUBTYPE);

                        if ((subtype != null) && subtype.ToString() == iTextSharp.text.pdf.PdfName.IMAGE.ToString())
                        {
                            byte[] bytes = iTextSharp.text.pdf.PdfReader.GetStreamBytesRaw((iTextSharp.text.pdf.PRStream)PDFStremObj);

                            if ((bytes != null))
                            {
                                try
                                {
                                    System.IO.MemoryStream MS = new System.IO.MemoryStream(bytes);

                                    MS.Position = 0;
                                    System.Drawing.Image ImgPDF = System.Drawing.Image.FromStream(MS);
                                    pictureBox1.Image = ImgPDF;
                                    MS.Close();
                                    MS.Flush();

                                }
                                catch (Exception)
                                {

                                }
                            }
                        }
                    }
                }
                PDFReaderObj.Close();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }                
        }

【问题讨论】:

  • 这与手头的问题无关,但我想我会指出:throw new Exception(ex.Message); 不会重新抛出异常,而是创建一个新异常并导致堆栈丢失跟踪信息。只需使用throw;,除非这是您明确想要达到的效果。
  • @harriyott:你没有明白我的意思。我想指定它应该搜索图像的页码。
  • itextsharp extract images 的可能重复项
  • @ChrisHaas:先生,我只想指定要阅读的页码。现在它正在阅读完整的 PDF 并从中搜索图像。
  • @ChrisHaas: RAFObj = new iTextSharp.text.pdf.RandomAccessFileOrArray(PDFSourcePath); PDFReaderObj = new iTextSharp.text.pdf.PdfReader(RAFObj, null);在上面你可以看到它的阅读我只想知道一些指定页面的方法,以便它只阅读特定页面

标签: c# pdf itextsharp


【解决方案1】:

我目前没有可用的 iTextSharp 4.0,因此此代码针对 5.2,但它也应该适用于旧版本。此代码几乎是直接提升from this post here,因此请参阅该帖子以及更多问题的回复。正如我在上面的 cmets 中所说,您的代码正在从文档的角度查看所有图像,而我链接到的代码是逐页查看的。

请阅读另一篇文章中的所有 cmets,尤其是 this one,它解释说此 适用于 JPG 图像。 PDF 支持许多不同类型的图像,因此除非您知道您只处理 JPG,否则您需要添加大量代码。有关一些提示,请参阅 this postthis post

        string testFile = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Doc1.pdf");
        string outputPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        int pageNum = 1;

        PdfReader pdf = new PdfReader(testFile);
        PdfDictionary pg = pdf.GetPageN(pageNum);
        PdfDictionary res = (PdfDictionary)PdfReader.GetPdfObject(pg.Get(PdfName.RESOURCES));
        PdfDictionary xobj = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT));
        if (xobj == null) { return; }
        foreach (PdfName name in xobj.Keys) {
            PdfObject obj = xobj.Get(name);
            if (!obj.IsIndirect()) { continue; }
            PdfDictionary tg = (PdfDictionary)PdfReader.GetPdfObject(obj);
            PdfName type = (PdfName)PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE));
            if (!type.Equals(PdfName.IMAGE)) { continue; }
            int XrefIndex = Convert.ToInt32(((PRIndirectReference)obj).Number.ToString(System.Globalization.CultureInfo.InvariantCulture));
            PdfObject pdfObj = pdf.GetPdfObject(XrefIndex);
            PdfStream pdfStrem = (PdfStream)pdfObj;
            byte[] bytes = PdfReader.GetStreamBytesRaw((PRStream)pdfStrem);
            if (bytes == null) { continue; }
            using (System.IO.MemoryStream memStream = new System.IO.MemoryStream(bytes)) {
                memStream.Position = 0;
                System.Drawing.Image img = System.Drawing.Image.FromStream(memStream);
                if (!Directory.Exists(outputPath))
                    Directory.CreateDirectory(outputPath);

                string path = Path.Combine(outputPath, String.Format(@"{0}.jpg", pageNum));
                System.Drawing.Imaging.EncoderParameters parms = new System.Drawing.Imaging.EncoderParameters(1);
                parms.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Compression, 0);
                var jpegEncoder = ImageCodecInfo.GetImageEncoders().ToList().Find(x => x.FormatID == ImageFormat.Jpeg.Guid);
                img.Save(path, jpegEncoder, parms);

            }
        }

【讨论】:

  • 嗨,谢谢,您的解决方案对我有帮助,但在一个 pdf xobj.Keys 中返回每个页面的所有页面的所有图像。你知道为什么吗?
【解决方案2】:

以下是我用来从 PDF 中提取图像的代码。它对我来说完全没问题。

//   Required: iTextSharp.dll

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using iTextSharp.text.pdf.parser;
using Dotnet = System.Drawing.Image;
using iTextSharp.text.pdf;

namespace PDF_Parsing {
    partial class ExtractPdfImage
    {
        string imgPath = @"c:\extractedImg.png";
        private void ExtractImage(string pdfFile)
        {
            const int pageNumber = 1;
            PdfReader pdf = new PdfReader(pdfFile);
            PdfDictionary pg = pdf.GetPageN(pageNumber);
            PdfDictionary res =               (PdfDictionary)PdfReader.GetPdfObject(pg.Get(PdfName.RESOURCES));
            PdfDictionary xobj = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT));
            foreach (PdfName name in xobj.Keys)
            {
                PdfObject obj = xobj.Get(name);
                if (obj.IsIndirect())
                {
                    PdfDictionary tg = (PdfDictionary)PdfReader.GetPdfObject(obj);
                    string width = tg.Get(PdfName.WIDTH).ToString();
                    string height = tg.Get(PdfName.HEIGHT).ToString();
                    ImageRenderInfo imgRI = ImageRenderInfo.CreateForXObject(new   Matrix(float.Parse(width), float.Parse(height)),
                        (PRIndirectReference)obj, tg);
                    RenderImage(imgRI);
                }
            }
        }

        private void RenderImage(ImageRenderInfo renderInfo)
        {
            PdfImageObject image = renderInfo.GetImage();
            using (Dotnet dotnetImg = image.GetDrawingImage())
            {
                if (dotnetImg != null)
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        dotnetImg.Save(ms, ImageFormat.Tiff);
                        Bitmap d = new Bitmap(dotnetImg);
                        d.Save(imgPath);
                    }
                }
            }
        }
    }
}

【讨论】:

  • 我已经尝试过这种方法并且我得到了一个图像,但是由于某种原因它被扭曲了(好像位图的字节流输出到不同宽度的位图)。有什么想法吗?
【解决方案3】:

以下代码可以很好地从特定页面提取图像。

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using iTextSharp.text.pdf.parser;
using Dotnet = System.Drawing.Image;
using iTextSharp.text.pdf;
namespace PDF_Parsing
{
  partial class PDF_ImgExtraction
  {
    string imgPath;
    private void ExtractImage(string pdfFile)
    {
      const int pageNumber = 1;//Page number to extract the image from
      PdfReader pdf = new PdfReader(pdfFile);
      PdfDictionary pg = pdf.GetPageN(pageNumber);
      PdfDictionary res = (PdfDictionary)PdfReader.GetPdfObject(pg.Get(PdfName.RESOURCES));
      PdfDictionary xobj = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT));
      foreach (PdfName name in xobj.Keys)
      {
        PdfObject obj = xobj.Get(name);
        if (obj.IsIndirect())
        {
          PdfDictionary tg = (PdfDictionary)PdfReader.GetPdfObject(obj);
          string width = tg.Get(PdfName.WIDTH).ToString();
          string height = tg.Get(PdfName.HEIGHT).ToString();
          ImageRenderInfo imgRI = ImageRenderInfo.CreateForXObject(new Matrix(float.Parse(width), float.Parse(height)), (PRIndirectReference)obj, tg);
          RenderImage(imgRI);
        }
      }
    }
    private void RenderImage(ImageRenderInfo renderInfo)
    {
      PdfImageObject image = renderInfo.GetImage();
      using (Dotnet dotnetImg = image.GetDrawingImage())
      {
        if (dotnetImg != null)
        {
          using (MemoryStream ms = new MemoryStream())
          {
            dotnetImg.Save(ms, ImageFormat.Tiff);
            Bitmap d = new Bitmap(dotnetImg);
            d.Save(imgPath);
          }
        }
      }
    }
  }
}

【讨论】:

    猜你喜欢
    • 2015-08-24
    • 2021-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-05
    • 2012-06-28
    • 2011-01-29
    相关资源
    最近更新 更多