All formats

Pillow

LanguagePython 3
LicenseMIT-CMU (HPND)
Repositorygithub.com/python-pillow/Pillow
DocumentationJPEG 2000 in the Pillow handbook
Depends onOpenJPEG 2.0+ (included in the PyPI wheels)
Read / writeyes / yes; JP2, J2K and JPX; modes L, LA, RGB, RGBA, CMYK and 16-bit grayscale (I;16)

Pillow is the standard imaging library for Python. Its JPEG 2000 plugin uses OpenJPEG, which is bundled in the binary wheels for Windows, macOS and Linux, so pip install pillow is enough. You open a .jp2 or .j2k file with Image.open and save with Image.save; the extension selects JP2 or raw codestream output.

Pillow converts YCbCr to RGB on read and supports subsampled components when reading. It doesn’t expose ICC profiles, XMP or other JP2 boxes; use glymur for full metadata access.

Installation#

Shell
pip install pillow

Check support with python -m PIL.report (look for JPEG 2000 support ok).

Basic usage: convert JPEG 2000 to PNG and back#

Python
from PIL import Image

with Image.open("in.jp2") as im:
    print(im.format, im.size, im.mode)   # JPEG2000 (640, 480) RGB
    im.save("out.png")

with Image.open("out.png") as im:
    im.save("lossless.jp2")              # default: lossless, 5/3 wavelet

How to save lossy JPEG 2000#

Quality is given as compression ratios (quality_mode="rates") or PSNR values in dB (quality_mode="dB"), one value per quality layer:

Python
from PIL import Image

with Image.open("in.png") as im:
    im.save(
        "lossy.jp2",
        quality_mode="rates",
        quality_layers=[40, 20, 10],  # 3 layers: 40:1, 20:1, 10:1
        irreversible=True,            # 9/7 wavelet, better for lossy
        mct=1,                        # RGB -> YCbCr
        num_resolutions=6,
        progression="RLCP",
    )
    im.save("psnr.j2k", quality_mode="dB", quality_layers=[38])  # raw codestream at ~38 dB

How to decode at reduced resolution#

Set reduce (number of resolution levels to discard) and optionally layers before the image data is loaded:

Python
from PIL import Image

with Image.open("big.jp2") as im:
    im.reduce = 3       # 1/8 width and height
    im.layers = 1       # first quality layer only
    im.load()
    print(im.size)
    im.save("preview.png")

How to write tiled JPEG 2000 for large images#

Python
with Image.open("scan.tif") as im:
    im.save("scan.jp2", tile_size=(1024, 1024), quality_mode="rates",
            quality_layers=[20], irreversible=True, plt=True)  # PLT markers: faster random access

How to write a digital cinema (DCI) frame#

Python
with Image.open("frame.tif") as im:          # 2048 x 1080 RGB
    im.save("frame.j2c", cinema_mode="cinema2k-24", no_jp2=True)

Options are "cinema2k-24", "cinema2k-48" and "cinema4k-24". One image dimension must match the DCI container size (2048 x 1080 or 4096 x 2160).

Tips#