diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 8b630ce3e442..11b72d3ed1b7 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -364,17 +364,25 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, # TODO slice input array first inp_dtype = A.dtype - if inp_dtype.kind == 'f': - scaled_dtype = A.dtype - else: - scaled_dtype = np.float32 - a_min = A.min() + a_max = A.max() + # figure out the type we should scale to. For floats, + # leave as is. For integers cast to an appropriate-sized + # float. Small integers get smaller floats in an attempt + # to keep the memory footprint reasonable. if a_min is np.ma.masked: - a_min, a_max = 0, 1 # all masked, so values don't matter + # all masked, so values don't matter + a_min, a_max = np.int32(0), np.int32(1) + if inp_dtype.kind == 'f': + scaled_dtype = A.dtype else: - a_min = a_min.astype(scaled_dtype) - a_max = A.max().astype(scaled_dtype) + # probably an integer of some type. + da = a_max.astype(np.float64) - a_min.astype(np.float64) + if da > 1e8: + # give more breathing room if a big dynamic range + scaled_dtype = np.float64 + else: + scaled_dtype = np.float32 # scale the input data to [.1, .9]. The Agg # interpolators clip to [0, 1] internally, use a @@ -386,6 +394,9 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, A_scaled = np.empty(A.shape, dtype=scaled_dtype) A_scaled[:] = A A_scaled -= a_min + a_min = a_min.astype(scaled_dtype) + a_max = a_max.astype(scaled_dtype) + if a_min != a_max: A_scaled /= ((a_max - a_min) / 0.8) A_scaled += 0.1 diff --git a/lib/matplotlib/tests/baseline_images/test_image/imshow_bignumbers.png b/lib/matplotlib/tests/baseline_images/test_image/imshow_bignumbers.png new file mode 100644 index 000000000000..ec189bb949e5 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_image/imshow_bignumbers.png differ diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py index 0e423ab5fd2b..fd6430d5687c 100644 --- a/lib/matplotlib/tests/test_image.py +++ b/lib/matplotlib/tests/test_image.py @@ -806,6 +806,19 @@ def test_imshow_flatfield(): im.set_clim(.5, 1.5) +@image_comparison(baseline_images=['imshow_bignumbers'], + remove_text=True, style='mpl20', + extensions=['png']) +def test_imshow_bignumbers(): + # putting a big number in an array of integers shouldn't + # ruin the dynamic range of the resolved bits. + fig, ax = plt.subplots() + img = np.array([[1, 2, 1e12],[3, 1, 4]], dtype=np.uint64) + pc = ax.imshow(img) + pc.set_clim(0, 5) + plt.show() + + @pytest.mark.parametrize( "make_norm", [colors.Normalize,