or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

attachments.mdcli-tools.mddocument-management.mdimage-bitmap.mdindex.mdpage-manipulation.mdpage-objects.mdtext-processing.mdtransformation.mdversion-info.md

transformation.mddocs/

0

# Transformation and Geometry

1

2

2D transformation matrices for coordinate system manipulation, rotation, scaling, translation operations, and geometric calculations. The PdfMatrix class provides comprehensive support for PDF coordinate transformations.

3

4

## Capabilities

5

6

### Matrix Creation

7

8

Create transformation matrices with various initialization options.

9

10

```python { .api }

11

class PdfMatrix:

12

def __init__(self, a=1, b=0, c=0, d=1, e=0, f=0):

13

"""

14

Create transformation matrix.

15

16

Parameters:

17

- a: float, horizontal scaling

18

- b: float, horizontal skewing

19

- c: float, vertical skewing

20

- d: float, vertical scaling

21

- e: float, horizontal translation

22

- f: float, vertical translation

23

24

Standard form: [a c e]

25

[b d f]

26

[0 0 1]

27

"""

28

29

@classmethod

30

def from_raw(cls, raw) -> PdfMatrix:

31

"""

32

Create matrix from raw FS_MATRIX structure.

33

34

Parameters:

35

- raw: FS_MATRIX, raw PDFium matrix structure

36

37

Returns:

38

PdfMatrix: Matrix object wrapping the raw structure

39

"""

40

```

41

42

Matrix creation examples:

43

44

```python

45

import pypdfium2 as pdfium

46

47

# Identity matrix (no transformation)

48

identity = pdfium.PdfMatrix()

49

print(f"Identity: {identity.get()}") # (1, 0, 0, 1, 0, 0)

50

51

# Custom matrix

52

custom = pdfium.PdfMatrix(a=2, d=2, e=100, f=50)

53

print(f"Custom: {custom.get()}") # Scale 2x and translate (100, 50)

54

55

# From raw PDFium matrix (if available)

56

# raw_matrix = some_pdfium_function_returning_matrix()

57

# matrix = pdfium.PdfMatrix.from_raw(raw_matrix)

58

```

59

60

### Matrix Properties

61

62

Access individual matrix coefficients.

63

64

```python { .api }

65

@property

66

def a(self) -> float:

67

"""Horizontal scaling factor."""

68

69

@property

70

def b(self) -> float:

71

"""Horizontal skewing factor."""

72

73

@property

74

def c(self) -> float:

75

"""Vertical skewing factor."""

76

77

@property

78

def d(self) -> float:

79

"""Vertical scaling factor."""

80

81

@property

82

def e(self) -> float:

83

"""Horizontal translation."""

84

85

@property

86

def f(self) -> float:

87

"""Vertical translation."""

88

```

89

90

Property access:

91

92

```python

93

matrix = pdfium.PdfMatrix(a=1.5, d=2.0, e=100, f=200)

94

95

print(f"Horizontal scale: {matrix.a}")

96

print(f"Vertical scale: {matrix.d}")

97

print(f"Translation: ({matrix.e}, {matrix.f})")

98

print(f"Skew: ({matrix.b}, {matrix.c})")

99

```

100

101

### Matrix Operations

102

103

Core matrix operations including conversion and multiplication.

104

105

```python { .api }

106

def get(self) -> tuple:

107

"""

108

Get matrix coefficients as tuple.

109

110

Returns:

111

tuple: (a, b, c, d, e, f) matrix coefficients

112

"""

113

114

def to_raw(self) -> FS_MATRIX:

115

"""

116

Convert to PDFium matrix structure.

117

118

Returns:

119

FS_MATRIX: Raw PDFium matrix for use with low-level functions

120

"""

121

122

def multiply(self, other: PdfMatrix) -> PdfMatrix:

123

"""

124

Multiply with another matrix.

125

126

Parameters:

127

- other: PdfMatrix, matrix to multiply with

128

129

Returns:

130

PdfMatrix: Result matrix (this * other)

131

"""

132

```

133

134

Basic operations:

135

136

```python

137

# Create matrices

138

m1 = pdfium.PdfMatrix(a=2, d=2) # Scale 2x

139

m2 = pdfium.PdfMatrix(e=100, f=50) # Translate (100, 50)

140

141

# Get coefficients

142

coeffs = m1.get()

143

print(f"Scale matrix: {coeffs}")

144

145

# Matrix multiplication (apply scale then translation)

146

combined = m1.multiply(m2)

147

print(f"Combined: {combined.get()}")

148

149

# Convert to raw for PDFium functions

150

raw_matrix = combined.to_raw()

151

```

