2

Since I did not get an answer to my previous question (looking for some s/w to strip all images from a PDF file), I have decided to code it myself.

Can anyone recommend a VCL component to help me?

Something to open, manipulate & save PDF files. As a bonus, something that can search & find the next image.


[Update] the original question states that I want to strip all images from a PDF file. I forgot to post that here. Sorry.

Any other PDF manipulation features are a bonus.

@Izzy - VCL (for which I created a new tag, so that vampire cheerleaders know what I am talking about), implies Embarcadero Delphi, or C++ Studio, or RAD studio, which contains both. Language is, perforce, Delphi or Embaradero C++ and o/s is Windows.

1
  • 2
    A bit broad, don't you think? "Something to open, manipulate & save PDF files". What kind of manipulations? A simple PDF splitter for AmigaOS would match this description as well as a full-fledged PDF editor for Linux (read between the lines: OS is missing as well ;). Oh: VCL, I see. Vampire CheerLeaders isn't it – so I guess it should mean Visual Component Library. So what language?
    – Izzy
    Commented Apr 20, 2015 at 9:26

2 Answers 2

2

You have 2 options:
1. Replace the images with a single 1*1 pixels white image. The code below shows how to implement this:

public class ImageReplacer
{
    public static void Run2()
    {
        // Create the replacement image
        PdfRawImage img = new PdfRawImage(new MemoryStream(new byte[] { 255 }));
        img.Width = img.Height = 1;
        img.ColorSpace = new PdfGrayColorSpace();
        img.BitsPerComponent = 8;

        // Load the document
        PdfFixedDocument document = new PdfFixedDocument("Sample.pdf");

        for (int i = 0; i < document.Pages.Count; i++)
        {
            PdfCosDictionary pageDictionary = document.Pages[i].CosDictionary;
            // Get the page resources dictionary
            PdfCosDictionary resourcesDictionary = pageDictionary["/Resources"] as PdfCosDictionary;
            // Replaces images in the resources
            ReplaceImagesInResources(resourcesDictionary, img);
        }

        document.Save("Sample_ReplaceImages.pdf");
    }

    private static void ReplaceImagesInResources(PdfCosDictionary cosResourcesDictionary, PdfRawImage newImage)
    {
        if (cosResourcesDictionary == null)
        {
            return;
        }

        PdfCosDictionary cosXObjectResDictionary = cosResourcesDictionary["/XObject"] as PdfCosDictionary;
        if (cosXObjectResDictionary != null)
        {
            string[] imageIDs = cosXObjectResDictionary.Keys;
            foreach (string imageID in imageIDs)
            {
                PdfCosDictionary cosXObject = cosXObjectResDictionary[imageID] as PdfCosDictionary;
                if (cosXObject != null)
                {
                    PdfCosName cosSubtype = cosXObject["/Subtype"] as PdfCosName;
                    if (cosSubtype != null)
                    {
                        if (cosSubtype.Value == "/Image")
                        {
                            // Replace image in resources dictionary with new white image.
                            cosXObjectResDictionary[imageID] = newImage.CosDictionary;
                        }
                        else
                        {
                            ReplaceImagesInResources(cosXObject["/Resources"] as PdfCosDictionary, newImage);
                        }
                    }
                }
            }
        }

        PdfCosDictionary cosPatternResDictionary = cosResourcesDictionary["/Pattern"] as PdfCosDictionary;
        if (cosPatternResDictionary != null)
        {
            string[] patternIDs = cosPatternResDictionary.Keys;
            foreach (string patternID in patternIDs)
            {
                PdfCosDictionary cosPattern = cosPatternResDictionary[patternID] as PdfCosDictionary;
                if (cosPattern != null)
                {
                    ReplaceImagesInResources(cosPattern["/Resources"] as PdfCosDictionary, newImage);
                }
            }
        }
    }
}

The problem with the above approach is that is does not remove the images embedded in the content stream and if an image has a softmask that makes it transparent, after replacement it will be opaque and possibly cover some content.

2. Remove the images from the document including the image references from the page content stream. The code below shows how to implement it:

public class ImageRemover
{
    public static void Main()
    {
        PdfFixedDocument document = new PdfFixedDocument("Sample.pdf");

        PdfReplaceImageTransform removeImageTransform = new PdfReplaceImageTransform();
        removeImageTransform.ReplaceImage += new EventHandler<PdfReplaceImageEventArgs>(HandleRemoveImage);
        for (int i = 0; i < document.Pages.Count; i++)
        {
            PdfPageTransformer pageTransformer = new PdfPageTransformer(document.Pages[i]);
            pageTransformer.ApplyTransform(removeImageTransform);
        }
        removeImageTransform.ReplaceImage -= new EventHandler<PdfReplaceImageEventArgs>(HandleRemoveImage);

        document.Save("Sample_RemoveImages.pdf");
    }

    private static void HandleRemoveImage(object sender, PdfReplaceImageEventArgs e)
    {
        // Set the new image to null to remove it.
        e.NewImage = null;
    }
}

The code above is implemented using the XFINIUM.PDF library (I work for the company that develops it) and it can run on any .NET, Mono and Xamarin platform.

2

Please take a look at this question on StackOverflow: PDF Convert to Black And White PNGs.

In the first step of my answer to this question, I explain how to find images on a page. In the third stap, I show how to replace such an image with another image. You could use this to replace the actual images with a white image (a 1 by 1 pixel image would be sufficient).

If you really want to remove the images (if white images aren't allowed), then you can throw away the Image XObjects, but in that case you have to remove all of the references to the removed images from the content stream of each page. That's possible with iText (Java) or iTextSharp (C#) too, but it is less trivial.

1
  • That's a long & complex/complete answer, which I will have to study in detail, but it looks very promising (+1). If replacing the image is easier than deleting it, can I replace it with a1x1 pixel white image, or must it remain the same size?
    – Mawg
    Commented Apr 21, 2015 at 6:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.