All formats

imagecodecs

LanguagePython 3 (Cython extension)
LicenseBSD-3-Clause
Repositorygithub.com/cgohlke/imagecodecs
DocumentationREADME and docstrings
Depends onNumPy; OpenJPEG is built into the wheels
Read / writeyes / yes; JP2 and J2K, 1-16 bit (and up to 26-bit integer) samples

imagecodecs is a collection of image codecs for NumPy arrays, made for scientific imaging. It’s used by tifffile, zarr and napari to decode compressed tiles. For JPEG 2000 it wraps OpenJPEG with simple functions: jpeg2k_decode turns bytes into an array, jpeg2k_encode turns an array into bytes.

It works on in-memory data and has no JP2 metadata API. It’s a good choice for 16-bit grayscale, multi-channel or volumetric data, where Pillow’s mode system is limiting.

Installation#

Shell
pip install imagecodecs

Binary wheels for Windows, macOS and Linux include OpenJPEG and the other codec libraries.

Basic usage: decode and encode#

Python
import imagecodecs

with open("in.jp2", "rb") as f:
    data = f.read()

if imagecodecs.jpeg2k_check(data):           # True for JP2/JPX/J2K signatures
    image = imagecodecs.jpeg2k_decode(data)  # NumPy array, (rows, cols) or (rows, cols, samples)
    print(image.shape, image.dtype)

    encoded = imagecodecs.jpeg2k_encode(image, level=0)  # level 0: lossless
    with open("out.jp2", "wb") as f:
        f.write(encoded)

How to read and write files directly#

imread and imwrite pick the codec from the file extension:

Python
from imagecodecs import imread, imwrite

image = imread("in.jp2")
imwrite("copy.j2k", image)

How to encode lossy JPEG 2000#

level is the target PSNR in dB for lossy compression; reversible=False selects the 9/7 wavelet:

Python
import imagecodecs
import numpy as np

image = np.random.randint(0, 4095, (512, 512), dtype=np.uint16)  # 12-bit data
encoded = imagecodecs.jpeg2k_encode(
    image,
    level=45,             # PSNR in dB
    reversible=False,
    bitspersample=12,
    codecformat="J2K",    # raw codestream; default is JP2
    numthreads=4,
)

How to decode at lower resolution#

skipres discards resolution levels, halving width and height each time:

Python
preview = imagecodecs.jpeg2k_decode(data, skipres=2)   # 1/4 size

Tips#