152

153

### Transformation Creation

154

155

Create specific types of transformations with convenient methods.

156

157

```python { .api }

158

def translate(self, x: float, y: float) -> PdfMatrix:

159

"""

160

Create translation matrix.

161

162

Parameters:

163

- x: float, horizontal translation in PDF units

164

- y: float, vertical translation in PDF units

165

166

Returns:

167

PdfMatrix: Translation transformation matrix

168

"""

169

170

def scale(self, x: float, y: float) -> PdfMatrix:

171

"""

172

Create scaling matrix.

173

174

Parameters:

175

- x: float, horizontal scaling factor

176

- y: float, vertical scaling factor

177

178

Returns:

179

PdfMatrix: Scaling transformation matrix

180

"""

181

182

def rotate(self, angle: float, ccw=False, rad=False) -> PdfMatrix:

183

"""

184

Create rotation matrix.

185

186

Parameters:

187

- angle: float, rotation angle

188

- ccw: bool, counter-clockwise rotation (default: clockwise)

189

- rad: bool, angle in radians (default: degrees)

190

191

Returns:

192

PdfMatrix: Rotation transformation matrix

193

"""

194

195

def mirror(self, v: bool, h: bool) -> PdfMatrix:

196

"""

197

Create mirroring matrix.

198

199

Parameters:

200

- v: bool, vertical mirroring (flip top-bottom)

201

- h: bool, horizontal mirroring (flip left-right)

202

203

Returns:

204

PdfMatrix: Mirroring transformation matrix

205

"""

206

207

def skew(self, x_angle: float, y_angle: float, rad=False) -> PdfMatrix:

208

"""

209

Create skewing matrix.

210

211

Parameters:

212

- x_angle: float, horizontal skew angle

213

- y_angle: float, vertical skew angle

214

- rad: bool, angles in radians (default: degrees)

215

216

Returns:

217

PdfMatrix: Skewing transformation matrix

218

"""

219

```

220

221

Transformation examples:

222

223

```python

224

import math

225

226

# Translation

227

translate_matrix = pdfium.PdfMatrix().translate(100, 200)

228

print(f"Translate (100, 200): {translate_matrix.get()}")

229

230

# Scaling

231

scale_matrix = pdfium.PdfMatrix().scale(1.5, 2.0)

232

print(f"Scale (1.5x, 2.0x): {scale_matrix.get()}")

233

234

# Rotation (45 degrees clockwise)

235

rotate_matrix = pdfium.PdfMatrix().rotate(45)

236

print(f"Rotate 45°: {rotate_matrix.get()}")

237

238

# Rotation (π/4 radians counter-clockwise)

239

rotate_ccw = pdfium.PdfMatrix().rotate(math.pi/4, ccw=True, rad=True)

240

print(f"Rotate π/4 CCW: {rotate_ccw.get()}")

241

242

# Mirroring

243

mirror_h = pdfium.PdfMatrix().mirror(v=False, h=True) # Horizontal flip

244

mirror_v = pdfium.PdfMatrix().mirror(v=True, h=False) # Vertical flip

245

print(f"Mirror horizontal: {mirror_h.get()}")

246

print(f"Mirror vertical: {mirror_v.get()}")

247

248

# Skewing

249

skew_matrix = pdfium.PdfMatrix().skew(15, 0) # 15° horizontal skew

250

print(f"Skew 15° horizontal: {skew_matrix.get()}")

251

```

252

253

### Point and Rectangle Transformation

254

255

Apply transformations to coordinates and rectangular areas.

256

257

```python { .api }

258

def on_point(self, x: float, y: float) -> tuple:

259

"""

260

Transform point coordinates.

261

262

Parameters:

263

- x: float, x-coordinate

264

- y: float, y-coordinate

265

266

Returns:

267

tuple: (transformed_x, transformed_y)

268

"""

269

270

def on_rect(self, left: float, bottom: float, right: float, top: float) -> tuple:

271

"""

272

Transform rectangle coordinates.

273

274

Parameters:

275

- left: float, left edge

276

- bottom: float, bottom edge

277

- right: float, right edge

278

- top: float, top edge

279

280

Returns:

281

tuple: (new_left, new_bottom, new_right, new_top)

282

"""

283

```

