Library for reading and writing a wide range of image, video, scientific, and volumetric data formats.
—
Low-level interfaces for manual control over reading and writing operations, providing fine-grained parameter access and custom workflow support.
Get reader objects for manual, sequential, or custom reading workflows.
def get_reader(uri, format=None, mode="?", **kwargs):
"""
Get a Reader object for manual reading operations.
Parameters:
- uri (ImageResource): File path, URL, bytes, or file object
- format (str, optional): Format to use for reading
- mode (str): Reader mode hint
- 'i': single image
- 'I': multiple images
- 'v': single volume
- 'V': multiple volumes
- '?': don't care (default)
- **kwargs: Format-specific parameters
Returns:
- Reader: Reader object with manual control methods
"""Usage Examples:
import imageio.v2 as imageio
# Basic reader usage
reader = imageio.get_reader('animation.gif')
try:
print(f"Number of frames: {len(reader)}")
print(f"Format: {reader.format}")
# Read frames individually
frame_0 = reader.get_data(0)
frame_5 = reader.get_data(5)
# Get metadata
global_meta = reader.get_meta_data()
frame_meta = reader.get_meta_data(3)
# Iterate through frames
for i, frame in enumerate(reader):
print(f"Frame {i}: {frame.shape}")
if i >= 10: # Process first 10 frames only
break
finally:
reader.close() # Always close reader
# Context manager usage (recommended)
with imageio.get_reader('video.mp4') as reader:
print(f"Video length: {len(reader)} frames")
# Skip frames efficiently
for i in range(0, len(reader), 30): # Every 30th frame
frame = reader.get_data(i)
process_frame(frame, i) # Your processing functionGet writer objects for manual, streaming, or custom writing workflows.
def get_writer(uri, format=None, mode="?", **kwargs):
"""
Get a Writer object for manual writing operations.
Parameters:
- uri (ImageResource): Output path or file object
- format (str, optional): Format to use for writing
- mode (str): Writer mode hint
- 'i': single image
- 'I': multiple images
- 'v': single volume
- 'V': multiple volumes
- '?': don't care (default)
- **kwargs: Format-specific parameters
Returns:
- Writer: Writer object with manual control methods
"""Usage Examples:
import imageio.v2 as imageio
import numpy as np
# Create animation frame by frame
with imageio.get_writer('animation.gif', duration=0.5) as writer:
for i in range(20):
# Generate frame dynamically
frame = np.zeros((100, 100, 3), dtype=np.uint8)
# Create rotating pattern
angle = i * 18 # degrees
x = int(50 + 30 * np.cos(np.radians(angle)))
y = int(50 + 30 * np.sin(np.radians(angle)))
frame[y-5:y+5, x-5:x+5] = [255, 0, 0] # Red dot
writer.append_data(frame)
# Optional: set per-frame metadata
frame_meta = {'frame_time': i * 0.5}
# Note: metadata support varies by format
# Write video with custom parameters
with imageio.get_writer('output.mp4', fps=30, codec='libx264') as writer:
for frame_data in generate_frames(): # Your frame generator
writer.append_data(frame_data)
# Manual writer control (not recommended for normal use)
writer = imageio.get_writer('manual.png')
try:
# For single images, append_data writes the image
image = np.random.randint(0, 255, (200, 200, 3), dtype=np.uint8)
writer.append_data(image)
# Set global metadata if supported
try:
writer.set_meta_data({'software': 'ImageIO Example'})
except NotImplementedError:
print("Format doesn't support metadata writing")
finally:
writer.close()class Reader:
"""Reader object for manual image reading control."""
def get_length(self):
"""Get number of images in the file."""
def get_data(self, index):
"""Get image data at specific index."""
def get_next_data(self):
"""Get next image in sequence."""
def get_meta_data(self, index=None):
"""Get metadata for image or global metadata."""
def set_image_index(self, index):
"""Set current reading position."""
def close(self):
"""Close the reader and free resources."""
def iter_data(self):
"""Iterate over all images with metadata."""
# Properties
request: Request # Request object with file info
format: Format # Format object (legacy plugins only)Detailed Usage:
import imageio.v2 as imageio
with imageio.get_reader('multi_page.tiff') as reader:
# Length and basic info
total_images = reader.get_length()
print(f"Total images: {total_images}")
# Access request information
print(f"Filename: {reader.request.filename}")
print(f"File size: {reader.request.get_file().seek(0, 2)}")
# Random access to images
middle_image = reader.get_data(total_images // 2)
last_image = reader.get_data(-1) # Last image
# Sequential reading with position control
reader.set_image_index(10) # Start from image 10
for i in range(5): # Read next 5 images
image = reader.get_next_data()
print(f"Image {10+i}: {image.shape}")
# Metadata access
global_meta = reader.get_meta_data() # Global file metadata
for i in range(min(3, total_images)): # First 3 images
image_meta = reader.get_meta_data(i)
print(f"Image {i} metadata: {image_meta}")
# Iteration with metadata
for image_with_meta in reader.iter_data():
print(f"Image shape: {image_with_meta.shape}")
print(f"Metadata: {image_with_meta.meta}")class Writer:
"""Writer object for manual image writing control."""
def append_data(self, im, meta=None):
"""Add image data to output."""
def set_meta_data(self, meta):
"""Set global metadata for output file."""
def close(self):
"""Close writer and finalize output."""
# Properties
request: Request # Request object with file info
format: Format # Format object (legacy plugins only)Detailed Usage:
import imageio.v2 as imageio
import numpy as np
from datetime import datetime
# Create multi-page TIFF with metadata
with imageio.get_writer('output.tiff', compression='lzw') as writer:
# Set global metadata
global_meta = {
'software': 'ImageIO Python',
'datetime': datetime.now().isoformat(),
'description': 'Multi-page TIFF created with ImageIO'
}
try:
writer.set_meta_data(global_meta)
except NotImplementedError:
print("This format doesn't support global metadata")
# Add images with individual metadata
for i in range(5):
# Create test image
image = np.random.randint(0, 255, (100, 100), dtype=np.uint8)
# Per-image metadata
image_meta = {
'page_number': i,
'timestamp': datetime.now().timestamp()
}
# Append image (metadata support varies by format)
writer.append_data(image, meta=image_meta)
print(f"Written to: {writer.request.filename}")Handle large files without loading everything into memory:
import imageio.v2 as imageio
import numpy as np
def process_large_video(input_path, output_path, processing_func):
"""Process large video file frame by frame."""
with imageio.get_reader(input_path) as reader:
# Get video properties
total_frames = len(reader)
first_frame = reader.get_data(0)
height, width = first_frame.shape[:2]
print(f"Processing {total_frames} frames of size {height}x{width}")
# Reset to beginning
reader.set_image_index(0)
with imageio.get_writer(output_path, fps=30) as writer:
for frame_num in range(total_frames):
# Read frame
frame = reader.get_data(frame_num)
# Process frame
processed_frame = processing_func(frame)
# Write processed frame
writer.append_data(processed_frame)
# Progress indicator
if frame_num % 100 == 0:
print(f"Processed {frame_num}/{total_frames} frames")
# Example processing function
def enhance_contrast(frame):
"""Simple contrast enhancement."""
frame = frame.astype(np.float32)
frame = (frame - frame.min()) / (frame.max() - frame.min()) * 255
return frame.astype(np.uint8)
# Usage
process_large_video('input_video.mp4', 'enhanced_video.mp4', enhance_contrast)Handle files that need special parameter control:
import imageio.v2 as imageio
def read_scientific_data(file_path, calibration_params):
"""Read scientific data with custom calibration."""
with imageio.get_reader(file_path, format='TIFF') as reader:
# Get calibration from metadata if available
global_meta = reader.get_meta_data()
# Override with provided calibration
pixel_size = calibration_params.get('pixel_size', 1.0)
units = calibration_params.get('units', 'pixels')
print(f"Reading {len(reader)} images with {pixel_size} {units}/pixel")
calibrated_images = []
for i in range(len(reader)):
# Read raw image
raw_image = reader.get_data(i)
image_meta = reader.get_meta_data(i)
# Apply calibration (example: convert to physical units)
calibrated_image = raw_image * pixel_size
# Attach enhanced metadata
enhanced_meta = {
**image_meta,
'pixel_size': pixel_size,
'units': units,
'calibrated': True
}
# Create Array with metadata
from imageio.core import Array
calibrated_array = Array(calibrated_image)
calibrated_array.meta = enhanced_meta
calibrated_images.append(calibrated_array)
return calibrated_images
# Usage
calibration = {'pixel_size': 0.1, 'units': 'micrometers'}
calibrated_data = read_scientific_data('microscopy.tiff', calibration)Robust file handling with error recovery:
import imageio.v2 as imageio
import numpy as np
def robust_multi_image_read(file_path, max_errors=5):
"""Read multi-image file with error recovery."""
try:
reader = imageio.get_reader(file_path)
except Exception as e:
print(f"Cannot open {file_path}: {e}")
return []
valid_images = []
error_count = 0
try:
total_length = len(reader)
print(f"Attempting to read {total_length} images")
for i in range(total_length):
try:
# Attempt to read image
image = reader.get_data(i)
# Validate image
if image.size == 0:
raise ValueError("Empty image")
if not np.isfinite(image).all():
raise ValueError("Invalid pixel values")
valid_images.append(image)
except Exception as e:
error_count += 1
print(f"Error reading image {i}: {e}")
if error_count >= max_errors:
print(f"Too many errors ({error_count}), stopping")
break
# Continue with next image
continue
finally:
reader.close()
print(f"Successfully read {len(valid_images)} images with {error_count} errors")
return valid_images
# Usage
images = robust_multi_image_read('potentially_corrupted.tiff', max_errors=10)Install with Tessl CLI
npx tessl i tessl/pypi-imageio