0
# Reader/Writer Objects
1
2
Low-level interfaces for manual control over reading and writing operations, providing fine-grained parameter access and custom workflow support.
3
4
## Capabilities
5
6
### Reader Objects
7
8
Get reader objects for manual, sequential, or custom reading workflows.
9
10
```python { .api }
11
def get_reader(uri, format=None, mode="?", **kwargs):
12
"""
13
Get a Reader object for manual reading operations.
14
15
Parameters:
16
- uri (ImageResource): File path, URL, bytes, or file object
17
- format (str, optional): Format to use for reading
18
- mode (str): Reader mode hint
19
- 'i': single image
20
- 'I': multiple images
21
- 'v': single volume
22
- 'V': multiple volumes
23
- '?': don't care (default)
24
- **kwargs: Format-specific parameters
25
26
Returns:
27
- Reader: Reader object with manual control methods
28
"""
29
```
30
31
**Usage Examples:**
32
33
```python
34
import imageio.v2 as imageio
35
36
# Basic reader usage
37
reader = imageio.get_reader('animation.gif')
38
39
try:
40
print(f"Number of frames: {len(reader)}")
41
print(f"Format: {reader.format}")
42
43
# Read frames individually
44
frame_0 = reader.get_data(0)
45
frame_5 = reader.get_data(5)
46
47
# Get metadata
48
global_meta = reader.get_meta_data()
49
frame_meta = reader.get_meta_data(3)
50
51
# Iterate through frames
52
for i, frame in enumerate(reader):
53
print(f"Frame {i}: {frame.shape}")
54
if i >= 10: # Process first 10 frames only
55
break
56
57
finally:
58
reader.close() # Always close reader
59
60
# Context manager usage (recommended)
61
with imageio.get_reader('video.mp4') as reader:
62
print(f"Video length: {len(reader)} frames")
63
64
# Skip frames efficiently
65
for i in range(0, len(reader), 30): # Every 30th frame
66
frame = reader.get_data(i)
67
process_frame(frame, i) # Your processing function
68
```
69
70
### Writer Objects
71
72
Get writer objects for manual, streaming, or custom writing workflows.
73
74
```python { .api }
75
def get_writer(uri, format=None, mode="?", **kwargs):
76
"""
77
Get a Writer object for manual writing operations.
78
79
Parameters:
80
- uri (ImageResource): Output path or file object
81
- format (str, optional): Format to use for writing
82
- mode (str): Writer mode hint
83
- 'i': single image
84
- 'I': multiple images
85
- 'v': single volume
86
- 'V': multiple volumes
87
- '?': don't care (default)
88
- **kwargs: Format-specific parameters
89
90
Returns:
91
- Writer: Writer object with manual control methods
92
"""
93
```
94
95
**Usage Examples:**
96
97
```python
98
import imageio.v2 as imageio
99
import numpy as np
100
101
# Create animation frame by frame
102
with imageio.get_writer('animation.gif', duration=0.5) as writer:
103
for i in range(20):
104
# Generate frame dynamically
105
frame = np.zeros((100, 100, 3), dtype=np.uint8)
106
107
# Create rotating pattern
108
angle = i * 18 # degrees
109
x = int(50 + 30 * np.cos(np.radians(angle)))
110
y = int(50 + 30 * np.sin(np.radians(angle)))
111
frame[y-5:y+5, x-5:x+5] = [255, 0, 0] # Red dot
112
113
writer.append_data(frame)
114
115
# Optional: set per-frame metadata
116
frame_meta = {'frame_time': i * 0.5}
117
# Note: metadata support varies by format
118
119
# Write video with custom parameters
120
with imageio.get_writer('output.mp4', fps=30, codec='libx264') as writer:
121
for frame_data in generate_frames(): # Your frame generator
122
writer.append_data(frame_data)
123
124
# Manual writer control (not recommended for normal use)
125
writer = imageio.get_writer('manual.png')
126
try:
127
# For single images, append_data writes the image
128
image = np.random.randint(0, 255, (200, 200, 3), dtype=np.uint8)
129
writer.append_data(image)
130
131
# Set global metadata if supported
132
try:
133
writer.set_meta_data({'software': 'ImageIO Example'})
134
except NotImplementedError:
135
print("Format doesn't support metadata writing")
136
finally:
137
writer.close()
138
```
139
140
## Reader Methods and Properties
141
142
### Core Reader Methods
143
144
```python { .api }
145
class Reader:
146
"""Reader object for manual image reading control."""
147
148
def get_length(self):
149
"""Get number of images in the file."""
150
151
def get_data(self, index):
152
"""Get image data at specific index."""
153
154
def get_next_data(self):
155
"""Get next image in sequence."""
156
157
def get_meta_data(self, index=None):
158
"""Get metadata for image or global metadata."""
159
160
def set_image_index(self, index):
161
"""Set current reading position."""
162
163
def close(self):
164
"""Close the reader and free resources."""
165
166
def iter_data(self):
167
"""Iterate over all images with metadata."""
168
169
# Properties
170
request: Request # Request object with file info
171
format: Format # Format object (legacy plugins only)
172
```
173
174
**Detailed Usage:**
175
176
```python
177
import imageio.v2 as imageio
178
179
with imageio.get_reader('multi_page.tiff') as reader:
180
# Length and basic info
181
total_images = reader.get_length()
182
print(f"Total images: {total_images}")
183
184
# Access request information
185
print(f"Filename: {reader.request.filename}")
186
print(f"File size: {reader.request.get_file().seek(0, 2)}")
187
188
# Random access to images
189
middle_image = reader.get_data(total_images // 2)
190
last_image = reader.get_data(-1) # Last image
191
192
# Sequential reading with position control
193
reader.set_image_index(10) # Start from image 10
194
for i in range(5): # Read next 5 images
195
image = reader.get_next_data()
196
print(f"Image {10+i}: {image.shape}")
197
198
# Metadata access
199
global_meta = reader.get_meta_data() # Global file metadata
200
for i in range(min(3, total_images)): # First 3 images
201
image_meta = reader.get_meta_data(i)
202
print(f"Image {i} metadata: {image_meta}")
203
204
# Iteration with metadata
205
for image_with_meta in reader.iter_data():
206
print(f"Image shape: {image_with_meta.shape}")
207
print(f"Metadata: {image_with_meta.meta}")
208
```
209
210
## Writer Methods and Properties
211
212
### Core Writer Methods
213
214
```python { .api }
215
class Writer:
216
"""Writer object for manual image writing control."""
217
218
def append_data(self, im, meta=None):
219
"""Add image data to output."""
220
221
def set_meta_data(self, meta):
222
"""Set global metadata for output file."""
223
224
def close(self):
225
"""Close writer and finalize output."""
226
227
# Properties
228
request: Request # Request object with file info
229
format: Format # Format object (legacy plugins only)
230
```
231
232
**Detailed Usage:**
233
234
```python
235
import imageio.v2 as imageio
236
import numpy as np
237
from datetime import datetime
238
239
# Create multi-page TIFF with metadata
240
with imageio.get_writer('output.tiff', compression='lzw') as writer:
241
# Set global metadata
242
global_meta = {
243
'software': 'ImageIO Python',
244
'datetime': datetime.now().isoformat(),
245
'description': 'Multi-page TIFF created with ImageIO'
246
}
247
248
try:
249
writer.set_meta_data(global_meta)
250
except NotImplementedError:
251
print("This format doesn't support global metadata")
252
253
# Add images with individual metadata
254
for i in range(5):
255
# Create test image
256
image = np.random.randint(0, 255, (100, 100), dtype=np.uint8)
257
258
# Per-image metadata
259
image_meta = {
260
'page_number': i,
261
'timestamp': datetime.now().timestamp()
262
}
263
264
# Append image (metadata support varies by format)
265
writer.append_data(image, meta=image_meta)
266
267
print(f"Written to: {writer.request.filename}")
268
```
269
270
## Advanced Reader/Writer Patterns
271
272
### Streaming Large Files
273
274
Handle large files without loading everything into memory:
275
276
```python
277
import imageio.v2 as imageio
278
import numpy as np
279
280
def process_large_video(input_path, output_path, processing_func):
281
"""Process large video file frame by frame."""
282
283
with imageio.get_reader(input_path) as reader:
284
# Get video properties
285
total_frames = len(reader)
286
first_frame = reader.get_data(0)
287
height, width = first_frame.shape[:2]
288
289
print(f"Processing {total_frames} frames of size {height}x{width}")
290
291
# Reset to beginning
292
reader.set_image_index(0)
293
294
with imageio.get_writer(output_path, fps=30) as writer:
295
for frame_num in range(total_frames):
296
# Read frame
297
frame = reader.get_data(frame_num)
298
299
# Process frame
300
processed_frame = processing_func(frame)
301
302
# Write processed frame
303
writer.append_data(processed_frame)
304
305
# Progress indicator
306
if frame_num % 100 == 0:
307
print(f"Processed {frame_num}/{total_frames} frames")
308
309
# Example processing function
310
def enhance_contrast(frame):
311
"""Simple contrast enhancement."""
312
frame = frame.astype(np.float32)
313
frame = (frame - frame.min()) / (frame.max() - frame.min()) * 255
314
return frame.astype(np.uint8)
315
316
# Usage
317
process_large_video('input_video.mp4', 'enhanced_video.mp4', enhance_contrast)
318
```
319
320
### Custom Format Handling
321
322
Handle files that need special parameter control:
323
324
```python
325
import imageio.v2 as imageio
326
327
def read_scientific_data(file_path, calibration_params):
328
"""Read scientific data with custom calibration."""
329
330
with imageio.get_reader(file_path, format='TIFF') as reader:
331
# Get calibration from metadata if available
332
global_meta = reader.get_meta_data()
333
334
# Override with provided calibration
335
pixel_size = calibration_params.get('pixel_size', 1.0)
336
units = calibration_params.get('units', 'pixels')
337
338
print(f"Reading {len(reader)} images with {pixel_size} {units}/pixel")
339
340
calibrated_images = []
341
for i in range(len(reader)):
342
# Read raw image
343
raw_image = reader.get_data(i)
344
image_meta = reader.get_meta_data(i)
345
346
# Apply calibration (example: convert to physical units)
347
calibrated_image = raw_image * pixel_size
348
349
# Attach enhanced metadata
350
enhanced_meta = {
351
**image_meta,
352
'pixel_size': pixel_size,
353
'units': units,
354
'calibrated': True
355
}
356
357
# Create Array with metadata
358
from imageio.core import Array
359
calibrated_array = Array(calibrated_image)
360
calibrated_array.meta = enhanced_meta
361
362
calibrated_images.append(calibrated_array)
363
364
return calibrated_images
365
366
# Usage
367
calibration = {'pixel_size': 0.1, 'units': 'micrometers'}
368
calibrated_data = read_scientific_data('microscopy.tiff', calibration)
369
```
370
371
### Error Recovery and Validation
372
373
Robust file handling with error recovery:
374
375
```python
376
import imageio.v2 as imageio
377
import numpy as np
378
379
def robust_multi_image_read(file_path, max_errors=5):
380
"""Read multi-image file with error recovery."""
381
382
try:
383
reader = imageio.get_reader(file_path)
384
except Exception as e:
385
print(f"Cannot open {file_path}: {e}")
386
return []
387
388
valid_images = []
389
error_count = 0
390
391
try:
392
total_length = len(reader)
393
print(f"Attempting to read {total_length} images")
394
395
for i in range(total_length):
396
try:
397
# Attempt to read image
398
image = reader.get_data(i)
399
400
# Validate image
401
if image.size == 0:
402
raise ValueError("Empty image")
403
404
if not np.isfinite(image).all():
405
raise ValueError("Invalid pixel values")
406
407
valid_images.append(image)
408
409
except Exception as e:
410
error_count += 1
411
print(f"Error reading image {i}: {e}")
412
413
if error_count >= max_errors:
414
print(f"Too many errors ({error_count}), stopping")
415
break
416
417
# Continue with next image
418
continue
419
420
finally:
421
reader.close()
422
423
print(f"Successfully read {len(valid_images)} images with {error_count} errors")
424
return valid_images
425
426
# Usage
427
images = robust_multi_image_read('potentially_corrupted.tiff', max_errors=10)
428
```