# pydicom_PIL.py """View DICOM images using Python image Library (PIL) Usage: >>> import dicom >>> from dicom.contrib.pydicom_PIL import show_PIL >>> ds = dicom.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.txt included with this distribution, also # available at http://pydicom.googlecode.com # 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 except: have_PIL = False have_numpy = True try: import numpy as np except: 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)]) # Display an image using the Python Imaging Library (PIL) def show_PIL(dataset): 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") if ('WindowWidth' not in dataset) or ('WindowCenter' not in dataset): # can only apply LUT if these values exist 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: mode = "I;16" # not sure about this -- PIL source says is 'experimental' and no documentation. Also, should bytes swap depending on endian of file and system?? 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) im = PIL.Image.frombuffer(mode, size, dataset.PixelData, "raw", mode, 0, 1) # Recommended to specify all details by http://www.pythonware.com/library/pil/handbook/image.htm else: image = get_LUT_value(dataset.pixel_array, dataset.WindowWidth, dataset.WindowCenter) im = PIL.Image.fromarray(image).convert('L') # Convert mode to L since LUT has only 256 values: http://www.pythonware.com/library/pil/handbook/image.htm im.show()