Skip to content

Commit

Permalink
Fix cached overlay pasting for RGB backgrounds
Browse files Browse the repository at this point in the history
  • Loading branch information
djhoese committed Apr 2, 2023
1 parent 794875f commit 8d3e5b0
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 13 deletions.
18 changes: 14 additions & 4 deletions pycoast/cw_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1204,8 +1204,7 @@ def _apply_cached_image(cache_file, cache_epoch, background, regenerate=False):
foreground = Image.open(cache_file)
logger.info("Using image in cache %s", cache_file)
if background is not None:
fg = foreground.convert("RGBa")
background.paste(fg, mask=fg)
_apply_cached_foreground_on_background(background, foreground)
return foreground
logger.info("Regenerating cache file.")
except OSError:
Expand All @@ -1218,8 +1217,7 @@ def _write_and_apply_new_cached_image(self):
except IOError as e:
logger.error("Can't save cache: %s", str(e))
if self._background is not None:
premult_foreground = self._foreground.convert("RGBa")
self._background.paste(premult_foreground, mask=premult_foreground)
_apply_cached_foreground_on_background(self._background, self._foreground)

def _generate_cache_filename(self, cache_prefix, area_def, overlays_dict):
area_hash = hash(area_def)
Expand Down Expand Up @@ -1450,6 +1448,18 @@ def _add_points_from_dict(self, points_dict):
)


def _apply_cached_foreground_on_background(background, foreground):
premult_foreground = foreground.convert("RGBa")
if background.mode == "RGBA":
# Cached foreground and background are both RGBA, not extra conversions needed
background.paste(premult_foreground, mask=premult_foreground)
return
background_rgba = background.convert("RGBA")
background_rgba.paste(premult_foreground, mask=premult_foreground)
# overwrite background image in place
background.paste(background_rgba)


class _GridDrawer:
"""Helper for drawing graticule/grid lines."""

Expand Down
23 changes: 14 additions & 9 deletions pycoast/tests/test_pycoast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1935,9 +1935,12 @@ def test_caching_with_param_changes(self, tmpdir):
# new cache file should be...new
assert os.path.getmtime(new_cache_filename) != mtime

@pytest.mark.parametrize("background_mode", ["RGB", "RGBA"])
@pytest.mark.parametrize("include_background_pattern", [False, True])
@pytest.mark.parametrize("upper_right_opacity", [32, 127, 255])
def test_cache_nocache_consistency(self, tmp_path, include_background_pattern, upper_right_opacity):
def test_cache_nocache_consistency(
self, tmp_path, include_background_pattern, background_mode, upper_right_opacity
):
"""Test that an image generated with an image looks the same when using a cached foreground."""
from pycoast import ContourWriterAGG

Expand Down Expand Up @@ -1971,20 +1974,20 @@ def test_cache_nocache_consistency(self, tmp_path, include_background_pattern, u
}

# Create the original cache file
background_img1 = _create_background_image(include_background_pattern)
background_img1 = _create_background_image(include_background_pattern, background_mode)
cached_image1 = cw.add_overlay_from_dict(overlays, area_def, background=background_img1)

# Reuse the generated cache file
background_img2 = _create_background_image(include_background_pattern)
background_img2 = _create_background_image(include_background_pattern, background_mode)
cached_image2 = cw.add_overlay_from_dict(overlays, area_def, background=background_img2)

# Create without cache
overlays.pop("cache")
background_img3 = _create_background_image(include_background_pattern)
background_img3 = _create_background_image(include_background_pattern, background_mode)
cw.add_overlay_from_dict(overlays, area_def, background=background_img3)

# Manually (no dict, no cache)
background_img4 = _create_background_image(include_background_pattern)
background_img4 = _create_background_image(include_background_pattern, background_mode)
for shape_params in overlays["shapefiles"]:
cw.add_shapefile_shapes(background_img4, area_def, **shape_params)

Expand Down Expand Up @@ -2019,10 +2022,12 @@ def _create_polygon_shapefile(fn: pathlib.Path, polygon_coords: list) -> None:
test_shapefile.record("test")


def _create_background_image(add_pattern: bool) -> Image:
img_data = np.zeros((200, 200, 4), dtype=np.uint8)
img_data[..., -1] = 255
def _create_background_image(add_pattern: bool, background_mode: str) -> Image:
num_bands = len(background_mode)
img_data = np.zeros((200, 200, num_bands), dtype=np.uint8)
if background_mode[-1] == "A":
img_data[..., -1] = 255
if add_pattern:
img_data[6:30, 6:30, 0] = 127
img_data[6:30, -30:-6, 0] = 127
return Image.fromarray(img_data, mode="RGBA")
return Image.fromarray(img_data, mode=background_mode)

0 comments on commit 8d3e5b0

Please sign in to comment.