Skip to main content
Version: API v2 Preview

Working with Images

Select images at document or page scope, by collection or coordinates. Singular selectors return the language's empty-result type; plural selectors return a collection.

Complete image-replacement workflow

Download images.pdf as input.pdf and replacement-logo.png into the same directory. The program replaces the first image and saves output.pdf.

from pathlib import Path
from pdfdancer import PDFDancer

with PDFDancer.open(Path("input.pdf")) as pdf:
images = pdf.select_images()
if not images:
raise RuntimeError("The sample image was not found")
result = images[0].replace_from_file(Path("replacement-logo.png"))
if not result.success:
raise RuntimeError(result.message)
pdf.save("output.pdf")

Open output.pdf and confirm that the original image was replaced. The remaining examples assume an open pdf session.

Select and inspect images

all_images = pdf.select_images()
page_images = pdf.page(1).select_images()
near_point = pdf.page(1).select_images_at(72, 700, tolerance=1.0)
image = pdf.page(1).select_image_at(72, 700, tolerance=1.0)
if image is not None:
print(image.width, image.height, image.aspect_ratio, image.page_number)

Add images

Use the image builder at document scope with an explicit one-based page, or use a page-scoped builder. Supply an image file and PDF coordinates before calling the terminal add operation.

from pathlib import Path

if not pdf.new_image().from_file(Path("logo.png")).at(1, 72, 700).add():
raise RuntimeError("Document-scoped image add failed")
if not pdf.page(2).new_image().from_file(Path("seal.png")).at(72, 80).add():
raise RuntimeError("Page-scoped image add failed")

Transformation methods return CommandResult; check success, message, warning, and the affected element identifier. Positive image rotation angles are clockwise.

Replace an image

Replacement keeps the selected image object's placement while changing its image data.

from pathlib import Path

image = pdf.page(1).select_image_at(72, 700, tolerance=1.0)
if image is None:
raise RuntimeError("Image not found")
result = image.replace_from_file(Path("new-logo.png"))
if not result.success:
raise RuntimeError(result.message)

Scale, rotate, and move

Choose one transformation, check its result, then select the image again before calculations that depend on current bounds.

# Scale by a factor.
result = image.scale(0.5)

# Or scale to a box in PDF points.
result = image.scale_to(180, 60, preserve_aspect_ratio=True)

# Or rotate clockwise and move to new PDF coordinates.
result = image.rotate(90)
moved = image.move_to(144, 650)

if not result.success or not moved:
raise RuntimeError(result.message)

The alternatives above illustrate individual methods; do not apply all of them in sequence unless that combined transformation is intended.

Crop, opacity, flipping, and pixel-region fill

Crop and fill-region dimensions are image pixels, not PDF page points. Opacity ranges from 0.0 (transparent) to 1.0 (opaque).

from pdfdancer import Color

crop_result = image.crop(left=10, top=5, right=10, bottom=5)
opacity_result = image.set_opacity(0.75)
flip_result = image.flip_horizontal()
fill_result = image.fill_region(0, 0, 40, 20, Color(255, 255, 255))

for result in (crop_result, opacity_result, flip_result, fill_result):
if not result.success:
raise RuntimeError(result.message)

These calls are shown together to document their parameters. For production edits, select the image again between transformations when current dimensions or coordinates influence the next operation.

Clipping

An image can remain visually clipped after moving because its clipping path is an independent PDF graphics-state constraint. Use clearClipping only when removing that constraint is intended, then inspect the rendered output.

if not image.clear_clipping():
raise RuntimeError("Image clipping could not be cleared")

Deletion

Delete the selected typed image rather than relying on its previous coordinates after other transformations. Re-run the selector if the workflow may have changed its identity or position.

if not image.delete():
raise RuntimeError("Image deletion failed")