How to replace raster images on a PDF page without creating a new page and copying all the elements over?

Q:
Is there a way to replace a raster image in a PDF document without
creating a new page and copying all the elements over?

For example, I would like to do something similar to:

ElementReader page_reader = new ElementReader();
page_reader.Begin( page );
Element element;
while ((element = page_reader.Next()) != null)
{
      if (element.GetType() == Element.Type.e_image)
       {
             //replace this image with another image
       }
}

I can current do this by creating a new page and copying all the
elements over, replacing any image elements with another image. But
is there a way to "reassign" the element instead so that I don't have
to recreate a new page (I would assume that this would save some
time)? The hope would be to dynamically change the raster images
within a pdf::Page depending on where in the PDF I'm viewing and the
zoom level/DPI. What I'm try to do is relacing all high-resolution
images in the PDF with a lower resolution image.
----
A:

Yes, using PDFNet API you can replace/swap all images on an existing
page without touching the page content stream (i.e. without having to
create a new page copy ever elements, delete the old page, etc.).

You can access all image XObjects used on the page through page
resource dictionary (page.GetResources()):

SDF.Obj res = page.GetResources();
if (res != null) {
  SDF.Obj images = res.FindObj("XObject")
  if (images != null) {
    SDF.DictInterator itr = images.DictBegin();
    SDF.DictInterator end = images.DictEnd();
    for (; itr!=end; itr.Next()) {
       Obj image = itr.Value() // (C++; in C#/VB use itr.Value())
       // check is the XObject is image or a form ... we are looking
for images only
       Obj subtype = image.FindObj("Subtype")
       if (subtype.GetName() == "Image") { // We have an image
          pdftron.PDF.Image old_img = new pdftron.PDF.Image(image);
          // or in C++ ... Image old_img(image);
         pdftron.PDF.Image replacement_img = ... resample the old
image or get a new image

          ... now replace the old image with a new one

image.GetDoc().Swap(image.GetObjNum(),replacement_img.GetObjNum());
         // that's it!
       }
...

Q:

Thanks!!! This is exactly what I was looking for. I had to make some
changes to the code (GetResources and FindObj no longer exist), but I
was able to make it work. You guys rock.

A few questions:
While iterating through the images, can I store all the image
"pointers" that I find for later use? That way, if I want to resize
the images and redraw the page again, I can just use my collection of
"pointers" instead of searching through the PDF page. I'm using C# if
that matters. It seems that the time to search for images is pretty
quick, so I don't know if this would even be necessary.

Will changing the raster images in the PDF (after calling
PDFDraw::GetBitmap) affect the caching that PDFDraw uses (I'm assuming
that it does image caching). If I were to call PdfDraw::GetBitmap,
would it know that the images have changed (I'm assuming that PdfDraw
does some type of image caching).
---

A:

While iterating through the images, can I store all the image "pointers"
that I find for later use?

Yes, you can keep a list of pointers to image objects (actually
pdftron.SDF.Obj-s which you can obtain using image.GetSDFObj()). You
can always instantiate a high-level image object from image SDF.Obj as
follwos:

// C++
Image myimage(image_sdf_obj);

// C#
Image myimage = new Image(image_sdf_obj);

These pointers are valid as long as PDFDoc is open.

It seems that the time to search for images is pretty quick,
so I don't know if this would even be necessary.

You are probably right. The search is quick enough that any
optimizations are probably not necessary.

Will changing the raster images in the PDF (after calling PDFDraw::GetBitmap)
affect the caching that PDFDraw uses

This depends on when you are replacing images. If you replace images
before creating PDFDraw object you should be fine. To be on the safe
side you can also disable caching (pdfdraw.SetCaching(false)).