Pillow
| Language | Python 3 |
|---|---|
| License | MIT-CMU (HPND) |
| Repository | github.com/python-pillow/Pillow |
| Documentation | JPEG 2000 in the Pillow handbook |
| Depends on | OpenJPEG 2.0+ (included in the PyPI wheels) |
| Read / write | yes / 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#
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#
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:
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:
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#
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#
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#
im.infomay contain"dpi"(from theresbox) and"comment"(from a COM marker).- Add
comment="..."when saving to replace OpenJPEG’s default “Created by OpenJPEG version” comment. - Set
Image.MAX_IMAGE_PIXELSto a limit you’re comfortable with before opening untrusted files.