To ask a more specific question: Here is a function adapted from the oft-repeated sample code parsing through all of the images in a PDF. Assume that I have already converted the images to JPG (another issue that is a separate question regarding the ExportToImage function and non-JPG images), so all I have to do is read the replacement files from disk and insert them in the right places. For example, a 20-page document that is just scanned paper pages.
The following code does that, and applies the changes to the xObject.Elements that matches what is in the PDF if it was created with JPG images. However, when I open the resulting PDF, I get the message "An error exists on this page. Acrobat may not display the page correctly", and all the pages are blank. The PDF file size looks like it has the right data (it's reduced from 22 mb to 3mb, matching one converted through other desktop applications) but it will not display. I'm assuming there are other steps to correct either the xObject or a Resources entry. Any ideas?
Code:
private static void ProcessImagesPDFSharp()
{
PdfDocument pdf = PdfReader.Open(@"test\test.pdf");
int imageCount = 0;
// Iterate pages
foreach (PdfPage page in pdf.Pages)
{
// Get resources dictionary
PdfDictionary resources = page.Elements.GetDictionary("/Resources");
if (resources != null)
{
// Get external objects dictionary
PdfDictionary xObjects = resources.Elements.GetDictionary("/XObject");
if (xObjects != null)
{
ICollection<PdfItem> items = xObjects.Elements.Values;
// Iterate references to external objects
foreach (PdfItem item in items)
{
PdfReference reference = item as PdfReference;
if (reference != null)
{
PdfDictionary xObject = reference.Value as PdfDictionary;
// Is external object an image?
if (xObject != null && xObject.Elements.GetString("/Subtype") == "/Image")
{
// Replace this object with a JPG file
xObject.Stream.Value = File.ReadAllBytes($@"test\page {++imageCount}.jpg").ToArray();
xObject.Elements.SetValue("/Length", new PdfInteger(xObject.Stream.Value.Length));
xObject.Elements.SetValue("/ColorSpace", new PdfString("/DeviceRGB"));
xObject.Elements.SetValue("/Filter", new PdfString("/DCTDecode"));
xObject.Elements.SetValue("/Type", new PdfString("/XObject"));
xObject.Elements.Remove("/DecodeParams");
}
}
}
}
}
}
pdf.Save(@"test\out.pdf");
}