A Python 3.6+ framework for decoding JPEG images and decoding/encoding RLE datasets, with a focus on providing support for pydicom.
pip install pylibjpeg
Make sure Git is installed, then
git clone https://github.com/pydicom/pylibjpeg
python -m pip install pylibjpeg
One or more plugins are required before pylibjpeg is able to handle JPEG images or RLE datasets. To handle a given format or DICOM Transfer Syntax you first have to install the corresponding package:
Format | Decode? | Encode? | Plugin | Based on |
---|---|---|---|---|
JPEG, JPEG-LS and JPEG XT | Yes | No | pylibjpeg-libjpeg | libjpeg |
JPEG 2000 | Yes | No | pylibjpeg-openjpeg | openjpeg |
RLE Lossless (PackBits) | Yes | Yes | pylibjpeg-rle | - |
UID | Description | Plugin |
---|---|---|
1.2.840.10008.1.2.4.50 | JPEG Baseline (Process 1) | pylibjpeg-libjpeg |
1.2.840.10008.1.2.4.51 | JPEG Extended (Process 2 and 4) | pylibjpeg-libjpeg |
1.2.840.10008.1.2.4.57 | JPEG Lossless, Non-Hierarchical (Process 14) | pylibjpeg-libjpeg |
1.2.840.10008.1.2.4.70 | JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14, Selection Value 1) |
pylibjpeg-libjpeg |
1.2.840.10008.1.2.4.80 | JPEG-LS Lossless | pylibjpeg-libjpeg |
1.2.840.10008.1.2.4.81 | JPEG-LS Lossy (Near-Lossless) Image Compression | pylibjpeg-libjpeg |
1.2.840.10008.1.2.4.90 | JPEG 2000 Image Compression (Lossless Only) | pylibjpeg-openjpeg |
1.2.840.10008.1.2.4.91 | JPEG 2000 Image Compression | pylibjpeg-openjpeg |
1.2.840.10008.1.2.5 | RLE Lossless | pylibjpeg-rle |
If you're not sure what the dataset's Transfer Syntax UID is, it can be determined with:
>>> from pydicom import dcmread
>>> ds = dcmread('path/to/dicom_file')
>>> ds.file_meta.TransferSyntaxUID.name
Assuming you have pydicom v2.1+ and suitable plugins installed:
from pydicom import dcmread
from pydicom.data import get_testdata_file
# With the pylibjpeg-libjpeg plugin
ds = dcmread(get_testdata_file('JPEG-LL.dcm'))
jpg_arr = ds.pixel_array
# With the pylibjpeg-openjpeg plugin
ds = dcmread(get_testdata_file('JPEG2000.dcm'))
j2k_arr = ds.pixel_array
# With the pylibjpeg-rle plugin and pydicom v2.2+
ds = dcmread(get_testdata_file('OBXXXX1A_rle.dcm'))
# pydicom defaults to the numpy handler for RLE so need
# to explicitly specify the use of pylibjpeg
ds.decompress("pylibjpeg")
rle_arr = ds.pixel_array
For datasets with multiple frames you can reduce your memory usage by
processing each frame separately using the generate_frames()
generator
function:
from pydicom import dcmread
from pydicom.data import get_testdata_file
from pydicom.pixel_data_handlers.pylibjpeg_handler import generate_frames
ds = dcmread(get_testdata_file('color3d_jpeg_baseline.dcm'))
frames = generate_frames(ds)
arr = next(frames)
You can also just use pylibjpeg to decode JPEG images to a numpy ndarray, provided you have a suitable plugin installed:
from pylibjpeg import decode
# Can decode using the path to a JPG file as str or path-like
arr = decode('filename.jpg')
# Or a file-like...
with open('filename.jpg', 'rb') as f:
arr = decode(f)
# Or bytes...
with open('filename.jpg', 'rb') as f:
arr = decode(f.read())
Assuming you have pydicom v2.2+ and suitable plugins installed:
from pydicom import dcmread
from pydicom.data import get_testdata_file
from pydicom.uid import RLELossless
ds = dcmread(get_testdata_file("CT_small.dcm"))
# Encode in-place using RLE Lossless and update the dataset
# Updates the Pixel Data, Transfer Syntax UID and Planar Configuration
ds.compress(uid)
# Save compressed
ds.save_as("CT_small_rle.dcm")