or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

color-management.mdcolor-utilities.mdcore-image.mddrawing.mdenhancement.mdfilters.mdfonts.mdimage-sequences.mdimage-statistics.mdindex.mdmath-operations.mdoperations.md

operations.mddocs/

0

# Image Operations and Transformations

1

2

Advanced image manipulation functions including automatic contrast adjustment, color space operations, geometric transformations, and specialized processing operations provided by the ImageOps module.

3

4

## Capabilities

5

6

### Automatic Image Enhancement

7

8

Functions for automatic image quality improvement and adjustment.

9

10

```python { .api }

11

def autocontrast(image, cutoff=0, ignore=None, mask=None, preserve_tone=False):

12

"""

13

Maximize image contrast by stretching histogram.

14

15

Parameters:

16

- image (Image): Input image

17

- cutoff (float | tuple): Percentage to cut from histogram ends (0-100)

18

- ignore (int | sequence): Pixel values to ignore in histogram

19

- mask (Image): Optional mask for selective processing

20

- preserve_tone (bool): Preserve image tone in Photoshop-like style

21

22

Returns:

23

Image: Auto-contrast adjusted image

24

"""

25

26

def equalize(image, mask=None):

27

"""

28

Equalize image histogram for improved contrast distribution.

29

30

Parameters:

31

- image (Image): Input image

32

- mask (Image): Optional mask for selective equalization

33

34

Returns:

35

Image: Histogram equalized image

36

"""

37

38

def posterize(image, bits):

39

"""

40

Reduce the number of bits for each color channel.

41

42

Parameters:

43

- image (Image): Input image

44

- bits (int): Number of bits to keep per channel (1-8)

45

46

Returns:

47

Image: Posterized image

48

"""

49

50

def solarize(image, threshold=128):

51

"""

52

Invert all pixel values above threshold (solarization effect).

53

54

Parameters:

55

- image (Image): Input image

56

- threshold (int): Threshold value (0-255)

57

58

Returns:

59

Image: Solarized image

60

"""

61

```

62

63

### Geometric Transformations and Sizing

64

65

Functions for resizing, fitting, and transforming images.

66

67

```python { .api }

68

def fit(image, size, method=3, bleed=0.0, centering=(0.5, 0.5)):

69

"""

70

Fit image within given size, cropping as needed.

71

72

Parameters:

73

- image (Image): Input image

74

- size (tuple): Target size as (width, height)

75

- method (int): Resampling method (Resampling.LANCZOS, etc.)

76

- bleed (float): Remove a border around fitted image (0.0-0.5)

77

- centering (tuple): Crop centering as (horizontal, vertical) (0.0-1.0)

78

79

Returns:

80

Image: Fitted image

81

"""

82

83

def contain(image, size, method=3):

84

"""

85

Resize image to fit within size while maintaining aspect ratio.

86

87

Parameters:

88

- image (Image): Input image

89

- size (tuple): Maximum size as (width, height)

90

- method (int): Resampling method

91

92

Returns:

93

Image: Contained image

94

"""

95

96

def cover(image, size, method=3):

97

"""

98

Resize image to cover the entire size, cropping if necessary.

99

100

Parameters:

101

- image (Image): Input image

102

- size (tuple): Target size as (width, height)

103

- method (int): Resampling method

104

105

Returns:

106

Image: Covered image (may be cropped)

107

"""

108

109

def pad(image, size, method=3, color=None, centering=(0.5, 0.5)):

110

"""

111

Resize and pad image to exact size.

112

113

Parameters:

114

- image (Image): Input image

115

- size (tuple): Target size as (width, height)

116

- method (int): Resampling method

117

- color (int | tuple | str): Padding color

118

- centering (tuple): Image centering in padded area

119

120

Returns:

121

Image: Padded image

122

"""

123

124

def scale(image, factor, resample=3):

125

"""

126

Scale image by a factor.

127

128

Parameters:

129

- image (Image): Input image

130

- factor (float): Scale factor (>1 enlarges, <1 shrinks)

131

- resample (int): Resampling method

132

133

Returns:

134

Image: Scaled image

135

"""

136

137

def crop(image, border=0):

138

"""

139

Remove border pixels from image.

140

141

Parameters:

142

- image (Image): Input image

143

- border (int | tuple): Border size to remove

144

145

Returns:

146

Image: Cropped image

147

"""

148

149

def expand(image, border=0, fill=0):

150

"""

151

Add border pixels around image.

152

153

Parameters:

154

- image (Image): Input image

155

- border (int | tuple): Border size to add

156

- fill (int | tuple | str): Border color

157

158

Returns:

159

Image: Expanded image

160

"""

161

```

