diff --git a/scikits/image/io/__init__.py b/scikits/image/io/__init__.py index 697ebf6d..860084a4 100644 --- a/scikits/image/io/__init__.py +++ b/scikits/image/io/__init__.py @@ -10,8 +10,8 @@ from _plugins import info as plugin_info available_plugins = plugins() -for preferred_plugin in ['pil', - 'matplotlib', 'gtk', 'freeimage', 'qt', 'null']: +for preferred_plugin in \ + ['pil', 'matplotlib', 'gtk', 'freeimage', 'qt', 'null']: if preferred_plugin in available_plugins: use_plugin(preferred_plugin) break diff --git a/scikits/image/io/_plugins/qt_plugin.ini b/scikits/image/io/_plugins/qt_plugin.ini index 9e98ba81..822a2867 100644 --- a/scikits/image/io/_plugins/qt_plugin.ini +++ b/scikits/image/io/_plugins/qt_plugin.ini @@ -1,4 +1,4 @@ [qt] description = Fast image display using the Qt library -provides = imshow, _app_show, imsave +provides = imshow, _app_show, imsave, imread diff --git a/scikits/image/io/_plugins/qt_plugin.py b/scikits/image/io/_plugins/qt_plugin.py index b58e2c38..ff8c7bed 100644 --- a/scikits/image/io/_plugins/qt_plugin.py +++ b/scikits/image/io/_plugins/qt_plugin.py @@ -10,6 +10,8 @@ try: from PyQt4.QtGui import (QApplication, QMainWindow, QImage, QPixmap, QLabel, QWidget) from PyQt4 import QtCore, QtGui + import sip + import warnings except ImportError: window_manager._release('qt') @@ -27,6 +29,7 @@ except ImportError: app = None + class ImageLabel(QLabel): def __init__(self, parent, arr): QLabel.__init__(self) @@ -77,6 +80,50 @@ class ImageWindow(QMainWindow): self.mgr.remove_window(self) +def imread_qt(filename): + """ + Read an image using QT's QImage.load + """ + qtimg = QImage() + if not qtimg.load(filename): + # QImage.load() returns false on failure, so raise an exception + raise IOError('Unable to load file %s' % filename) + if qtimg.depth() == 1: + raise IOError('1-bit images currently not supported') + # TODO: Warn about other odd formats we don't currently handle properly, + # such as the odd 16-bit packed formats QT supports + arrayptr = qtimg.bits() + # QT may pad the image, so we need to use bytesPerLine, not width for + # the conversion to a numpy array + bytesPerPixel = qtimg.depth() // 8 + pixelsPerLine = qtimg.bytesPerLine() // bytesPerPixel + img_size = pixelsPerLine * qtimg.height() * bytesPerPixel + arrayptr.setsize(img_size) + img = np.array(arrayptr) + # Reshape and trim down to correct dimensions + if bytesPerPixel > 1: + img = img.reshape((qtimg.height(), pixelsPerLine, bytesPerPixel)) + img = img[:, :qtimg.width(), :] + else: + img = img.reshape((qtimg.height(), pixelsPerLine)) + img = img[:, :qtimg.width()] + # Strip qt's false alpha channel if needed + # and reorder color axes as required + if bytesPerPixel == 4 and not qtimg.hasAlphaChannel(): + img = img[:, :, 2::-1] + elif bytesPerPixel == 4: + img[:, :, 0:3] = img[:, :, 2::-1] + return img + +if sip.SIP_VERSION >= 0x040c00: + # sip.voidptr only acquired a buffer view in 4.12.0, so our imread + # doesn't work with earlier versions + imread = imread_qt +else: + warnings.warn(RuntimeWarning( + "sip version too old. QT imread disabled")) + + def imshow(arr, fancy=False): global app if not app: diff --git a/scikits/image/io/_plugins/util.py b/scikits/image/io/_plugins/util.py index b21dae45..2f37074c 100644 --- a/scikits/image/io/_plugins/util.py +++ b/scikits/image/io/_plugins/util.py @@ -135,14 +135,15 @@ def prepare_for_display(npy_img): if npy_img.ndim == 2 or \ (npy_img.ndim == 3 and npy_img.shape[2] == 1): + npy_plane = npy_img.reshape((height, width)) if np.issubdtype(npy_img.dtype, float): - out[:,:,0] = npy_img*255 + out[:,:,0] = npy_plane*255 out[:,:,1] = out[:,:,0] out[:,:,2] = out[:,:,0] else: - out[:,:,0] = npy_img - out[:,:,1] = npy_img - out[:,:,2] = npy_img + out[:,:,0] = npy_plane + out[:,:,1] = npy_plane + out[:,:,2] = npy_plane elif npy_img.ndim == 3: if npy_img.shape[2] == 3 or npy_img.shape[2] == 4: