From d05dc65a13664c2dfdba4e015e1e2e97b7be8928 Mon Sep 17 00:00:00 2001 From: Matt Savoie Date: Fri, 20 Dec 2024 14:11:19 -0700 Subject: [PATCH] =?UTF-8?q?DAS-2280:=20Merge=20TRANSPARENT=5FIDX=20and=20N?= =?UTF-8?q?ODATA=5FIDX=20to=20increase=20available=20=E2=80=A6=20(#41)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 24 +++++++++++++++++++----- docker/service_version.txt | 2 +- hybig/browse.py | 14 ++++++-------- hybig/color_utility.py | 3 --- tests/unit/test_browse.py | 20 ++++++++++---------- 5 files changed, 36 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ce6c2e..a89247a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,18 +4,31 @@ HyBIG follows semantic versioning. All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). +## [v2.2.0] - 2024-12-19 + +### Changed + +* NODATA and TRANSPARENT values are merged. [[#41](https://github.com/nasa/harmony-browse-image-generator/pull/41)] + - User visible change: paletted PNG outupt images will have up to 254 color + values and a 255th value that is transparent. + - Internal code changes: removes `TRANSPARENT_IDX` (254) and uses + `NODATA_IDX` (255) in its stead. A color of (0,0,0,0) was previosly set to + both the indexes (254 and 255) in the ouput PNGs and now only 255 will have + this value. This change ensures the roundtrip from single band to RGBA to + paletted PNG is consistent. + ## [v2.1.0] - 2024-12-13 ### Changed -* Input GeoTIFF RGB[A] images are **no longer palettized** when converted to a PNG. The new resulting output browse images are now 3 or 4 band PNG retaining the color information of the input image.[#39](https://github.com/nasa/harmony-browse-image-generator/pull/39) -* Changed pre-commit configuration to remove `black-jupyter` dependency [#38](https://github.com/nasa/harmony-browse-image-generator/pull/38) -* Updates service image's python to 3.12 [#38](https://github.com/nasa/harmony-browse-image-generator/pull/38) -* Simplifies test scripts to run with pytest and pytest plugins [#38](https://github.com/nasa/harmony-browse-image-generator/pull/38) +* Input GeoTIFF RGB[A] images are **no longer palettized** when converted to a PNG. The new resulting output browse images are now 3 or 4 band PNG retaining the color information of the input image.[[#39](https://github.com/nasa/harmony-browse-image-generator/pull/39)] +* Changed pre-commit configuration to remove `black-jupyter` dependency [[#38](https://github.com/nasa/harmony-browse-image-generator/pull/38)] +* Updates service image's python to 3.12 [[#38](https://github.com/nasa/harmony-browse-image-generator/pull/38)] +* Simplifies test scripts to run with pytest and pytest plugins [[#38](https://github.com/nasa/harmony-browse-image-generator/pull/38)] ### Removed -* Removes `test_code_format.py` in favor of `ruff` pre-commit configuration [#38](https://github.com/nasa/harmony-browse-image-generator/pull/38) +* Removes `test_code_format.py` in favor of `ruff` pre-commit configuration [[#38](https://github.com/nasa/harmony-browse-image-generator/pull/38)] ## [v2.0.2] - 2024-10-15 @@ -92,6 +105,7 @@ For more information on internal releases prior to NASA open-source approval, see legacy-CHANGELOG.md. [unreleased]: https://github.com/nasa/harmony-browse-image-generator/ +[v2.2.0]: https://github.com/nasa/harmony-browse-image-generator/releases/tag/2.2.0 [v2.1.0]: https://github.com/nasa/harmony-browse-image-generator/releases/tag/2.1.0 [v2.0.2]: https://github.com/nasa/harmony-browse-image-generator/releases/tag/2.0.2 [v2.0.1]: https://github.com/nasa/harmony-browse-image-generator/releases/tag/2.0.1 diff --git a/docker/service_version.txt b/docker/service_version.txt index 7ec1d6d..ccbccc3 100644 --- a/docker/service_version.txt +++ b/docker/service_version.txt @@ -1 +1 @@ -2.1.0 +2.2.0 diff --git a/hybig/browse.py b/hybig/browse.py index 8c120fd..2246666 100644 --- a/hybig/browse.py +++ b/hybig/browse.py @@ -28,8 +28,6 @@ NODATA_RGBA, OPAQUE, TRANSPARENT, - TRANSPARENT_IDX, - TRANSPARENT_RGBA, all_black_color_map, get_color_palette, palette_from_remote_colortable, @@ -299,7 +297,7 @@ def convert_gray_1band_to_raster(data_array: DataArray) -> ndarray: """Convert a 1-band raster without a color association.""" band = data_array[0, :, :] cmap = matplotlib.colormaps['Greys_r'] - cmap.set_bad(TRANSPARENT_RGBA) + cmap.set_bad(NODATA_RGBA) norm = Normalize(vmin=np.nanmin(band), vmax=np.nanmax(band)) scalar_map = ScalarMappable(cmap=cmap, norm=norm) @@ -403,9 +401,9 @@ def palettize_raster(raster: ndarray) -> tuple[ndarray, dict]: written to the final raster as 254 and add the mapped RGBA value to the color palette. """ - # reserves 254 for transparent images and 255 for off grid fill values - # 0 to 253 - max_colors = 254 + # reserves 255 for transparent and off grid fill values + # 0 to 254 + max_colors = 255 rgb_raster, alpha = remove_alpha(raster) multiband_image = Image.fromarray(reshape_as_image(rgb_raster)) @@ -427,8 +425,8 @@ def add_alpha( """ if alpha is not None and np.any(alpha != OPAQUE): # Set any alpha to the transparent index value - quantized_array = np.where(alpha != OPAQUE, TRANSPARENT_IDX, quantized_array) - color_map[TRANSPARENT_IDX] = TRANSPARENT_RGBA + quantized_array = np.where(alpha != OPAQUE, NODATA_IDX, quantized_array) + color_map[NODATA_IDX] = NODATA_RGBA return quantized_array, color_map diff --git a/hybig/color_utility.py b/hybig/color_utility.py index 4efdd68..921ff0d 100644 --- a/hybig/color_utility.py +++ b/hybig/color_utility.py @@ -21,9 +21,6 @@ # Applied to transparent pixels where alpha < 255 TRANSPARENT = np.uint8(0) OPAQUE = np.uint8(255) -TRANSPARENT_RGBA = (0, 0, 0, 0) -TRANSPARENT_IDX = 254 - # Applied to off grid areas during reprojection NODATA_RGBA = (0, 0, 0, 0) NODATA_IDX = 255 diff --git a/tests/unit/test_browse.py b/tests/unit/test_browse.py index 4f9c1c2..897149c 100644 --- a/tests/unit/test_browse.py +++ b/tests/unit/test_browse.py @@ -654,7 +654,7 @@ def test_convert_5_multiband_to_raster(self): ) def test_standardize_raster_for_writing_jpeg_3band(self): - raster = self.random.integers(255, size=(3, 5, 6)) + raster = self.random.integers(255, size=(3, 5, 6), dtype='uint8') count = 'irrelevant' driver = 'JPEG' expected_raster = np.copy(raster) @@ -667,7 +667,7 @@ def test_standardize_raster_for_writing_jpeg_3band(self): np.testing.assert_array_equal(expected_raster, actual_raster, strict=True) def test_standardize_raster_for_writing_jpeg_4band(self): - raster = self.random.integers(255, size=(4, 7, 8)) + raster = self.random.integers(255, size=(4, 7, 8), dtype='uint8') driver = 'JPEG' count = 'irrelevant' expected_raster = np.copy(raster[0:3, :, :]) @@ -680,7 +680,7 @@ def test_standardize_raster_for_writing_jpeg_4band(self): @patch('hybig.browse.palettize_raster') def test_standardize_raster_for_writing_png_4band(self, palettize_mock): - raster = self.random.integers(255, size=(4, 7, 8)) + raster = self.random.integers(255, size=(4, 7, 8), dtype='uint8') driver = 'PNG' count = 'not 1' @@ -690,7 +690,7 @@ def test_standardize_raster_for_writing_png_4band(self, palettize_mock): @patch('hybig.browse.palettize_raster') def test_standardize_raster_for_writing_png_3band(self, palettize_mock): - raster = self.random.integers(255, size=(3, 7, 8)) + raster = self.random.integers(255, size=(3, 7, 8), dtype='uint8') driver = 'PNG' count = 'not 1' @@ -700,7 +700,7 @@ def test_standardize_raster_for_writing_png_3band(self, palettize_mock): @patch('hybig.browse.palettize_raster') def test_prepare_1band_raster_for_writing_png(self, palettize_mock): - raster = self.random.integers(255, size=(1, 7, 8)) + raster = self.random.integers(255, size=(1, 7, 8), dtype='uint8') driver = 'PNG' count = 1 palettize_mock.return_value = (None, None) @@ -711,7 +711,7 @@ def test_prepare_1band_raster_for_writing_png(self, palettize_mock): @patch('hybig.browse.get_color_map_from_image') def test_palettize_raster_no_alpha_layer(self, get_color_map_mock, image_mock): """Test that the quantize function is called by a correct image.""" - raster = self.random.integers(255, dtype='uint8', size=(3, 10, 11)) + raster = self.random.integers(255, size=(3, 10, 11), dtype='uint8') quantized_output = Image.fromarray( self.random.integers(254, size=(10, 11), dtype='uint8') @@ -724,7 +724,7 @@ def test_palettize_raster_no_alpha_layer(self, get_color_map_mock, image_mock): out_raster, out_map = palettize_raster(raster) - multiband_image_mock.quantize.assert_called_once_with(colors=254) + multiband_image_mock.quantize.assert_called_once_with(colors=255) get_color_map_mock.assert_called_once_with(quantized_output) np.testing.assert_array_equal(expected_out_raster, out_raster, strict=True) @@ -733,7 +733,7 @@ def test_palettize_raster_no_alpha_layer(self, get_color_map_mock, image_mock): @patch('hybig.browse.get_color_map_from_image') def test_palettize_raster_with_alpha_layer(self, get_color_map_mock, image_mock): """Test that the quantize function is called by a correct image.""" - raster = self.random.integers(255, dtype='uint8', size=(4, 10, 11)) + raster = self.random.integers(255, size=(4, 10, 11), dtype='uint8') # No transparent pixels raster[3, :, :] = 255 @@ -748,11 +748,11 @@ def test_palettize_raster_with_alpha_layer(self, get_color_map_mock, image_mock) multiband_image_mock.quantize.return_value = quantized_output expected_out_raster = np.array(quantized_output).reshape(1, 10, 11) - expected_out_raster[0, 0:3, 0:3] = 254 + expected_out_raster[0, 0:3, 0:3] = 255 out_raster, out_map = palettize_raster(raster) - multiband_image_mock.quantize.assert_called_once_with(colors=254) + multiband_image_mock.quantize.assert_called_once_with(colors=255) get_color_map_mock.assert_called_once_with(quantized_output) np.testing.assert_array_equal(expected_out_raster, out_raster, strict=True)