Library for reading and writing a wide range of image, video, scientific, and volumetric data formats.
—
Streamlined interface with context managers, unified resource handling, and enhanced metadata access designed for modern Python development patterns.
Open image resources using context managers for automatic cleanup and resource management.
def imopen(uri, io_mode, *, plugin=None, extension=None, format_hint=None,
legacy_mode=False, **kwargs):
"""
Open an ImageResource with context manager support.
Parameters:
- uri (ImageResource): File path, URL, bytes, or file object
- io_mode (str): 'r' for reading, 'w' for writing
- plugin (str, optional): Specific plugin to use
- extension (str, optional): Treat resource as having this extension
- format_hint (str, optional): Deprecated, use extension instead
- legacy_mode (bool): Enable v2 compatibility mode
- **kwargs: Plugin-specific parameters
Returns:
- PluginV3: Plugin instance for the opened resource
Warning: Remember to close plugin when not using context manager (PyPy)
"""Usage Examples:
import imageio.v3 as iio
# Basic usage with context manager
with iio.imopen('image.jpg', 'r') as img_file:
image = img_file.read()
properties = img_file.properties()
metadata = img_file.metadata()
print(f"Shape: {properties.shape}")
# Writing with context manager
import numpy as np
image = np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)
with iio.imopen('output.jpg', 'w') as img_file:
img_file.write(image)
# Specify plugin explicitly
with iio.imopen('data.raw', 'r', plugin='RAW-FI') as img_file:
raw_data = img_file.read()
# Manual resource management (ensure cleanup)
img_file = iio.imopen('image.png', 'r')
try:
image = img_file.read()
finally:
img_file.close()Read images with enhanced control and modern Python patterns.
def imread(uri, *, index=None, plugin=None, extension=None,
format_hint=None, **kwargs):
"""
Read an ndimage from a URI using v3 API.
Parameters:
- uri (ImageResource): Resource to read from
- index (int|Ellipsis|None):
- int: Select specific image by index
- ...: Read all images and stack along batch dimension
- None: Let plugin decide (usually first image)
- plugin (str, optional): Plugin to use
- extension (str, optional): Treat resource as this extension
- format_hint (str, optional): Deprecated, use extension
- **kwargs: Plugin-specific parameters
Returns:
- np.ndarray: Image data as numpy array
"""Usage Examples:
import imageio.v3 as iio
# Basic reading
image = iio.imread('photo.jpg')
print(f"Shape: {image.shape}, dtype: {image.dtype}")
# Read specific frame from multi-image file
frame_5 = iio.imread('animation.gif', index=5)
# Read all frames and stack them
all_frames = iio.imread('animation.gif', index=...)
print(f"Stacked shape: {all_frames.shape}") # (n_frames, height, width, channels)
# Read with specific plugin
image = iio.imread('data.tiff', plugin='tifffile')
# Read with format hint
image = iio.imread('ambiguous_file', extension='.png')Write images with unified interface and enhanced control.
def imwrite(uri, image, *, plugin=None, extension=None,
format_hint=None, **kwargs):
"""
Write an ndimage to the given URI using v3 API.
Parameters:
- uri (ImageResource): Resource to write to
- image (ArrayLike): Image data to write
- plugin (str, optional): Plugin to use
- extension (str, optional): Treat resource as this extension
- format_hint (str, optional): Deprecated, use extension
- **kwargs: Plugin-specific parameters
Returns:
- None: When writing to file
- bytes: When uri is '<bytes>'
"""Usage Examples:
import imageio.v3 as iio
import numpy as np
# Basic writing
image = np.random.randint(0, 255, (200, 300, 3), dtype=np.uint8)
iio.imwrite('output.png', image)
# Write with specific plugin
iio.imwrite('output.tiff', image, plugin='tifffile')
# Write as bytes
png_bytes = iio.imwrite('<bytes>', image, extension='.png')
# Write with quality settings
iio.imwrite('high_quality.jpg', image, quality=95)
# Write multi-dimensional array as stack
volume = np.random.randint(0, 255, (10, 100, 100), dtype=np.uint8)
iio.imwrite('stack.tiff', volume)Iterate through images in a file with memory-efficient streaming.
def imiter(uri, *, plugin=None, extension=None, format_hint=None, **kwargs):
"""
Iterate over ndimages in a URI.
Parameters:
- uri (ImageResource): Resource to iterate over
- plugin (str, optional): Plugin to use
- extension (str, optional): Treat resource as this extension
- format_hint (str, optional): Deprecated, use extension
- **kwargs: Plugin-specific parameters
Yields:
- np.ndarray: Next image in the sequence
"""Usage Examples:
import imageio.v3 as iio
# Iterate through GIF frames
for i, frame in enumerate(iio.imiter('animation.gif')):
print(f"Frame {i}: {frame.shape}")
# Process frame without loading all frames into memory
# Iterate through video frames
for frame_num, frame in enumerate(iio.imiter('video.mp4')):
if frame_num % 30 == 0: # Process every 30th frame
processed = process_frame(frame) # Your processing function
iio.imwrite(f'frame_{frame_num:06d}.jpg', processed)
# Iterate with plugin specification
for page in iio.imiter('document.pdf', plugin='pillow'):
print(f"Page shape: {page.shape}")
# Process large TIFF stack efficiently
total_intensity = 0
frame_count = 0
for slice_img in iio.imiter('large_stack.tiff'):
total_intensity += slice_img.mean()
frame_count += 1
average_intensity = total_intensity / frame_count
print(f"Average intensity across {frame_count} slices: {average_intensity}")Get standardized image properties without loading pixel data.
def improps(uri, *, index=None, plugin=None, extension=None, **kwargs):
"""
Read standardized metadata/properties.
Parameters:
- uri (ImageResource): Resource to analyze
- index (int|Ellipsis|None): Which image to analyze
- plugin (str, optional): Plugin to use
- extension (str, optional): Treat resource as this extension
- **kwargs: Plugin-specific parameters
Returns:
- ImageProperties: Standardized properties dataclass
"""Usage Examples:
import imageio.v3 as iio
# Get properties without loading pixel data
props = iio.improps('large_image.tiff')
print(f"Shape: {props.shape}")
print(f"Data type: {props.dtype}")
print(f"Number of images: {props.n_images}")
print(f"Is batch: {props.is_batch}")
print(f"Spacing: {props.spacing}")
# Check properties of specific frame
props_frame_10 = iio.improps('animation.gif', index=10)
# Check properties of all frames stacked
props_all = iio.improps('animation.gif', index=...)
print(f"Stacked shape: {props_all.shape}") # Includes batch dimension
# Use properties to decide processing strategy
if props.n_images > 100:
print("Large multi-image file, use iteration")
for frame in iio.imiter('large_file.tiff'):
process_frame(frame)
else:
print("Small file, load all at once")
images = iio.imread('small_file.tiff', index=...)Access detailed, format-specific metadata.
def immeta(uri, *, index=None, plugin=None, extension=None,
exclude_applied=True, **kwargs):
"""
Read format-specific metadata.
Parameters:
- uri (ImageResource): Resource to analyze
- index (int|Ellipsis|None): Which image's metadata to read
- plugin (str, optional): Plugin to use
- extension (str, optional): Treat resource as this extension
- exclude_applied (bool): Exclude already-applied transformations
- **kwargs: Plugin-specific parameters
Returns:
- dict: Format-specific metadata dictionary
"""Usage Examples:
import imageio.v3 as iio
# Get EXIF data from JPEG
jpeg_meta = iio.immeta('photo.jpg')
print("EXIF data:", jpeg_meta.get('exif', {}))
print("Camera make:", jpeg_meta.get('exif', {}).get('Make', 'Unknown'))
# Get TIFF metadata
tiff_meta = iio.immeta('microscopy.tiff')
print("TIFF tags:", tiff_meta)
print("Resolution:", tiff_meta.get('resolution', 'Unknown'))
# Get global metadata (index=...)
global_meta = iio.immeta('multi_image.tiff', index=...)
print("Global metadata:", global_meta)
# Get metadata for specific frame
frame_meta = iio.immeta('animation.gif', index=5)
print("Frame 5 metadata:", frame_meta)
# Include applied transformations in metadata
full_meta = iio.immeta('image.jpg', exclude_applied=False)
print("Full metadata including applied transforms:", full_meta)Control plugin selection explicitly:
import imageio.v3 as iio
# List available plugins for a format
# (Check imageio.config.known_plugins for available options)
# Force specific plugin usage
image = iio.imread('image.tiff', plugin='tifffile') # Use tifffile plugin
image = iio.imread('image.tiff', plugin='pillow') # Use pillow plugin
# Use extension hint to influence plugin selection
image = iio.imread('ambiguous_file', extension='.jpg')
# Modern approach replaces legacy format parameter
# Old v2 style: imread('file.jpg', format='JPEG-PIL')
# New v3 style: imread('file.jpg', plugin='pillow')Efficient batch operations using modern patterns:
import imageio.v3 as iio
from pathlib import Path
import numpy as np
def process_images_v3(input_dir, output_dir, operation='grayscale'):
"""Process images using v3 API patterns."""
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
for img_file in input_path.glob('*.jpg'):
try:
# Check properties first
props = iio.improps(img_file)
print(f"Processing {img_file.name}: {props.shape}")
# Read and process
image = iio.imread(img_file)
if operation == 'grayscale' and len(props.shape) == 3:
# Convert to grayscale
processed = np.mean(image, axis=2).astype(image.dtype)
elif operation == 'thumbnail':
# Simple downsampling (for demo)
processed = image[::4, ::4] # Every 4th pixel
else:
processed = image
# Write result
output_file = output_path / f"processed_{img_file.name}"
iio.imwrite(output_file, processed)
except Exception as e:
print(f"Error processing {img_file.name}: {e}")
# Usage
process_images_v3('input_photos', 'output_photos', 'grayscale')V3 API provides enhanced error information:
import imageio.v3 as iio
# Comprehensive error handling
def safe_image_read(uri):
"""Safely read an image with detailed error handling."""
try:
# First check if we can get properties
props = iio.improps(uri)
print(f"File properties: {props.shape}, {props.dtype}")
# Then read the image
image = iio.imread(uri)
return image, None
except FileNotFoundError:
return None, "File not found"
except PermissionError:
return None, "Permission denied"
except Exception as e:
# Check if it's a plugin-specific error
error_msg = str(e)
if "plugin" in error_msg.lower():
return None, f"Plugin error: {error_msg}"
else:
return None, f"General error: {error_msg}"
# Usage
image, error = safe_image_read('problematic_file.jpg')
if error:
print(f"Failed to read image: {error}")
else:
print(f"Successfully read image: {image.shape}")Advanced context manager usage:
import imageio.v3 as iio
# Process multiple files with shared plugin instance
def batch_process_with_context():
"""Demonstrate efficient context manager usage."""
# Reading multiple images with same plugin
with iio.imopen('first_image.tiff', 'r', plugin='tifffile') as img_file:
props = img_file.properties()
print(f"First image: {props.shape}")
# Plugin instance can read multiple "pages" if supported
if hasattr(img_file, 'iter'):
for i, page in enumerate(img_file.iter()):
print(f"Page {i}: {page.shape}")
# Writing multiple related files
images = [np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)
for _ in range(3)]
for i, image in enumerate(images):
with iio.imopen(f'output_{i:03d}.png', 'w') as img_file:
img_file.write(image)
# Nested context managers for complex operations
def complex_processing():
"""Complex processing with multiple resources."""
with iio.imopen('input.tiff', 'r') as reader:
with iio.imopen('output.tiff', 'w') as writer:
for page in reader.iter():
# Process each page
processed = apply_processing(page) # Your processing
writer.write(processed)
batch_process_with_context()Install with Tessl CLI
npx tessl i tessl/pypi-imageio