Extrae la imagen del PDF usando itextsharp

Estoy tratando de extraer todas las imágenes de un pdf usando itextsharp, pero no puedo superar este obstáculo.

El error se produce en la línea System.Drawing.Image ImgPDF = System.Drawing.Image.FromStream(MS); dando un error de “El parámetro no es válido”.

Creo que funciona cuando la imagen es un bitmap pero no de otro formato.

Tengo este código siguiente: perdón por la longitud;

  private void Form1_Load(object sender, EventArgs e) { FileStream fs = File.OpenRead(@"reader.pdf"); byte[] data = new byte[fs.Length]; fs.Read(data, 0, (int)fs.Length); List ImgList = new List(); 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(data); 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); ImgList.Add(ImgPDF); } catch (Exception) { } } } } } PDFReaderObj.Close(); } catch (Exception ex) { throw new Exception(ex.Message); } } //Form1_Load 

He usado esta biblioteca en el pasado sin ningún problema.

http://www.winnovative-software.com/PdfImgExtractor.aspx

 private void btnExtractImages_Click(object sender, EventArgs e) { if (pdfFileTextBox.Text.Trim().Equals(String.Empty)) { MessageBox.Show("Please choose a source PDF file", "Choose PDF file", MessageBoxButtons.OK); return; } // the source pdf file string pdfFileName = pdfFileTextBox.Text.Trim(); // start page number int startPageNumber = int.Parse(textBoxStartPage.Text.Trim()); // end page number // when it is 0 the extraction will continue up to the end of document int endPageNumber = 0; if (textBoxEndPage.Text.Trim() != String.Empty) endPageNumber = int.Parse(textBoxEndPage.Text.Trim()); // create the PDF images extractor object PdfImagesExtractor pdfImagesExtractor = new PdfImagesExtractor(); pdfImagesExtractor.LicenseKey = "31FAUEJHUEBQRl5AUENBXkFCXklJSUlQQA=="; // the demo output directory string outputDirectory = Path.Combine(Application.StartupPath, @"DemoFiles\Output"); Cursor = Cursors.WaitCursor; // set the handler to be called when an image was extracted pdfImagesExtractor.ImageExtractedEvent += pdfImagesExtractor_ImageExtractedEvent; try { // start images counting imageIndex = 0; // call the images extractor to raise the ImageExtractedEvent event when an images is extracted from a PDF page // the pdfImagesExtractor_ImageExtractedEvent handler below will be executed for each extracted image pdfImagesExtractor.ExtractImagesInEvent(pdfFileName, startPageNumber, endPageNumber); // Alternatively you can use the ExtractImages() and ExtractImagesToFile() methods // to extracted the images from a PDF document in memory or to image files in a directory // uncomment the line below to extract the images to an array of ExtractedImage objects //ExtractedImage[] pdfPageImages = pdfImagesExtractor.ExtractImages(pdfFileName, startPageNumber, endPageNumber); // uncomment the lines below to extract the images to image files in a directory //string outputDirectory = System.IO.Path.Combine(Application.StartupPath, @"DemoFiles\Output"); //pdfImagesExtractor.ExtractImagesToFile(pdfFileName, startPageNumber, endPageNumber, outputDirectory, "pdfimage"); } catch (Exception ex) { // The extraction failed MessageBox.Show(String.Format("An error occurred. {0}", ex.Message), "Error"); return; } finally { // uninstall the event handler pdfImagesExtractor.ImageExtractedEvent -= pdfImagesExtractor_ImageExtractedEvent; Cursor = Cursors.Arrow; } try { System.Diagnostics.Process.Start(outputDirectory); } catch (Exception ex) { MessageBox.Show(string.Format("Cannot open output folder. {0}", ex.Message)); return; } } ///  /// The ImageExtractedEvent event handler called after an image was extracted from a PDF page. /// The event is raised when the ExtractImagesInEvent() method is used ///  /// The handler argument containing the extracted image and the PDF page number void pdfImagesExtractor_ImageExtractedEvent(ImageExtractedEventArgs args) { // get the image object and page number from even handler argument Image pdfPageImageObj = args.ExtractedImage.ImageObject; int pageNumber = args.ExtractedImage.PageNumber; // save the extracted image to a PNG file string outputPageImage = Path.Combine(Application.StartupPath, @"DemoFiles\Output", "pdfimage_" + pageNumber.ToString() + "_" + imageIndex++ + ".png"); pdfPageImageObj.Save(outputPageImage, ImageFormat.Png); args.ExtractedImage.Dispose(); } 

Resuelto…

Incluso obtuve la misma excepción de “El parámetro no es válido” y después de tanto trabajo con la ayuda del enlace proporcionado por der_chirurg (http://kuujinbo.info/iTextSharp/CCITTFaxDecodeExtract.aspx) lo resolví y lo siguiente es código:

 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) { PdfReader pdfReader = new PdfReader(files[fileIndex]); for (int pageNumber = 1; pageNumber <= pdfReader.NumberOfPages; pageNumber++) { 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); } } } } } } 