284

285

Coordinate transformation:

286

287

```python

288

# Create composite transformation

289

transform = pdfium.PdfMatrix()

290

transform = transform.translate(100, 50) # Move to (100, 50)

291

transform = transform.rotate(30) # Rotate 30 degrees

292

transform = transform.scale(1.5, 1.5) # Scale 1.5x

293

294

# Transform a point

295

original_point = (0, 0)

296

transformed_point = transform.on_point(*original_point)

297

print(f"Point {original_point} -> {transformed_point}")

298

299

# Transform another point

300

point2 = (100, 100)

301

transformed_point2 = transform.on_point(*point2)

302

print(f"Point {point2} -> {transformed_point2}")

303

304

# Transform a rectangle

305

original_rect = (0, 0, 200, 100) # (left, bottom, right, top)

306

transformed_rect = transform.on_rect(*original_rect)

307

print(f"Rectangle {original_rect} -> {transformed_rect}")

308

```

309

310

### Complex Transformations

311

312

Combine multiple transformations for complex geometric operations.

313

314

```python

315

def create_centered_rotation(center_x, center_y, angle):

316

"""Create rotation around specific center point."""

317

318

# Translate to origin

319

to_origin = pdfium.PdfMatrix().translate(-center_x, -center_y)

320

321

# Rotate around origin

322

rotation = pdfium.PdfMatrix().rotate(angle)

323

324

# Translate back

325

from_origin = pdfium.PdfMatrix().translate(center_x, center_y)

326

327

# Combine transformations (order matters!)

328

result = to_origin.multiply(rotation).multiply(from_origin)

329

330

return result

331

332

def create_fit_transformation(source_rect, target_rect, maintain_aspect=True):

333

"""Create transformation to fit source rectangle into target rectangle."""

334

335

src_left, src_bottom, src_right, src_top = source_rect

336

tgt_left, tgt_bottom, tgt_right, tgt_top = target_rect

337

338

src_width = src_right - src_left

339

src_height = src_top - src_bottom

340

tgt_width = tgt_right - tgt_left

341

tgt_height = tgt_top - tgt_bottom

342

343

# Calculate scaling factors

344

scale_x = tgt_width / src_width

345

scale_y = tgt_height / src_height

346

347

if maintain_aspect:

348

# Use smaller scale to maintain aspect ratio

349

scale = min(scale_x, scale_y)

350

scale_x = scale_y = scale

351

352

# Create transformation

353

transform = pdfium.PdfMatrix()

354

355

# Translate source to origin

356

transform = transform.translate(-src_left, -src_bottom)

357

358

# Scale to fit

359

transform = transform.scale(scale_x, scale_y)

360

361

# Translate to target position

362

if maintain_aspect:

363

# Center in target rectangle

364

actual_width = src_width * scale

365

actual_height = src_height * scale

366

offset_x = (tgt_width - actual_width) / 2

367

offset_y = (tgt_height - actual_height) / 2

368

transform = transform.translate(tgt_left + offset_x, tgt_bottom + offset_y)

369

else:

370

transform = transform.translate(tgt_left, tgt_bottom)

371

372

return transform

373

374

# Usage examples

375

pdf = pdfium.PdfDocument("document.pdf")

376

page = pdf[0]

377

378

# Get an image object

379

for i in range(page.count_objects()):

380

obj = page.get_object(i)

381

if isinstance(obj, pdfium.PdfImage):

382

383

# Rotate image around its center

384

bounds = obj.get_pos()

385

if bounds:

386

left, bottom, right, top = bounds

387

center_x = (left + right) / 2

388

center_y = (bottom + top) / 2

389

390

rotation_transform = create_centered_rotation(center_x, center_y, 45)

391

obj.set_matrix(rotation_transform)

392

393

# Or fit image to specific area

394

target_area = (100, 100, 400, 300) # Specific rectangle

395

if bounds:

396

fit_transform = create_fit_transformation(bounds, target_area, maintain_aspect=True)

397

obj.set_matrix(fit_transform)

398

399

break

400

401

# Regenerate page content

402

page.gen_content()

403

```

404

405

### Coordinate System Utilities

406

407

Helper functions for working with PDF coordinate systems.

408

409