162

163

### Color and Tone Operations

164

165

Functions for color manipulation and tone adjustment.

166

167

```python { .api }

168

def colorize(image, black, white, mid=None, blackpoint=0, whitepoint=255, midpoint=127):

169

"""

170

Colorize a grayscale image with specified colors.

171

172

Parameters:

173

- image (Image): Grayscale input image

174

- black (int | tuple | str): Color for black pixels

175

- white (int | tuple | str): Color for white pixels

176

- mid (int | tuple | str): Color for mid-tone pixels

177

- blackpoint (int): Pixel value mapped to black color (0-255)

178

- whitepoint (int): Pixel value mapped to white color (0-255)

179

- midpoint (int): Pixel value mapped to mid color (0-255)

180

181

Returns:

182

Image: Colorized image

183

"""

184

185

def grayscale(image):

186

"""

187

Convert image to grayscale using ITU-R 601-2 luma transform.

188

189

Parameters:

190

- image (Image): Input image

191

192

Returns:

193

Image: Grayscale image

194

"""

195

196

def invert(image):

197

"""

198

Invert image colors (negative effect).

199

200

Parameters:

201

- image (Image): Input image

202

203

Returns:

204

Image: Inverted image

205

"""

206

```

207

208

### Orientation and Flipping

209

210

Functions for rotating and flipping images.

211

212

```python { .api }

213

def flip(image):

214

"""

215

Flip image vertically (top to bottom).

216

217

Parameters:

218

- image (Image): Input image

219

220

Returns:

221

Image: Vertically flipped image

222

"""

223

224

def mirror(image):

225

"""

226

Flip image horizontally (left to right).

227

228

Parameters:

229

- image (Image): Input image

230

231

Returns:

232

Image: Horizontally flipped image

233

"""

234

235

def exif_transpose(image, in_place=False):

236

"""

237

Transpose image according to EXIF orientation data.

238

239

Parameters:

240

- image (Image): Input image with EXIF data

241

- in_place (bool): Modify image in place if True

242

243

Returns:

244

Image | None: Transposed image (or None if in_place=True)

245

"""

246

```

247

248

### Advanced Transformations

249

250

Functions for complex geometric transformations.

251

252

```python { .api }

253

def deform(image, deformer, resample=1):

254

"""

255

Deform image using a deformer object.

256

257

Parameters:

258

- image (Image): Input image

259

- deformer: Deformer object implementing getmesh() method

260

- resample (int): Resampling method

261

262

Returns:

263

Image: Deformed image

264

"""

265

```

266

267

## Usage Examples

268

269

### Automatic Image Enhancement Workflow

270

271

```python

272

from PIL import Image, ImageOps

273

274

def enhance_image_auto(image_path, save_path):

275

"""Automatically enhance an image using multiple operations."""

276

img = Image.open(image_path)

277

278

# Step 1: Auto contrast adjustment

279

enhanced = ImageOps.autocontrast(img, cutoff=2)

280

281

# Step 2: Equalize histogram for better distribution

282

enhanced = ImageOps.equalize(enhanced)

283

284

# Step 3: Convert to grayscale and back to remove color casts

285

if img.mode == "RGB":

286

gray = ImageOps.grayscale(enhanced)

287

# Apply colorization to remove color casts

288

enhanced = ImageOps.colorize(gray, black="black", white="white")

289

290

enhanced.save(save_path)

291

return enhanced

292

293

# Process an image

294

enhanced = enhance_image_auto("photo.jpg", "enhanced_photo.jpg")

295

```

296

297

### Professional Photo Resizing

298

299

```python

300

from PIL import Image, ImageOps

301

302

def resize_for_web(image_path, max_size=(800, 600), quality=85):

303

"""Resize image for web use with proper aspect ratio handling."""

304

img = Image.open(image_path)

305

306

# Method 1: Contain - fits within bounds

307

contained = ImageOps.contain(img, max_size, method=Image.Resampling.LANCZOS)

308

contained.save("web_contained.jpg", "JPEG", quality=quality, optimize=True)

309

310

# Method 2: Cover - fills entire area, may crop

311

covered = ImageOps.cover(img, max_size, method=Image.Resampling.LANCZOS)

312

covered.save("web_covered.jpg", "JPEG", quality=quality, optimize=True)

313

314

# Method 3: Fit with cropping control

315

fitted = ImageOps.fit(img, max_size, method=Image.Resampling.LANCZOS,

316

centering=(0.5, 0.4)) # Center horizontally, slightly above center vertically

317

fitted.save("web_fitted.jpg", "JPEG", quality=quality, optimize=True)

318

319

# Method 4: Pad to exact size

320

padded = ImageOps.pad(img, max_size, method=Image.Resampling.LANCZOS,

321

color="white", centering=(0.5, 0.5))

322

padded.save("web_padded.jpg", "JPEG", quality=quality, optimize=True)

323

324

resize_for_web("original_photo.jpg")

325

```