Debe verificar el / filtro de la secuencia para ver qué formato de imagen utiliza una imagen determinada. Puede ser un formato de imagen estándar:

  • DCTDecode (jpeg)
  • JPXDecode (jpeg 2000)
  • JBIG2Decode (jbig es un formato solo B & W)
  • CCITTFaxDecode (formato de fax, PDF admite grupos 3 y 4)

Aparte de eso, necesitará obtener los bytes sin formato (como usted) y crear una imagen utilizando el ancho, altura, bits por componente, cantidad de componentes del color de la secuencia de imagen (podría ser CMYK, indexado, RGB o Algo) Weird), y algunos otros, como se define en la sección 8.9 de la especificación ISO PDF (disponible de forma gratuita).

Entonces, en algunos casos, su código funcionará, pero en otros fallará con la excepción que mencionó.

PD: cuando tienes una excepción, POR FAVOR incluye el seguimiento de la stack cada vez. ¿Por favor, con azúcar en la parte superior?

En la versión más nueva de iTextSharp, el primer parámetro de ImageRenderInfo.CreateForXObject ya no es Matrix sino GraphicsState . El enfoque de @ der_chirurg debería funcionar. Me probé con la información del siguiente enlace y funcionó muy bien:

http://www.thevalvepage.com/swmonkey/2014/11/26/extract-images-from-pdf-files-using-itextsharp/

Para extraer todas las imágenes en todas las páginas, no es necesario implementar filtros diferentes. iTextSharp tiene un Renderer de imagen, que guarda todas las imágenes en su tipo de imagen original.

Simplemente haz lo siguiente aquí: http://kuujinbo.info/iTextSharp/CCITTFaxDecodeExtract.aspx No necesitas implementar HttpHandler …

Agregué la biblioteca en github, que extrae imágenes en PDF y las comprime.

Podría ser útil cuando comiences a jugar con la biblioteca ITextSharp muy poderosa.

Aquí el enlace: https://github.com/rock-walker/PdfCompression

Esto funciona para mí y creo que es una solución simple:

Escribe un RenderListener personalizado e implementa su método RenderImage, algo como esto

  public void RenderImage(ImageRenderInfo info) { PdfImageObject image = info.GetImage(); Parser.Matrix matrix = info.GetImageCTM(); var fileType = image.GetFileType(); ImageFormat format; switch (fileType) {//you may add more types here case "jpg": case "jpeg": format = ImageFormat.Jpeg; break; case "pnt": format = ImageFormat.Png; break; case "bmp": format = ImageFormat.Bmp; break; case "tiff": format = ImageFormat.Tiff; break; case "gif": format = ImageFormat.Gif; break; default: format = ImageFormat.Jpeg; break; } var pic = image.GetDrawingImage(); var x = matrix[Parser.Matrix.I31]; var y = matrix[Parser.Matrix.I32]; var width = matrix[Parser.Matrix.I11]; var height = matrix[Parser.Matrix.I22]; if (x <  && y < ) { return;//ignore these images } pic.Save(, format); }