Extract image from PDF using itextsharp

In newer version of iTextSharp, the 1st parameter of ImageRenderInfo.CreateForXObject is not Matrix anymore but GraphicsState. @der_chirurg's approach should work. I tested myself with the information from the following link and it worked beautifully:

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


Resolved...

Even I got the same exception of "Parameter is not valid" and after so much of work with the help of the link provided by der_chirurg (http://kuujinbo.info/iTextSharp/CCITTFaxDecodeExtract.aspx ) I resolved it and following is the code:

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);
                    }
                }
            }
        }
    }
}

You need to check the stream's /Filter to see what image format a given image uses. It may be a standard image format:

  • DCTDecode (jpeg)
  • JPXDecode (jpeg 2000)
  • JBIG2Decode (jbig is a B&W only format)
  • CCITTFaxDecode (fax format, PDF supports group 3 and 4)

Other than that, you'll need to get the raw bytes (as you are), and build an image using the image stream's width, height, bits per component, number of color components (could be CMYK, indexed, RGB, or Something Weird), and a few others, as defined in section 8.9 of the ISO PDF SPECIFICATION (available for free).

So in some cases your code will work, but in others, it'll fail with the exception you mentioned.

PS: When you have an exception, PLEASE include the stack trace every single time. Pretty please with sugar on top?


Works for me like this, using these two methods:

    public static List<System.Drawing.Image> ExtractImagesFromPDF(byte[] bytes)
    {
        var imgs = new List<System.Drawing.Image>();
        var pdf = new PdfReader(bytes);

        try
        {
            for (int pageNumber = 1; pageNumber <= pdf.NumberOfPages; pageNumber++)
            {
                PdfDictionary pg = pdf.GetPageN(pageNumber);
                List<PdfObject> objs = FindImageInPDFDictionary(pg);

                foreach (var obj in objs)
                {
                    if (obj != null)
                    {
                        int XrefIndex = Convert.ToInt32(((PRIndirectReference)obj).Number.ToString(System.Globalization.CultureInfo.InvariantCulture));
                        PdfObject pdfObj = pdf.GetPdfObject(XrefIndex);
                        PdfStream pdfStrem = (PdfStream)pdfObj;
                        var pdfImage = new PdfImageObject((PRStream)pdfStrem);
                        var img = pdfImage.GetDrawingImage();

                        imgs.Add(img);
                    }
                }
            }
        }
        finally
        {
            pdf.Close();
        }

        return imgs;
    }

    private static List<PdfObject> FindImageInPDFDictionary(PdfDictionary pg)
    {
        var res = (PdfDictionary)PdfReader.GetPdfObject(pg.Get(PdfName.RESOURCES));
        var xobj = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT));
        var pdfObgs = new List<PdfObject>();

        if (xobj != null)
        {
            foreach (PdfName name in xobj.Keys)
            {
                PdfObject obj = xobj.Get(name);
                if (obj.IsIndirect())
                {
                    var tg = (PdfDictionary)PdfReader.GetPdfObject(obj);
                    var type = (PdfName)PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE));

                    if (PdfName.IMAGE.Equals(type)) // image at the root of the pdf
                    {
                        pdfObgs.Add(obj);
                    }
                    else if (PdfName.FORM.Equals(type)) // image inside a form
                    {
                        FindImageInPDFDictionary(tg).ForEach(o => pdfObgs.Add(o));
                    }
                    else if (PdfName.GROUP.Equals(type)) // image inside a group
                    {
                        FindImageInPDFDictionary(tg).ForEach(o => pdfObgs.Add(o));
                    }
                }
            }
        }

        return pdfObgs;
    }