326

327

### Creative Color Effects

328

329

```python

330

from PIL import Image, ImageOps

331

332

def create_artistic_effects(image_path):

333

"""Create various artistic effects using ImageOps."""

334

img = Image.open(image_path)

335

336

# Convert to grayscale first for colorization effects

337

gray = ImageOps.grayscale(img)

338

339

# Sepia tone effect

340

sepia = ImageOps.colorize(gray, black="black", white="#FFF8DC", mid="#CD853F")

341

sepia.save("sepia_effect.jpg")

342

343

# Cool blue tone

344

cool = ImageOps.colorize(gray, black="#000080", white="#E6F3FF", mid="#4169E1")

345

cool.save("cool_effect.jpg")

346

347

# Warm orange tone

348

warm = ImageOps.colorize(gray, black="#2F1B14", white="#FFF8DC", mid="#FF8C00")

349

warm.save("warm_effect.jpg")

350

351

# High contrast black and white

352

high_contrast = ImageOps.autocontrast(gray, cutoff=5)

353

high_contrast.save("high_contrast.jpg")

354

355

# Posterized effect

356

posterized = ImageOps.posterize(img, bits=4)

357

posterized.save("posterized.jpg")

358

359

# Solarization effect

360

solarized = ImageOps.solarize(img, threshold=100)

361

solarized.save("solarized.jpg")

362

363

# Inverted colors (negative)

364

inverted = ImageOps.invert(img)

365

inverted.save("inverted.jpg")

366

367

create_artistic_effects("portrait.jpg")

368

```

369

370

### Batch Image Processing

371

372

```python

373

from PIL import Image, ImageOps

374

import os

375

import glob

376

377

def batch_process_images(input_dir, output_dir, target_size=(1024, 768)):

378

"""Batch process images in a directory."""

379

380

# Create output directory if it doesn't exist

381

os.makedirs(output_dir, exist_ok=True)

382

383

# Find all image files

384

image_extensions = ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.tiff"]

385

image_files = []

386

for ext in image_extensions:

387

image_files.extend(glob.glob(os.path.join(input_dir, ext)))

388

image_files.extend(glob.glob(os.path.join(input_dir, ext.upper())))

389

390

for image_path in image_files:

391

try:

392

filename = os.path.basename(image_path)

393

name, ext = os.path.splitext(filename)

394

395

# Open and process image

396

img = Image.open(image_path)

397

398

# Fix orientation based on EXIF

399

if hasattr(img, '_getexif') and img._getexif():

400

img = ImageOps.exif_transpose(img)

401

402

# Resize while maintaining aspect ratio

403

processed = ImageOps.contain(img, target_size, method=Image.Resampling.LANCZOS)

404

405

# Auto-enhance

406

processed = ImageOps.autocontrast(processed, cutoff=1)

407

408

# Save processed image

409

output_path = os.path.join(output_dir, f"{name}_processed{ext}")

410

if ext.lower() in ['.jpg', '.jpeg']:

411

processed.save(output_path, "JPEG", quality=90, optimize=True)

412

else:

413

processed.save(output_path)

414

415

print(f"Processed: {filename}")

416

417

except Exception as e:

418

print(f"Error processing {filename}: {e}")

419

420

# Process all images in a directory

421

batch_process_images("input_photos", "output_photos", target_size=(800, 600))

422

```

423

424

### Image Borders and Frames

425

426

```python

427

from PIL import Image, ImageOps

428

429

def add_decorative_border(image_path, border_size=20, border_color="white"):

430

"""Add decorative border to image."""

431

img = Image.open(image_path)

432

433

# Simple border

434

bordered = ImageOps.expand(img, border=border_size, fill=border_color)

435

bordered.save("simple_border.jpg")

436

437

# Fancy multi-layer border

438

# Inner border

439

bordered = ImageOps.expand(img, border=5, fill="black")

440

# Middle border

441

bordered = ImageOps.expand(bordered, border=15, fill="white")

442

# Outer border

443

bordered = ImageOps.expand(bordered, border=3, fill="gray")

444

bordered.save("fancy_border.jpg")

445

446

# Asymmetric border (different sizes for each side)

447

# Using crop with negative values adds border

448

width, height = img.size

449

expanded = Image.new(img.mode, (width + 100, height + 60), "lightgray")

450

expanded.paste(img, (50, 20)) # Offset creates border

451

expanded.save("asymmetric_border.jpg")

452

453

add_decorative_border("photo.jpg")

454

```

