0
# Page Objects and Graphics
1
2
Manipulation of PDF page objects including images, text, and vector graphics. Supports object transformation, insertion, removal, and detailed analysis of page content structure.
3
4
## Capabilities
5
6
### Page Object Base Class
7
8
The PdfObject class serves as the base for all page objects including text, images, and vector graphics.
9
10
```python { .api }
11
class PdfObject:
12
def get_pos(self) -> tuple:
13
"""
14
Get object position bounds.
15
16
Returns:
17
tuple: (left, bottom, right, top) bounding rectangle in PDF units
18
"""
19
20
def get_matrix(self) -> PdfMatrix:
21
"""
22
Get object transformation matrix.
23
24
Returns:
25
PdfMatrix: Current transformation matrix
26
"""
27
28
def set_matrix(self, matrix: PdfMatrix):
29
"""
30
Set object transformation matrix.
31
32
Parameters:
33
- matrix: PdfMatrix, new transformation matrix
34
"""
35
36
def transform(self, matrix: PdfMatrix):
37
"""
38
Apply transformation matrix to object.
39
40
Parameters:
41
- matrix: PdfMatrix, transformation to apply
42
"""
43
```
44
45
Basic object manipulation:
46
47
```python
48
import pypdfium2 as pdfium
49
50
pdf = pdfium.PdfDocument("document.pdf")
51
page = pdf[0]
52
53
# Iterate through page objects
54
for i in range(page.count_objects()):
55
obj = page.get_object(i)
56
57
# Get object information
58
bounds = obj.get_pos()
59
matrix = obj.get_matrix()
60
61
print(f"Object {i}:")
62
print(f" Type: {obj.type}")
63
print(f" Bounds: {bounds}")
64
print(f" Matrix: {matrix.get()}")
65
print(f" Level: {obj.level}")
66
```
67
68
### Page Object Properties
69
70
Access object metadata and relationships.
71
72
```python { .api }
73
@property
74
def raw(self) -> FPDF_PAGEOBJECT:
75
"""Raw PDFium page object handle."""
76
77
@property
78
def type(self) -> int:
79
"""Object type constant (text, image, path, etc.)."""
80
81
@property
82
def page(self) -> PdfPage:
83
"""Parent page containing this object."""
84
85
@property
86
def pdf(self) -> PdfDocument:
87
"""Parent document containing this object."""
88
89
@property
90
def level(self) -> int:
91
"""Nesting level of the object."""
92
```
93
94
### Image Objects
95
96
The PdfImage class provides specialized handling for image objects within PDF pages.
97
98
```python { .api }
99
class PdfImage(PdfObject):
100
@classmethod
101
def new(cls, pdf: PdfDocument) -> PdfImage:
102
"""
103
Create new image object.
104
105
Parameters:
106
- pdf: PdfDocument, parent document
107
108
Returns:
109
PdfImage: New image object (not yet inserted into page)
110
"""
111
112
def get_metadata(self) -> ImageInfo:
113
"""
114
Get image metadata information.
115
116
Returns:
117
ImageInfo: Named tuple with image format, mode, and filter information
118
"""
119
120
def get_size(self) -> tuple[int, int]:
121
"""
122
Get image dimensions.
123
124
Returns:
125
tuple: (width, height) in pixels
126
"""
127
128
def get_filters(self, skip_simple=False) -> list:
129
"""
130
Get list of filters applied to image data.
131
132
Parameters:
133
- skip_simple: bool, skip simple/common filters
134
135
Returns:
136
list: Filter names applied to image
137
"""
138
```
139
140
Image metadata structure:
141
142
```python { .api }
143
class ImageInfo(NamedTuple):
144
format: str # Image format (JPEG, PNG, etc.)
145
mode: str # Color mode (RGB, RGBA, L, etc.)
146
metadata: dict # Additional metadata
147
all_filters: list # All filters applied
148
complex_filters: list # Complex/uncommon filters
149
```
150
151
### Image Data Access
152
153
Extract and manipulate image data from PDF image objects.
154
155
```python { .api }
156
def get_bitmap(self, render=False) -> PdfBitmap:
157
"""
158
Get image as bitmap.
159
160
Parameters:
161
- render: bool, render image through PDFium (may change appearance)
162
163
Returns:
164
PdfBitmap: Image data as bitmap object
165
"""
166
167
def get_data(self, decode_simple=False) -> bytes:
168
"""
169
Get raw image data.
170
171
Parameters:
172
- decode_simple: bool, decode simple filters (like FlateDecode)
173
174
Returns:
175
bytes: Raw image data (may be compressed)
176
"""
177
178
def extract(self, dest: str, *args, **kwargs):
179
"""
180
Extract image to file.
181
182
Parameters:
183
- dest: str, output file path
184
- Additional parameters for format-specific options
185
186
Automatically detects image format and saves appropriately.
187
"""
188
```
189
190
Image processing examples:
191
192
```python
193
pdf = pdfium.PdfDocument("document.pdf")
194
page = pdf[0]
195
196
# Find and process all images on page
197
for i in range(page.count_objects()):
198
obj = page.get_object(i)
199
200
if isinstance(obj, pdfium.PdfImage):
201
print(f"\nProcessing image {i}:")
202
203
# Get image metadata
204
metadata = obj.get_metadata()
205
print(f" Format: {metadata.format}")
206
print(f" Mode: {metadata.mode}")
207
print(f" Size: {obj.get_size()}")
208
print(f" Filters: {metadata.all_filters}")
209
210
# Extract image to file
211
output_path = f"extracted_image_{i}.png"
212
try:
213
obj.extract(output_path)
214
print(f" Extracted to: {output_path}")
215
except Exception as e:
216
print(f" Extraction failed: {e}")
217
218
# Try getting as bitmap instead
219
try:
220
bitmap = obj.get_bitmap()
221
pil_image = bitmap.to_pil()
222
pil_image.save(output_path)
223
print(f" Converted and saved to: {output_path}")
224
except Exception as e2:
225
print(f" Bitmap conversion failed: {e2}")
226
227
# Analyze image position and transformation
228
bounds = obj.get_pos()
229
matrix = obj.get_matrix()
230
print(f" Position: {bounds}")
231
print(f" Transform: {matrix.get()}")
232
```
233
234
### Image Modification
235
236
Modify existing images or create new image objects.
237
238
```python { .api }
239
def load_jpeg(self, source, pages=None, inline=False, autoclose=True):
240
"""
241
Load JPEG data into image object.
242
243
Parameters:
244
- source: file path, bytes, or file-like object containing JPEG data
245
- pages: list of pages to apply to (None = current page)
246
- inline: bool, embed as inline image
247
- autoclose: bool, close source if file-like object
248
"""
249
250
def set_bitmap(self, bitmap: PdfBitmap, pages=None):
251
"""
252
Set image data from bitmap.
253
254
Parameters:
255
- bitmap: PdfBitmap, source bitmap data
256
- pages: list of pages to apply to (None = current page)
257
"""
258
```
259
260
Creating and modifying images:
261
262
```python
263
pdf = pdfium.PdfDocument.new()
264
page = pdf.new_page(612, 792) # US Letter
265
266
# Create new image object
267
img_obj = pdfium.PdfImage.new(pdf)
268
269
# Load JPEG data
270
img_obj.load_jpeg("photo.jpg")
271
272
# Position the image on page
273
transform = pdfium.PdfMatrix()
274
transform = transform.translate(100, 400) # Position
275
transform = transform.scale(200, 150) # Size
276
277
img_obj.set_matrix(transform)
278
279
# Insert into page
280
page.insert_object(img_obj)
281
282
# Generate content stream
283
page.gen_content()
284
285
# Save document
286
pdf.save("document_with_image.pdf")
287
```
288
289
### Object Transformation
290
291
Apply geometric transformations to page objects including rotation, scaling, and translation.
292
293
```python
294
def transform_objects_example(page):
295
"""Example of transforming page objects."""
296
297
for i in range(page.count_objects()):
298
obj = page.get_object(i)
299
300
if isinstance(obj, pdfium.PdfImage):
301
# Get current transformation
302
current_matrix = obj.get_matrix()
303
print(f"Current matrix: {current_matrix.get()}")
304
305
# Create new transformation
306
new_matrix = pdfium.PdfMatrix()
307
308
# Scale image to 150% size
309
new_matrix = new_matrix.scale(1.5, 1.5)
310
311
# Rotate 15 degrees
312
new_matrix = new_matrix.rotate(15)
313
314
# Move to new position
315
new_matrix = new_matrix.translate(50, 100)
316
317
# Combine with existing transformation
318
combined_matrix = current_matrix.multiply(new_matrix)
319
320
# Apply transformation
321
obj.set_matrix(combined_matrix)
322
323
print(f"New matrix: {combined_matrix.get()}")
324
325
# Usage
326
pdf = pdfium.PdfDocument("document.pdf")
327
page = pdf[0]
328
transform_objects_example(page)
329
330
# Regenerate content stream after transformations
331
page.gen_content()
332
pdf.save("transformed_document.pdf")
333
```
334
335
### Object Analysis
336
337
Analyze page objects for content extraction and document understanding.
338
339
```python
340
def analyze_page_objects(page):
341
"""Comprehensive page object analysis."""
342
343
analysis = {
344
'total_objects': page.count_objects(),
345
'images': [],
346
'text_objects': 0,
347
'path_objects': 0,
348
'other_objects': 0,
349
'coverage_area': 0
350
}
351
352
page_width, page_height = page.get_size()
353
page_area = page_width * page_height
354
355
for i in range(page.count_objects()):
356
obj = page.get_object(i)
357
bounds = obj.get_pos()
358
359
# Calculate object area
360
if bounds:
361
left, bottom, right, top = bounds
362
obj_area = (right - left) * (top - bottom)
363
analysis['coverage_area'] += obj_area
364
365
# Categorize objects
366
if isinstance(obj, pdfium.PdfImage):
367
img_info = {
368
'index': i,
369
'size': obj.get_size(),
370
'bounds': bounds,
371
'metadata': obj.get_metadata()._asdict()
372
}
373
analysis['images'].append(img_info)
374
375
elif obj.type == pdfium.raw.FPDF_PAGEOBJ_TEXT:
376
analysis['text_objects'] += 1
377
378
elif obj.type == pdfium.raw.FPDF_PAGEOBJ_PATH:
379
analysis['path_objects'] += 1
380
381
else:
382
analysis['other_objects'] += 1
383
384
# Calculate coverage percentage
385
analysis['coverage_percentage'] = (analysis['coverage_area'] / page_area) * 100
386
387
return analysis
388
389
# Usage
390
pdf = pdfium.PdfDocument("document.pdf")
391
392
for i, page in enumerate(pdf):
393
print(f"\n--- Page {i+1} Object Analysis ---")
394
analysis = analyze_page_objects(page)
395
396
print(f"Total objects: {analysis['total_objects']}")
397
print(f"Images: {len(analysis['images'])}")
398
print(f"Text objects: {analysis['text_objects']}")
399
print(f"Path objects: {analysis['path_objects']}")
400
print(f"Other objects: {analysis['other_objects']}")
401
print(f"Coverage: {analysis['coverage_percentage']:.1f}%")
402
403
# Detail image information
404
for img_info in analysis['images']:
405
print(f" Image {img_info['index']}: {img_info['size']} pixels")
406
print(f" Format: {img_info['metadata']['format']}")
407
print(f" Bounds: {img_info['bounds']}")
408
```
409
410
### Form XObjects
411
412
Handle PDF Form XObjects for reusable content and complex graphics. Form XObjects are reusable page content that can be embedded multiple times within documents.
413
414
```python { .api }
415
class PdfXObject:
416
"""
417
XObject helper class for managing reusable PDF content.
418
419
Form XObjects are self-contained graphic objects that can be referenced
420
multiple times within a PDF document. They're useful for templates,
421
logos, headers, footers, and other repeated content.
422
423
Attributes:
424
- raw: FPDF_XOBJECT, underlying PDFium XObject handle
425
- pdf: PdfDocument, reference to document this XObject belongs to
426
"""
427
428
def __init__(self, raw, pdf):
429
"""
430
Initialize XObject wrapper.
431
432
Parameters:
433
- raw: FPDF_XOBJECT, PDFium XObject handle
434
- pdf: PdfDocument, parent document
435
436
Note: XObjects are typically created via PdfDocument.page_as_xobject()
437
rather than direct instantiation.
438
"""
439
440
def as_pageobject(self) -> PdfObject:
441
"""
442
Convert Form XObject to independent page object.
443
444
Returns:
445
PdfObject: Page object representation of the XObject content
446
447
Creates an independent page object from the XObject that can be
448
inserted into pages. Multiple page objects can share the same
449
XObject resources. Page objects remain valid after XObject closure.
450
"""
451
452
def close(self):
453
"""Close and release XObject resources."""
454
```
455
456
Creating and using XObjects:
457
458
```python
459
import pypdfium2 as pdfium
460
461
# Load source document
462
source_pdf = pdfium.PdfDocument("source_document.pdf")
463
target_pdf = pdfium.PdfDocument.new()
464
465
# Convert a page to XObject for reuse
466
page_xobject = source_pdf.page_as_xobject(0, target_pdf)
467
468
# Create target page
469
target_page = target_pdf.new_page(612, 792)
470
471
# Create multiple page objects from the same XObject
472
header_obj = page_xobject.as_pageobject()
473
footer_obj = page_xobject.as_pageobject()
474
475
# Position header at top of page
476
header_matrix = pdfium.PdfMatrix()
477
header_matrix = header_matrix.translate(50, 700)
478
header_matrix = header_matrix.scale(0.5, 0.5) # Scale down
479
header_obj.set_matrix(header_matrix)
480
481
# Position footer at bottom
482
footer_matrix = pdfium.PdfMatrix()
483
footer_matrix = footer_matrix.translate(50, 50)
484
footer_matrix = footer_matrix.scale(0.3, 0.3) # Scale down more
485
footer_obj.set_matrix(footer_matrix)
486
487
# Insert both objects into page
488
target_page.insert_obj(header_obj)
489
target_page.insert_obj(footer_obj)
490
491
# Generate content and save
492
target_page.gen_content()
493
target_pdf.save("document_with_reused_content.pdf")
494
495
# XObject can be closed after page objects are created
496
page_xobject.close()
497
```
498
499
XObject reuse patterns:
500
501
```python
502
def create_template_document():
503
"""Create document with repeated template content."""
504
505
# Source document with logo/header content
506
logo_pdf = pdfium.PdfDocument("company_logo.pdf")
507
main_pdf = pdfium.PdfDocument.new()
508
509
# Convert logo page to reusable XObject
510
logo_xobject = logo_pdf.page_as_xobject(0, main_pdf)
511
512
# Create multiple pages with logo
513
for i in range(5):
514
page = main_pdf.new_page(612, 792)
515
516
# Add logo to each page
517
logo_obj = logo_xobject.as_pageobject()
518
519
# Position logo in top-right corner
520
logo_matrix = pdfium.PdfMatrix()
521
logo_matrix = logo_matrix.translate(450, 720) # Top-right
522
logo_matrix = logo_matrix.scale(0.2, 0.2) # Small size
523
logo_obj.set_matrix(logo_matrix)
524
525
page.insert_obj(logo_obj)
526
527
# Add page-specific content here
528
# ... (text, images, etc.)
529
530
page.gen_content()
531
532
# Clean up
533
logo_xobject.close()
534
logo_pdf.close()
535
536
return main_pdf
537
538
# Usage
539
template_doc = create_template_document()
540
template_doc.save("template_document.pdf")
541
template_doc.close()
542
```
543
544
### Exception Handling
545
546
Handle errors that may occur during image extraction and processing.
547
548
```python { .api }
549
class ImageNotExtractableError(Exception):
550
"""
551
Raised when image cannot be extracted from PDF.
552
553
This may occur due to:
554
- Unsupported image formats
555
- Corrupted image data
556
- Complex filter combinations
557
- Encrypted or protected images
558
"""
559
```
560
561
Safe image extraction:
562
563
```python
564
def safe_extract_images(page, output_dir):
565
"""Safely extract all images from page."""
566
import os
567
568
extracted_count = 0
569
failed_count = 0
570
571
for i in range(page.count_objects()):
572
obj = page.get_object(i)
573
574
if isinstance(obj, pdfium.PdfImage):
575
try:
576
# Try direct extraction first
577
output_path = os.path.join(output_dir, f"image_{i}.png")
578
obj.extract(output_path)
579
extracted_count += 1
580
print(f"Extracted image {i}")
581
582
except pdfium.ImageNotExtractableError:
583
# Try bitmap conversion
584
try:
585
bitmap = obj.get_bitmap(render=True)
586
pil_image = bitmap.to_pil()
587
output_path = os.path.join(output_dir, f"image_{i}_rendered.png")
588
pil_image.save(output_path)
589
extracted_count += 1
590
print(f"Rendered and extracted image {i}")
591
592
except Exception as e:
593
failed_count += 1
594
print(f"Failed to extract image {i}: {e}")
595
596
except Exception as e:
597
failed_count += 1
598
print(f"Unexpected error extracting image {i}: {e}")
599
600
return extracted_count, failed_count
601
602
# Usage
603
import os
604
os.makedirs("extracted_images", exist_ok=True)
605
606
pdf = pdfium.PdfDocument("document.pdf")
607
page = pdf[0]
608
609
extracted, failed = safe_extract_images(page, "extracted_images")
610
print(f"Successfully extracted: {extracted}")
611
print(f"Failed extractions: {failed}")
612
```
613
614
## Object Type Constants
615
616
Common object type constants available through the raw module:
617
618
```python
619
# Available through pypdfium2.raw
620
FPDF_PAGEOBJ_UNKNOWN = 0 # Unknown object type
621
FPDF_PAGEOBJ_TEXT = 1 # Text object
622
FPDF_PAGEOBJ_PATH = 2 # Path/vector graphics
623
FPDF_PAGEOBJ_IMAGE = 3 # Image object
624
FPDF_PAGEOBJ_SHADING = 4 # Shading object
625
FPDF_PAGEOBJ_FORM = 5 # Form XObject
626
```
627
628
Object type identification:
629
630
```python
631
for i in range(page.count_objects()):
632
obj = page.get_object(i)
633
634
type_names = {
635
pdfium.raw.FPDF_PAGEOBJ_TEXT: "Text",
636
pdfium.raw.FPDF_PAGEOBJ_PATH: "Path",
637
pdfium.raw.FPDF_PAGEOBJ_IMAGE: "Image",
638
pdfium.raw.FPDF_PAGEOBJ_SHADING: "Shading",
639
pdfium.raw.FPDF_PAGEOBJ_FORM: "Form"
640
}
641
642
type_name = type_names.get(obj.type, "Unknown")
643
print(f"Object {i}: {type_name} (type {obj.type})")
644
```