Skip to main content
Version: API v3

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")