455

456

### Smart Cropping and Composition

457

458

```python

459

from PIL import Image, ImageOps

460

461

def smart_crop_portraits(image_path):

462

"""Demonstrate different cropping strategies for portraits."""

463

img = Image.open(image_path)

464

465

# Square crop for profile pictures - center on upper portion

466

square_size = min(img.size)

467

square = ImageOps.fit(img, (square_size, square_size),

468

method=Image.Resampling.LANCZOS,

469

centering=(0.5, 0.3)) # Center horizontally, upper third vertically

470

square.save("profile_square.jpg")

471

472

# 16:9 crop for social media

473

aspect_16_9 = (1920, 1080)

474

social = ImageOps.fit(img, aspect_16_9,

475

method=Image.Resampling.LANCZOS,

476

centering=(0.5, 0.4))

477

# Scale down to reasonable size

478

social = ImageOps.contain(social, (800, 450), method=Image.Resampling.LANCZOS)

479

social.save("social_media.jpg")

480

481

# 4:5 crop for Instagram

482

instagram_ratio = (800, 1000)

483

instagram = ImageOps.fit(img, instagram_ratio,

484

method=Image.Resampling.LANCZOS,

485

centering=(0.5, 0.35))

486

instagram.save("instagram_crop.jpg")

487

488

smart_crop_portraits("portrait.jpg")

489

```

490

491

### Orientation Handling

492

493

```python

494

from PIL import Image, ImageOps

495

496

def handle_image_orientation(image_path):

497

"""Properly handle image orientation using EXIF data."""

498

img = Image.open(image_path)

499

500

print(f"Original size: {img.size}")

501

print(f"Original mode: {img.mode}")

502

503

# Check for EXIF orientation data

504

if hasattr(img, '_getexif') and img._getexif():

505

exif = img._getexif()

506

if exif and 274 in exif: # 274 is the orientation tag

507

orientation = exif[274]

508

print(f"EXIF orientation: {orientation}")

509

510

# Fix orientation automatically

511

corrected = ImageOps.exif_transpose(img)

512

if corrected is not None:

513

print(f"Corrected size: {corrected.size}")

514

corrected.save("orientation_corrected.jpg")

515

else:

516

print("No orientation correction needed")

517

img.save("orientation_corrected.jpg")

518

519

# Manual orientation operations

520

flipped_v = ImageOps.flip(img) # Vertical flip

521

flipped_h = ImageOps.mirror(img) # Horizontal flip

522

523

flipped_v.save("flipped_vertical.jpg")

524

flipped_h.save("flipped_horizontal.jpg")

525

526

handle_image_orientation("photo_with_exif.jpg")

527

```

528

529

### Image Quality Enhancement Pipeline

530

531

```python

532

from PIL import Image, ImageOps

533

534

def enhance_image_quality(image_path, output_path):

535

"""Professional image enhancement pipeline."""

536

img = Image.open(image_path)

537

538

# Step 1: Fix orientation

539

img = ImageOps.exif_transpose(img) or img

540

541

# Step 2: Crop unwanted borders (remove 1% from each edge)

542

width, height = img.size

543

crop_amount = min(width, height) * 0.01

544

img = ImageOps.crop(img, border=int(crop_amount))

545

546

# Step 3: Gentle auto-contrast (preserve most of the original look)

547

img = ImageOps.autocontrast(img, cutoff=0.5)

548

549

# Step 4: Subtle histogram equalization on luminance only

550

if img.mode == "RGB":

551

# Convert to HSV, equalize V channel, convert back

552

import colorsys

553

# This is a simplified approach - in practice you'd use proper color space conversion

554

img = ImageOps.autocontrast(img, cutoff=1.0)

555

556

# Step 5: Resize to target resolution if needed

557

max_dimension = 2048

558

if max(img.size) > max_dimension:

559

img = ImageOps.contain(img, (max_dimension, max_dimension),

560

method=Image.Resampling.LANCZOS)

561

562

# Save with optimal quality

563

img.save(output_path, "JPEG", quality=95, optimize=True)

564

return img

565

566

# Enhance image quality

567

enhanced = enhance_image_quality("raw_photo.jpg", "enhanced_photo.jpg")

568

```