imageio review
imageio 2.37.4 reads and writes still images, frame sequences, video, volumes, and scientific formats as NumPy arrays. New code uses imageio.v3 functions for reading, writing, iteration, properties, metadata, and direct plugin access. A plugin manager chooses Pillow or an optional backend from the resource and extension. The July 2026 release now attaches the missing filename to FileNotFoundError and includes documentation and dependency upkeep. Our base install worked, but TIFF, HEIC, raw, FITS, ITK, and video capabilities still depend on separate backend packages.
imageio 2.37.4 installed in 0.6 seconds, used 78 MB across three packages, and produced zero pip-audit findings in our sandbox. It is a good adapter for mixed NumPy image inputs; choose a format-specific library for editing, deep video control, or one fixed scientific format.
We installed it
| Install | ✓ · 0.6s | 3 packages on disk · 78 MB |
| Import | ✓ | import imageio in 0.58s · pure Python · py.typed · requires Python >=3.10 |
| Known vulns | 0 | (pip-audit) |
Answers from our run
Does imageio install cleanly?
Yes. In a fresh container with an empty cache, pip install imageio finished in 0.6s, leaving 3 packages and 78 MB on disk. pip-audit reported no known vulnerabilities.
What does imageio need to run?
Python >=3.10, and nothing compiled: it is pure Python. In our run import imageio succeeded in 0.58s, and the package ships py.typed for type checkers.
imageio or Pillow: which should you use?
Pillow: Use it for common still images when editing and drawing matter as much as file I/O. imageio 2.37.4 installed in 0.6 seconds, used 78 MB across three packages, and produced zero pip-audit findings in our sandbox.
When should you not use imageio?
The job is common still-image editing. Pillow already supplies the decoder plus resizing, drawing, mode conversion, and filters that imageio does not add.
Use it if
- One NumPy-facing API should accept several image or scientific file families.
- Videos and multi-page images need frame iteration without loading the complete series.
- Callers provide a mix of paths, URLs, byte buffers, and file-like objects.
- You need common shape and dtype properties while retaining access to a backend's native metadata.
- The job is common still-image editing. Pillow already supplies the decoder plus resizing, drawing, mode conversion, and filters that imageio does not add.
- You need video streams, timestamps, audio, seeking, and codec details. PyAV exposes those concepts directly, while imageio presents decoded frames.
- Every listed format must work after the base install. Many formats require their own optional backend and fail at open time when it is absent.
- Downstream code assumes one array rank. A still can produce H by W by C while a series can add a leading frame dimension, depending on index and plugin behavior.
- The code uses bare imageio.imread examples. That is the older v2 API; current work should import imageio.v3 and test its different frame and metadata rules.
Setup reality
We installed imageio 2.37.4 in 0.6 seconds in a clean Python 3.12 environment. Three packages occupied 78 MB. The measured package metadata reported 55 direct dependencies, Python >=3.10, pure Python code, and py.typed. pip-audit found no known vulnerabilities, while import imageio completed in 0.58 seconds. The package inspection did not identify a license, so check the distribution and project terms for your compliance record.
Use import imageio.v3 as iio for a new project. The basic environment covers NumPy and Pillow-backed formats, while video, advanced TIFF, HEIC, raw-camera, FITS, and ITK files require matching extras or packages. Backend absence is discovered when a resource opens, often with suggestions in the exception. Build and test the exact format matrix rather than treating the format catalogue as an installed feature list.
Automatic plugin selection uses the resource and extension. Set plugin explicitly when a TIFF must go through tifffile or an MP4 must use PyAV. Options passed to a reader or writer belong to that backend, so a JPEG quality keyword is not a portable imageio setting. Byte input can need extension='.png' to guide selection; the special '' output also needs an extension to choose an encoder.
Specify index=0 for one frame and index=... for a full series. An omitted index may change result rank when another plugin handles the file. imiter() is the safer route for a long video or stack because it does not retain every decoded frame. Writers also expect suitable array dtypes. Convert float ranges explicitly before an 8-bit format instead of relying on an undocumented rescale.
Patterns
Load one still frame load-still-image
import imageio.v3 as iio
image = iio.imread('photo.jpg', index=0)
print(image.shape, image.dtype)index=0 states that the caller wants one image; leaving it open can produce a full stack for a multi-frame resource.
Select a writer from the filename save-image-by-extension
import imageio.v3 as iio
iio.imwrite('output.png', image)
iio.imwrite('preview.jpg', image, quality=75)quality is understood by the Pillow JPEG writer. Backend options are not shared automatically with every imageio plugin.
Request every frame explicitly load-frame-stack
frames = iio.imread('animation.gif', index=...)
print(frames.shape)The ellipsis loads the complete series into one array, whose decoded memory use may greatly exceed the file size.
Iterate through an MP4 stream-video-frames
for number, frame in enumerate(iio.imiter('clip.mp4', plugin='pyav')):
consume(number, frame)The pyav backend is optional. Iteration controls retained memory, while decoding and seeking still follow PyAV behavior.
Give encoded bytes a format hint decode-byte-payload
image = iio.imread(payload, extension='.png')A byte buffer has no filename, so extension helps the plugin manager choose among installed decoders.
Write an image into memory encode-byte-payload
png_payload = iio.imwrite('<bytes>', image, extension='.png')'<bytes>' asks for encoded bytes. extension is required because there is no output filename to identify the format.
Read shape and dtype metadata inspect-image-properties
props = iio.improps('scan.tif', index=...)
print(props.shape, props.dtype, props.n_images)improps avoids a full pixel read when the plugin can determine these fields cheaply; available properties still vary by backend.
Open OME-TIFF with tifffile force-tiff-backend
volume = iio.imread('volume.ome.tif', plugin='tifffile', index=...)Install tifffile separately. Pinning it avoids Pillow's narrower TIFF behavior and different metadata layout.
Map float pixels to uint8 convert-float-for-png
import numpy as np
output = (np.clip(float_image, 0, 1) * 255).round().astype(np.uint8)
iio.imwrite('output.png', output)Make the numeric range explicit; imageio does not promise to scale every floating-point array for an 8-bit writer.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| Pillow | PyPI | Use it for common still images when editing and drawing matter as much as file I/O. |
| opencv-python | PyPI | Use it when decoding feeds computer-vision operations and OpenCV's BGR conventions fit the pipeline. |
| tifffile | PyPI | Use it directly when TIFF pages, pyramids, tags, and scientific layouts are the entire problem. |
More data guides
numpy · fsspec · pandas · sqlalchemy · pyarrow · lxml · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.

