Files
penracourses/helpers/pydicom_PIL.py
T
Ross fc2c64cd76 .
2021-02-14 17:58:25 +00:00

123 lines
4.1 KiB
Python

# pydicom_PIL.py
"""View DICOM images using Python image Library (PIL)
Usage:
>>> import pydicom
>>> from pydicom.contrib.pydicom_PIL import show_PIL
>>> ds = pydicom.read_file("filename")
>>> show_PIL(ds)
Requires Numpy:
http://numpy.scipy.org/
and Python Imaging Library:
http://www.pythonware.com/products/pil/
"""
# Copyright (c) 2009 Darcy Mason, Adit Panchal
# This file is part of pydicom, relased under an MIT license.
# See the file LICENSE included with this distribution, also
# available at https://github.com/pydicom/pydicom
# Based on image.py from pydicom version 0.9.3,
# LUT code added by Adit Panchal
# Tested on Python 2.5.4 (32-bit) on Mac OS X 10.6
# using numpy 1.3.0 and PIL 1.1.7b1
have_PIL = True
try:
import PIL.Image, PIL.ImageOps
from pydicom.pixel_data_handlers.util import apply_voi_lut, apply_modality_lut
except ImportError:
have_PIL = False
have_numpy = True
try:
import numpy as np
except ImportError:
have_numpy = False
def get_LUT_value(data, window, level):
"""Apply the RGB Look-Up Table for the given
data and window/level value."""
if not have_numpy:
raise ImportError("Numpy is not available."
"See http://numpy.scipy.org/"
"to download and install")
return np.piecewise(data,
[data <= (level - 0.5 - (window - 1) / 2),
data > (level - 0.5 + (window - 1) / 2)],
[0, 255, lambda data: ((data - (level - 0.5)) /
(window - 1) + 0.5) * (255 - 0)])
def get_PIL_image(dataset):
"""Get Image object from Python Imaging Library(PIL)"""
if not have_PIL:
raise ImportError("Python Imaging Library is not available. "
"See http://www.pythonware.com/products/pil/ "
"to download and install")
if ('PixelData' not in dataset):
raise TypeError("Cannot show image -- DICOM dataset does not have "
"pixel data")
# Apply modality lut
array = apply_modality_lut(dataset.pixel_array, dataset)
# voi lut doesn't seem to help
#array = apply_voi_lut(array, dataset)
# can only apply LUT if these window info exists
if ('WindowWidth' not in dataset) or ('WindowCenter' not in dataset):
bits = dataset.BitsAllocated
samples = dataset.SamplesPerPixel
if bits == 8 and samples == 1:
mode = "L"
elif bits == 8 and samples == 3:
mode = "RGB"
elif bits == 16:
# not sure about this -- PIL source says is 'experimental'
# and no documentation. Also, should bytes swap depending
# on endian of file and system??
mode = "I;16"
else:
raise TypeError("Don't know PIL mode for %d BitsAllocated "
"and %d SamplesPerPixel" % (bits, samples))
# PIL size = (width, height)
size = (dataset.Columns, dataset.Rows)
array = apply_modality_lut(dataset.pixel_array, dataset)
array = apply_voi_lut(array, dataset)
if dataset["PhotometricInterpretation"].value == "MONOCHROME1":
# We need to invert
array = np.invert(array)
pixel_data = array.tostring()
# Recommended to specify all details
# by http://www.pythonware.com/library/pil/handbook/image.htm
im = PIL.Image.frombuffer(mode, size, pixel_data,
"raw", mode, 0, 1)
else:
ew = dataset['WindowWidth']
ec = dataset['WindowCenter']
ww = int(ew.value[0] if ew.VM > 1 else ew.value)
wc = int(ec.value[0] if ec.VM > 1 else ec.value)
## Convert mode to L since LUT has only 256 values:
## http://www.pythonware.com/library/pil/handbook/image.htm
image = get_LUT_value(array, ww, wc)
im = PIL.Image.fromarray(image).convert('L')
return im
def show_PIL(dataset):
"""Display an image using the Python Imaging Library (PIL)"""
im = get_PIL_image(dataset)
im.show()