From 2137081dd57134ddf8b379daf174e26535af4e54 Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 24 Nov 2023 10:12:58 +0200 Subject: [PATCH 1/4] Add a test for stretching uint8 data --- trollimage/tests/test_image.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/trollimage/tests/test_image.py b/trollimage/tests/test_image.py index 3421efe8..f211e4dd 100644 --- a/trollimage/tests/test_image.py +++ b/trollimage/tests/test_image.py @@ -1631,6 +1631,18 @@ def test_linear_stretch_does_not_affect_alpha(self, dtype): np.testing.assert_allclose(img.data.values, res, atol=1.e-6) + def test_linear_stretch_uint8(self): + """Test linear stretch with uint8 data.""" + arr = np.arange(75, dtype=np.uint8).reshape(5, 5, 3) + arr[4, 4, :] = 255 + data = xr.DataArray(arr.copy(), dims=['y', 'x', 'bands'], + coords={'bands': ['R', 'G', 'B']}) + img = xrimage.XRImage(data) + img.stretch_linear() + + assert img.data.values.min() == pytest.approx(0.0) + assert img.data.values.max() == pytest.approx(1.0960743801652901) + @pytest.mark.parametrize("dtype", (np.float32, np.float64, float)) def test_histogram_stretch(self, dtype): """Test histogram stretching.""" From 2d8e89dc7a7eeb2d1d8b746dbbf4eb6c0ce45c97 Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 24 Nov 2023 10:26:30 +0200 Subject: [PATCH 2/4] Fix integer stretching --- trollimage/tests/test_image.py | 9 +++++---- trollimage/xrimage.py | 6 +++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/trollimage/tests/test_image.py b/trollimage/tests/test_image.py index f211e4dd..f49c166a 100644 --- a/trollimage/tests/test_image.py +++ b/trollimage/tests/test_image.py @@ -1631,16 +1631,17 @@ def test_linear_stretch_does_not_affect_alpha(self, dtype): np.testing.assert_allclose(img.data.values, res, atol=1.e-6) - def test_linear_stretch_uint8(self): - """Test linear stretch with uint8 data.""" - arr = np.arange(75, dtype=np.uint8).reshape(5, 5, 3) + @pytest.mark.parametrize("dtype", (np.uint8, np.uint16, int)) + def test_linear_stretch_integer(self, dtype): + """Test linear stretch with integer data.""" + arr = np.arange(75, dtype=dtype).reshape(5, 5, 3) arr[4, 4, :] = 255 data = xr.DataArray(arr.copy(), dims=['y', 'x', 'bands'], coords={'bands': ['R', 'G', 'B']}) img = xrimage.XRImage(data) img.stretch_linear() - assert img.data.values.min() == pytest.approx(0.0) + assert img.data.values.min() == pytest.approx(-0.0015614156835530892) assert img.data.values.max() == pytest.approx(1.0960743801652901) @pytest.mark.parametrize("dtype", (np.float32, np.float64, float)) diff --git a/trollimage/xrimage.py b/trollimage/xrimage.py index 515925e4..70a87080 100644 --- a/trollimage/xrimage.py +++ b/trollimage/xrimage.py @@ -1082,6 +1082,7 @@ def crude_stretch(self, min_stretch=None, max_stretch=None): attrs = self.data.attrs offset = -min_stretch * scale_factor + self.data = np.multiply(self.data, scale_factor, dtype=scale_factor.dtype) + offset self.data.attrs = attrs self.data.attrs.setdefault('enhancement_history', []).append({'scale': scale_factor, @@ -1095,8 +1096,11 @@ def _check_stretch_value(self, val, kind='min'): if isinstance(val, (list, tuple)): val = self.xrify_tuples(val) + dtype = self.data.dtype + if np.issubdtype(dtype, np.integer): + dtype = np.dtype(np.float32) try: - val = val.astype(self.data.dtype) + val = val.astype(dtype) except AttributeError: val = self.data.dtype.type(val) From d35a5ac3ced0344172322a5e021f139169548042 Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 24 Nov 2023 12:59:45 +0200 Subject: [PATCH 3/4] Handle higher than 16-bit integers separately --- trollimage/tests/test_image.py | 22 ++++++++++++++-------- trollimage/xrimage.py | 4 +++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/trollimage/tests/test_image.py b/trollimage/tests/test_image.py index f49c166a..1f8820cf 100644 --- a/trollimage/tests/test_image.py +++ b/trollimage/tests/test_image.py @@ -1631,18 +1631,24 @@ def test_linear_stretch_does_not_affect_alpha(self, dtype): np.testing.assert_allclose(img.data.values, res, atol=1.e-6) - @pytest.mark.parametrize("dtype", (np.uint8, np.uint16, int)) - def test_linear_stretch_integer(self, dtype): - """Test linear stretch with integer data.""" - arr = np.arange(75, dtype=dtype).reshape(5, 5, 3) - arr[4, 4, :] = 255 + @pytest.mark.parametrize(("dtype", "max_val", "exp_min", "exp_max"), + ((np.uint8, 255, -0.005358012691140175, 1.0053772069513798), + (np.int8, 127, -0.004926108196377754, 1.0058689523488282), + (np.uint16, 65535, -0.005050825305515899, 1.005050893505104), + (np.int16, 32767, -0.005052744992717635, 1.0050527782880818), + (np.uint32, 4294967295, -0.005050505077517274, 1.0050505395923495), + (np.int32, 2147483647, -0.00505050499355784, 1.0050505395923495), + (int, 2147483647, -0.00505050499355784, 1.0050505395923495), + )) + def test_linear_stretch_integers(self, dtype, max_val, exp_min, exp_max): + """Test linear stretch with low-bit unsigned integer data.""" + arr = np.linspace(0, max_val, num=75, dtype=dtype).reshape(5, 5, 3) data = xr.DataArray(arr.copy(), dims=['y', 'x', 'bands'], coords={'bands': ['R', 'G', 'B']}) img = xrimage.XRImage(data) img.stretch_linear() - - assert img.data.values.min() == pytest.approx(-0.0015614156835530892) - assert img.data.values.max() == pytest.approx(1.0960743801652901) + assert img.data.values.min() == pytest.approx(exp_min) + assert img.data.values.max() == pytest.approx(exp_max) @pytest.mark.parametrize("dtype", (np.float32, np.float64, float)) def test_histogram_stretch(self, dtype): diff --git a/trollimage/xrimage.py b/trollimage/xrimage.py index 70a87080..da0b28f8 100644 --- a/trollimage/xrimage.py +++ b/trollimage/xrimage.py @@ -1097,8 +1097,10 @@ def _check_stretch_value(self, val, kind='min'): val = self.xrify_tuples(val) dtype = self.data.dtype - if np.issubdtype(dtype, np.integer): + if isinstance(dtype, (np.uint8, np.int8, np.uint16, np.int16)): dtype = np.dtype(np.float32) + elif np.issubdtype(dtype, np.integer) or isinstance(dtype, int): + dtype = np.dtype(np.float64) try: val = val.astype(dtype) except AttributeError: From 034d65977dad6ec6a7c886b538be9b854e28c3bd Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 24 Nov 2023 13:18:10 +0200 Subject: [PATCH 4/4] Fix dtype check --- trollimage/xrimage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trollimage/xrimage.py b/trollimage/xrimage.py index da0b28f8..be218c03 100644 --- a/trollimage/xrimage.py +++ b/trollimage/xrimage.py @@ -1097,7 +1097,7 @@ def _check_stretch_value(self, val, kind='min'): val = self.xrify_tuples(val) dtype = self.data.dtype - if isinstance(dtype, (np.uint8, np.int8, np.uint16, np.int16)): + if dtype in (np.uint8, np.int8, np.uint16, np.int16): dtype = np.dtype(np.float32) elif np.issubdtype(dtype, np.integer) or isinstance(dtype, int): dtype = np.dtype(np.float64)