# Pdfium Impl Page Objects Edit

> Use when adding, removing, transforming, or relocating page objects on a PDF page with pdfium-render: stamping an image, drawing a path, scaling or rotating an object with a PdfMatrix, or moving an object to another page. Prevents the borrow-checker fight that naive remove-then-insert object moving causes, the double-add bug from calling both a create_ and an add_ method, and reaching for the set_matrix and copy_onto_new_page names that were removed in 0.9.0. Covers PdfPageObjects create_ and add_ and remove_ methods, PdfPageImageObject constructors, PdfMatrix transforms, apply_matrix, PdfPageGroupObject, and copy_to_page / move_to_page across pdfium-render 0.8.x and 0.9.x. Keywords: pdfium-render page objects, PdfPageObjects, add_image_object, create_image_object, create_path_object_bezier, remove_object, PdfPageImageObject, new_from_jpeg_file, apply_matrix, PdfMatrix, transform, PdfPageGroupObject, copy_to_page, move_to_page, set_matrix removed, copy_onto_new_page removed, objects_mut, stamp image on PDF, d

- Skill: `impertio-studio/pdfium-impl-page-objects-edit` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add impertio-studio/pdfium-impl-page-objects-edit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/impertio-studio/pdfium-impl-page-objects-edit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- License: MIT
- Author: Impertio-Studio (https://skillmd.com/u/impertio-studio)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/impertio-studio/pdfium-impl-page-objects-edit

---


# pdfium-impl-page-objects-edit

## What this skill covers

A PDF page holds a collection of page objects: text, path, image, shading, and
XObject form objects. This skill covers MUTATING that collection: creating
objects, adding and removing them, transforming them with a `PdfMatrix`, and
relocating them between pages with `PdfPageGroupObject` and the
`copy_to_page` / `move_to_page` methods.

For reading and inspecting existing page objects see
`pdfium-syntax-page-objects`. For copying whole pages between documents see
`pdfium-impl-multi-page`. For `PdfPoints` and coordinate geometry see
`pdfium-core-coordinates`. Default API surface here is 0.9.x.

## Quick reference

| Goal | Call |
|------|------|
| Get a mutable collection | `page.objects_mut()` |
| Create and add an image in one step | `objects.create_image_object(x, y, &image, w, h)` |
| Create and add a bezier path | `objects.create_path_object_bezier(...)` |
| Build a detached image object | `PdfPageImageObject::new(&document, &image)` |
| Attach a detached object | `objects.add_image_object(obj)` / `add_path_object(obj)` |
| Remove an object | `objects.remove_object(obj)` / `remove_object_at_index(i)` |
| Transform an object | `object.apply_matrix(matrix)` |
| Relocate an object | `object.copy_to_page(&mut page)` / `move_to_page(&mut page)` |

ALWAYS call `objects_mut()` to mutate. `objects()` returns an immutable
`&PdfPageObjects`; the `create_`, `add_`, and `remove_` methods all take
`&mut self` and will not compile against it.

## Two ways to create an object

`pdfium-render` offers two distinct construction styles. NEVER mix them for the
same object.

### Style A : `create_*` (build and add in one call)

The `create_*` methods on `PdfPageObjects` build the object AND add it to the
page, returning the added `PdfPageObject`:

```rust
use pdfium_render::prelude::*;

let object = page.objects_mut().create_image_object(
    PdfPoints::new(100.0),   // x
    PdfPoints::new(500.0),   // y
    &image,                  // an image::DynamicImage
    Some(PdfPoints::new(200.0)),  // width
    Some(PdfPoints::new(150.0)),  // height
)?;
```

Path variants: `create_path_object_line`, `create_path_object_bezier`,
`create_path_object_rect`, `create_path_object_circle`,
`create_path_object_circle_at`, `create_path_object_ellipse`,
`create_path_object_ellipse_at`. Also `create_text_object`.

### Style B : `new` then `add_*` (build detached, then attach)

`PdfPageImageObject` constructors build a detached object bound to a document.
A separate `add_image_object` call attaches it to a page:

```rust
let object = PdfPageImageObject::new_from_jpeg_file(&document, "logo.jpg")?;
let added = page.objects_mut().add_image_object(object)?;
```

NEVER call both a `create_*` method and an `add_*` method for the same object:
`create_*` already added it. A second `add_*` adds a duplicate or fails.

## PdfPageImageObject constructors

| Constructor | Use |
|-------------|-----|
| `new(&document, &image)` | image at its natural size |
| `new_with_width(&document, &image, width)` | width fixed, height from aspect ratio |
| `new_with_height(&document, &image, height)` | height fixed, width from aspect ratio |
| `new_with_size(&document, &image, width, height)` | exact size |
| `new_from_jpeg_file(&document, path)` | load straight from a JPEG file (0.8.29) |
| `new_from_jpeg_reader(&document, reader)` | load from any `Read + Seek` (0.8.29) |

Every constructor returns `Result<PdfPageImageObject, PdfiumError>` and takes
the `PdfDocument` the object will belong to. Use `set_image()` to replace the
image, `get_raw_image()` / `get_processed_image()` to read it back.

## Transforming an object with PdfMatrix

A `PdfPageObject` carries a transformation matrix. Apply a `PdfMatrix` with
`apply_matrix`:

```rust
use pdfium_render::prelude::*;

let matrix = PdfMatrix::IDENTITY
    .scale(2.0, 2.0)?
    .rotate_clockwise_degrees(45.0)?;
object.apply_matrix(matrix)?;
```

`PdfMatrix` factory methods (`translate`, `scale`, `rotate_clockwise_degrees`,
`rotate_counter_clockwise_degrees`, `flip_horizontally`, `flip_vertically`)
each return `Result<PdfMatrix, PdfiumError>`, so chain them with `?`.

| Method on a page object | Effect |
|-------------------------|--------|
| `apply_matrix(matrix)` | compose `matrix` onto the object's current transform |
| `transform(a, b, c, d, e, f)` | apply a raw six-value matrix |
| `reset_matrix(matrix)` | replace the object's transform |
| `reset_matrix_to_identity()` | clear the transform |
| `matrix()` | read the current transform |

Version trap: `set_matrix()` was deprecated in 0.8.15 and removed in 0.9.0.
ALWAYS use `apply_matrix()` (or `reset_matrix()` to replace rather than
compose).

## Removing objects

```rust
// By value : you must own the PdfPageObject
let removed = page.objects_mut().remove_object(object)?;
// By index
let removed = page.objects_mut().remove_object_at_index(0)?;
```

Both return the removed `PdfPageObject`. Version trap: the 0.6.x names
`delete_object` / `delete_object_at_index` were renamed to `remove_object` /
`remove_object_at_index` in 0.7.4.

## Relocating objects between pages

NEVER hand-roll object moving as remove-from-page-A then add-to-page-B. That
pattern fights the borrow checker, because removing requires a mutable borrow
of one page's objects while inserting requires a mutable borrow of another
(issues #60, #25). ALWAYS use the dedicated relocation methods.

| Method | Source | Effect |
|--------|--------|--------|
| `object.copy_to_page(&mut page)` | a single `PdfPageObject` | duplicate onto `page` |
| `object.move_to_page(&mut page)` | a single `PdfPageObject` | move onto `page` |
| `group.copy_to_page(&mut page)` | a `PdfPageGroupObject` | duplicate the whole group |
| `group.move_to_page(&mut page)` | a `PdfPageGroupObject` | move the whole group |

`PdfPageGroupObject` collects several objects so one transform or one
relocation applies to all of them at once. Build a group with
`objects.create_group(...)` or `create_empty_group()`, then call `apply_matrix`,
`copy_to_page`, `move_to_page`, or `move_to_annotation` on the group.

Version trap: the `PdfPageGroupObject::copy_onto_new_page_*` methods were
removed in 0.9.0. ALWAYS use `copy_to_page()`.

## Common failures (quick triage)

| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| compile error: method takes `&mut self` | called a mutator on `objects()` | use `objects_mut()` |
| compile error: `set_matrix` not found | removed 0.9.0 name | use `apply_matrix()` |
| compile error: `copy_onto_new_page` not found | removed 0.9.0 name | use `copy_to_page()` |
| compile error: `delete_object` not found | renamed in 0.7.4 | use `remove_object()` |
| borrow-checker error moving an object | hand-rolled remove-then-insert | use `move_to_page()` |
| `CannotMoveObjectAcrossDocuments` | `move_to_page` targeted another document's page | see `pdfium-impl-multi-page` |
| duplicate object on the page | both `create_*` and `add_*` called | use exactly one construction style |

## Reference files

- `references/methods.md`: complete signatures for `PdfPageObjects`,
  `PdfPageImageObject`, `PdfMatrix`, `PdfPageGroupObject`, and the object
  transform methods, with version annotations.
- `references/examples.md`: verified editing code, from stamping an image to
  moving objects between pages.
- `references/anti-patterns.md`: real editing failures, why each fails, and the
  fix.

## Companion skills

- `pdfium-syntax-page-objects`: reading and inspecting existing page objects.
- `pdfium-impl-multi-page`: copying whole pages between documents.
- `pdfium-core-coordinates`: `PdfPoints`, `PdfRect` vs `PdfQuadPoints`.
- `pdfium-impl-saving`: persisting the edited document.