```python

410

def pdf_to_screen_transform(page_width, page_height, screen_width, screen_height, maintain_aspect=True):

411

"""Create transformation from PDF coordinates to screen coordinates."""

412

413

# PDF uses bottom-left origin, screen uses top-left

414

# Need to flip Y axis and scale appropriately

415

416

scale_x = screen_width / page_width

417

scale_y = screen_height / page_height

418

419

if maintain_aspect:

420

scale = min(scale_x, scale_y)

421

scale_x = scale_y = scale

422

423

transform = pdfium.PdfMatrix()

424

425

# Scale to screen size

426

transform = transform.scale(scale_x, -scale_y) # Negative Y to flip

427

428

# Translate to handle flipped Y coordinate

429

transform = transform.translate(0, -page_height * scale_y)

430

431

return transform

432

433

def inches_to_pdf_transform(dpi=72):

434

"""Create transformation from inches to PDF units."""

435

return pdfium.PdfMatrix().scale(dpi, dpi)

436

437

def mm_to_pdf_transform():

438

"""Create transformation from millimeters to PDF units."""

439

mm_per_inch = 25.4

440

pdf_units_per_inch = 72

441

scale = pdf_units_per_inch / mm_per_inch

442

return pdfium.PdfMatrix().scale(scale, scale)

443

444

# Usage

445

page = pdf[0]

446

page_width, page_height = page.get_size()

447

448

# Transform for 800x600 screen display

449

screen_transform = pdf_to_screen_transform(

450

page_width, page_height, 800, 600, maintain_aspect=True

451

)

452

453

# Convert PDF point to screen coordinates

454

pdf_point = (200, 400)

455

screen_point = screen_transform.on_point(*pdf_point)

456

print(f"PDF point {pdf_point} -> Screen point {screen_point}")

457

```

458

459

### Matrix Analysis

460

461

Analyze transformation matrices to understand their properties.

462

463

```python

464

def analyze_matrix(matrix):

465

"""Analyze transformation matrix properties."""

466

467

a, b, c, d, e, f = matrix.get()

468

469

# Translation components

470

translation = (e, f)

471

472

# Scaling factors (approximate for rotated matrices)

473

scale_x = math.sqrt(a*a + b*b)

474

scale_y = math.sqrt(c*c + d*d)

475

476

# Rotation angle (in degrees)

477

rotation_rad = math.atan2(b, a)

478

rotation_deg = math.degrees(rotation_rad)

479

480

# Determinant (affects area scaling)

481

determinant = a*d - b*c

482

483

# Shearing

484

shear = (c != 0 or b != 0) and (abs(rotation_deg) % 90 != 0)

485

486

analysis = {

487

'translation': translation,

488

'scale_x': scale_x,

489

'scale_y': scale_y,

490

'rotation_degrees': rotation_deg,

491

'determinant': determinant,

492

'area_scale_factor': abs(determinant),

493

'preserves_angles': abs(abs(determinant) - scale_x * scale_y) < 1e-6,

494

'has_shear': shear,

495

'is_identity': abs(a-1) < 1e-6 and abs(d-1) < 1e-6 and abs(b) < 1e-6 and abs(c) < 1e-6 and abs(e) < 1e-6 and abs(f) < 1e-6

496

}

497

498

return analysis

499

500

# Usage

501

transform = pdfium.PdfMatrix().translate(100, 50).rotate(30).scale(1.5, 2.0)

502

analysis = analyze_matrix(transform)

503

504

print("Matrix Analysis:")

505

for key, value in analysis.items():

506

print(f" {key}: {value}")

507

```

508

509

## Common Transformation Patterns

510

511

### Object Positioning

512

513

```python

514

def position_object_at_center(obj, page_width, page_height):

515

"""Position object at page center."""

516

517

bounds = obj.get_pos()

518

if not bounds:

519

return

520

521

left, bottom, right, top = bounds

522

obj_width = right - left

523

obj_height = top - bottom

524

525

# Calculate center position

526

center_x = (page_width - obj_width) / 2

527

center_y = (page_height - obj_height) / 2

528

529

# Create transformation to move to center

530

transform = pdfium.PdfMatrix().translate(

531

center_x - left,

532

center_y - bottom

533

)

534

535

obj.set_matrix(transform)

536

537

# Usage with page object

538

page = pdf[0]

539

page_width, page_height = page.get_size()

540

541

for i in range(page.count_objects()):

542

obj = page.get_object(i)

543

if isinstance(obj, pdfium.PdfImage):

544

position_object_at_center(obj, page_width, page_height)

545

break

546

```