diff --git a/fsl/data/image.py b/fsl/data/image.py
index b5d0cad72d12850aecbeeab7ac072aca9f9d3485..e21ad87c2cf34cfe629ecba94e7cf2890cfb0472 100644
--- a/fsl/data/image.py
+++ b/fsl/data/image.py
@@ -1042,7 +1042,8 @@ class Image(Nifti):
                          calculated immediately (vi a call to
                          :meth:`calcRange`). Otherwise, the image range is
                          incrementally updated as more data is read from memory
-                         or disk.
+                         or disk. If ``loadData=False``, ``calcRange`` is also
+                         set to ``False``.
 
         :arg threaded:   If ``True``, the :class:`.ImageWrapper` will use a
                          separate thread for data range calculation. Defaults
@@ -1065,8 +1066,11 @@ class Image(Nifti):
         nibImage = None
         saved    = False
 
-        if loadData:
-            threaded = False
+        # disable threaded access if loadData is True
+        threaded = threaded and (not loadData)
+
+        # don't calcRange if not loading data
+        calcRange = calcRange and loadData
 
         # Take a copy of the header if one has
         # been provided
diff --git a/fsl/data/imagewrapper.py b/fsl/data/imagewrapper.py
index 771f288a24c1719e66cb4b9812f1f613edf6ed71..c9fec4a478d49c5818db15c09db2629940febf1e 100644
--- a/fsl/data/imagewrapper.py
+++ b/fsl/data/imagewrapper.py
@@ -388,6 +388,14 @@ class ImageWrapper(notifier.Notifier):
             self.__data = np.asanyarray(self.__image.dataobj)
 
 
+    @property
+    def dataIsLoaded(self):
+        """Return true if the image data has been loaded into memory, ``False``
+        otherwise.
+        """
+        return self.__data is not None
+
+
     def __getData(self, sliceobj, isTuple=False):
         """Retrieves the image data at the location specified by ``sliceobj``.