diff --git a/Dockerfile b/Dockerfile
index 4a5e75b..9f6e33c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -10,7 +10,7 @@ FROM alpine:3.20
RUN apk update && \
apk add py3-qt5 py3-numpy py3-pip py3-pillow ttf-freefont mesa-dri-gallium && \
rm -rf /var/cache/apk/* usr/lib/python3.12/EXTERNALLY-MANAGED &&\
- pip3 install pydicom pyqtgraph
+ pip3 install pydicom pyqtgraph pylibjpeg
WORKDIR /dicombrowser
diff --git a/dicombrowser/__init__.py b/dicombrowser/__init__.py
index b0807ed..8679a45 100644
--- a/dicombrowser/__init__.py
+++ b/dicombrowser/__init__.py
@@ -17,6 +17,5 @@
# with this program (LICENSE.txt). If not, see
-
from ._version import __version__, __author__, __copyright__
from .dicombrowser import mainargv
diff --git a/dicombrowser/_version.py b/dicombrowser/_version.py
index ea681df..ffddf35 100644
--- a/dicombrowser/_version.py
+++ b/dicombrowser/_version.py
@@ -17,9 +17,8 @@
# with this program (LICENSE.txt). If not, see
__appname__ = "DicomBrowser"
-__version_info__ = (1, 5, 0) # global application version, major/minor/patch
+__version_info__ = (1, 5, 1) # global application version, major/minor/patch
__version__ = f"{__version_info__[0]}.{__version_info__[1]}.{__version_info__[2]}"
__author__ = "Eric Kerfoot"
-__author_email__="eric.kerfoot@kcl.ac.uk"
+__author_email__ = "eric.kerfoot@kcl.ac.uk"
__copyright__ = "Copyright (c) 2016-22 Eric Kerfoot, King's College London, all rights reserved. Licensed under the GPL (see LICENSE.txt)."
-
diff --git a/dicombrowser/dicom.py b/dicombrowser/dicom.py
index e8add52..cc380da 100644
--- a/dicombrowser/dicom.py
+++ b/dicombrowser/dicom.py
@@ -21,6 +21,7 @@
from concurrent.futures import ProcessPoolExecutor, as_completed
from io import BytesIO
from glob import glob
+from warnings import warn
import numpy as np
from pydicom import dicomio, datadict, errors
@@ -65,6 +66,30 @@
FULL_NAME_MAP = {v: k for k, v in KEYWORD_NAME_MAP.items()} # maps full names to keywords
+def get_2d_equivalent_image(img):
+ """Given an array `img` of some arbitrary dimensions, attempt to choose a valid 2D gray/RGB/RGBA image from it."""
+ ndim = img.ndim
+ shape = img.shape
+ color_dim = ndim > 2 and shape[-1] in (1, 3, 4)
+
+ if ndim <= 2 or (ndim == 3 and color_dim): # 0D array, 1D array, 2D grayscale or 2D RGB(A)
+ if ndim < 2:
+ warn(f"Image has unusual shape {shape}, attempting to visualise")
+
+ return img
+ elif ndim == 3: # 3D grayscale
+ warn(f"Image is volume with shape {shape}, using mid-slice")
+ elif ndim == 4 and color_dim:
+ warn(f"Image is RGB(A) volume with shape {shape}, using mid-slice")
+ else:
+ warn(f"Image is unknown volume with shape {shape}, using mid-slices")
+
+ # attempt to slice the volume in every dimension that's not height, width, or the channels
+ stop = 3 if color_dim else 2 # dimensions to not slice in, ie. (height,width) or (height,width,channels)
+ slices = [s // 2 for s in shape[:-stop]] + [slice(None)] * stop
+ return img[tuple(slices)]
+
+
def get_scaled_image(dcm):
"""Return image data from `dcm` scaled using slope and intercept values."""
try:
diff --git a/dicombrowser/dicombrowser.py b/dicombrowser/dicombrowser.py
index ab871db..6e8fdfe 100755
--- a/dicombrowser/dicombrowser.py
+++ b/dicombrowser/dicombrowser.py
@@ -34,7 +34,7 @@
from ._version import __version__
from . import res
-from .dicom import load_dicom_dir, load_dicom_zip, SERIES_LIST_COLUMNS, ATTR_TREE_COLUMNS
+from .dicom import load_dicom_dir, load_dicom_zip, get_2d_equivalent_image, SERIES_LIST_COLUMNS, ATTR_TREE_COLUMNS
from .models import AttrItemModel, SeriesTreeModel
@@ -49,6 +49,7 @@
class LoadWorker(QtCore.QRunnable):
"""Loads Dicom data in a separate thread, updating the UI through the given signals."""
+
def __init__(self, src, status_signal, update_signal):
super().__init__()
self.src = src
@@ -231,8 +232,8 @@ def set_series_image(self, i, auto_range=False):
if img is None: # if the image is None use the default "no image" object
img = self.noimg
- # elif len(img.shape)==3: # multi-channel or multi-dimensional image, use average of dimensions
- # img=np.mean(img,axis=2)
+
+ img = get_2d_equivalent_image(img) # get something renderable in 2D
self.image_view.setImage(img.T, autoRange=auto_range, autoLevels=self.autoLevelsCheck.isChecked())
self._fill_attr_view()
diff --git a/dicombrowser/models.py b/dicombrowser/models.py
index b78d261..a037443 100644
--- a/dicombrowser/models.py
+++ b/dicombrowser/models.py
@@ -99,6 +99,7 @@ def fill_attrs(self, dcm, columns, regex=None, maxValueSize=256):
class SeriesTreeModel(QtGui.QStandardItemModel):
"""Represents the tree of Dicom series organised under nodes for each source file/directory."""
+
def __init__(self, columns, data={}, parent=None):
super().__init__(parent)
self.columns = columns