Skip to content

Commit

Permalink
remove gamma correction references
Browse files Browse the repository at this point in the history
  • Loading branch information
biserhong committed Jan 1, 2025
1 parent 993ed66 commit 21f2db2
Show file tree
Hide file tree
Showing 8 changed files with 2 additions and 307 deletions.
1 change: 0 additions & 1 deletion terracotta/handlers/rgb.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ def rgb(
tile_xyz: Optional[Tuple[int, int, int]] = None,
*,
stretch_ranges: Optional[ListOfRanges] = None,
gamma_factor: Optional[float] = None,
color_transform: Optional[str] = None,
tile_size: Optional[Tuple[int, int]] = None
) -> BinaryIO:
Expand Down
10 changes: 0 additions & 10 deletions terracotta/handlers/singleband.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@

import collections

import numpy as np

from terracotta import get_settings, get_driver, image, xyz
from terracotta.profile import trace

Expand All @@ -28,7 +26,6 @@ def singleband(
*,
colormap: Union[str, Mapping[Number, RGBA], None] = None,
stretch_range: Optional[Tuple[NumberOrString, NumberOrString]] = None,
gamma_factor: Optional[float] = None,
tile_size: Optional[Tuple[int, int]] = None
) -> BinaryIO:
"""Return singleband image as PNG"""
Expand Down Expand Up @@ -76,13 +73,6 @@ def singleband(

cmap_or_palette = cast(Optional[str], colormap)

if gamma_factor:
# gamma correction is monotonic and preserves percentiles
band_stretch_range_arr = np.array(stretch_range_, dtype=tile_data.dtype)
stretch_range_ = list(image.gamma_correction(band_stretch_range_arr, gamma_factor, band_range))
# gamma correct band data
tile_data = image.gamma_correction(tile_data, gamma_factor, band_range)

out = image.to_uint8(tile_data, *stretch_range_)

return image.array_to_png(out, colormap=cmap_or_palette)
28 changes: 2 additions & 26 deletions terracotta/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
Utilities to create and manipulate images.
"""

from typing import List, Sequence, Tuple, TypeVar, Union, Optional
from typing import List, Sequence, Tuple, TypeVar, Union
from typing.io import BinaryIO

from io import BytesIO
import numbers

import numpy as np
from PIL import Image
from color_operations import parse_operations
from color_operations.operations import gamma
from color_operations.utils import to_math_type, scale_dtype
from color_operations.utils import to_math_type

from terracotta.profile import trace
from terracotta import exceptions, get_settings
Expand Down Expand Up @@ -166,28 +164,6 @@ def to_uint8(data: Array, lower_bound: Number, upper_bound: Number) -> Array:
return rescaled.astype(np.uint8)


def gamma_correction(
masked_data: Array,
gamma_factor: float,
band_range: list,
out_dtype: type = np.uint16,
) -> Array:
"""Apply gamma correction to the input array and scale it to the output dtype."""
if not isinstance(gamma_factor, numbers.Number) or gamma_factor <= 0:
raise exceptions.InvalidArgumentsError("Invalid gamma factor")

if band_range:
arr = contrast_stretch(masked_data, band_range, (0, 1))
elif np.issubdtype(masked_data.dtype, np.integer):
arr = to_math_type(masked_data)
else:
raise exceptions.InvalidArgumentsError("No band range given and array is not of integer type")

arr = gamma(arr, gamma_factor)
arr = scale_dtype(arr, out_dtype)
return arr


def apply_color_transform(
masked_data: Array,
color_transform: str,
Expand Down
7 changes: 0 additions & 7 deletions terracotta/server/rgb.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ class Meta:
"Null values indicate global minimum / maximum."
),
)
gamma_factor = fields.Float(
validate=validate.Range(min=0, min_inclusive=False),
missing=None,
description="Gamma factor to perform gamma correction."
)
color_transform = fields.String(
missing=None,
description="Gamma factor to perform gamma correction."
Expand Down Expand Up @@ -174,13 +169,11 @@ def _get_rgb_image(

rgb_values = (options.pop("r"), options.pop("g"), options.pop("b"))
stretch_ranges = tuple(options.pop(k) for k in ("r_range", "g_range", "b_range"))
gamma_factor = options.pop("gamma_factor")

image = rgb(
some_keys,
rgb_values,
stretch_ranges=stretch_ranges,
gamma_factor=gamma_factor,
tile_xyz=tile_xyz,
**options,
)
Expand Down
6 changes: 0 additions & 6 deletions terracotta/server/singleband.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,6 @@ class Meta:
missing=None,
)

gamma_factor = fields.Float(
validate=validate.Range(min=0, min_inclusive=False),
missing=None,
description="Gamma factor to perform gamma correction."
)

colormap = fields.String(
description="Colormap to apply to image (see /colormap)",
validate=validate.OneOf(("explicit", *AVAILABLE_CMAPS)),
Expand Down
117 changes: 0 additions & 117 deletions tests/handlers/test_rgb.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,120 +222,3 @@ def test_rgb_preview(use_testdb):
raw_img = rgb.rgb(["val21", "x"], ["val22", "val23", "val24"])
img_data = np.asarray(Image.open(raw_img))
assert img_data.shape == (*terracotta.get_settings().DEFAULT_TILE_SIZE, 3)


def test_rgb_gamma_correction(use_testdb, testdb, raster_file_xyz):
import terracotta
from terracotta.xyz import get_tile_data
from terracotta.handlers import rgb
from terracotta import image

ds_keys = ["val21", "x", "val22"]
bands = ["val22", "val23", "val24"]
gamma_factor = 2

raw_img = rgb.rgb(
ds_keys[:2],
bands,
raster_file_xyz,
gamma_factor=gamma_factor,
)
img_data = np.asarray(Image.open(raw_img))[..., 0]

# get non-gamma corrected data to compare to
driver = terracotta.get_driver(testdb)

with driver.connect():
tile_data = get_tile_data(
driver, ds_keys, tile_xyz=raster_file_xyz, tile_size=img_data.shape
)

tile_metadata = driver.get_metadata(ds_keys)

# non-gamma corrected uint8 data
tile_uint8 = image.to_uint8(tile_data, *tile_metadata["range"])

# filter transparent values
valid_mask = ~tile_data.mask
assert np.all(img_data[~valid_mask] == 0)

valid_img = img_data[valid_mask]
valid_data = tile_uint8.compressed()

# gamma factor of 2 is sqrt(x) in [0, 1]
assert np.all(valid_img > valid_data)


@pytest.mark.parametrize(
"gamma_factor_params",
[
['-1', "Invalid gamma factor"],
['2,2', "Invalid gamma factor"],
['[1]', "Invalid gamma factor"],
['0', "Invalid gamma factor"],
],
)
def test_rgb_invalid_gamma_factor(use_testdb, raster_file_xyz, gamma_factor_params):
from terracotta.handlers import rgb

ds_keys = ["val21", "x", "val22"]
bands = ["val22", "val23", "val24"]

gamma_factor = gamma_factor_params[:2]
with pytest.raises(exceptions.InvalidArgumentsError) as err:
rgb.rgb(
ds_keys[:2],
bands,
raster_file_xyz,
gamma_factor=gamma_factor,
)
assert gamma_factor[1] in str(err.value)


def test_rgb_stretch_gamma_correction(use_testdb, testdb, raster_file_xyz):
import terracotta
from terracotta.xyz import get_tile_data
from terracotta.handlers import rgb

ds_keys = ["val21", "x", "val22"]
bands = ["val22", "val23", "val24"]
gamma_factor = 2
pct_stretch_range = ["p2", "p98"]

raw_img = rgb.rgb(
ds_keys[:2],
bands,
raster_file_xyz,
gamma_factor=gamma_factor,
stretch_ranges=[pct_stretch_range] * 3,
)
img_data = np.asarray(Image.open(raw_img))[..., 0]

# get unstretched data to compare to
driver = terracotta.get_driver(testdb)

with driver.connect():
tile_data = get_tile_data(
driver, ds_keys, tile_xyz=raster_file_xyz, tile_size=img_data.shape
)
band_metadata = driver.get_metadata(ds_keys)

stretch_range = [
band_metadata["percentiles"][1],
band_metadata["percentiles"][97],
]

# filter transparent values
valid_mask = ~tile_data.mask
assert np.all(img_data[~valid_mask] == 0)

valid_img = img_data[valid_mask]
valid_data = tile_data.compressed()

assert np.all(valid_img[valid_data < stretch_range[0]] == 1)
stretch_range_mask = (valid_data > stretch_range[0]) & (
valid_data < stretch_range[1]
)
assert np.all(valid_img[stretch_range_mask] >= 1)
assert np.all(valid_img[stretch_range_mask] <= 255)
assert np.all(valid_img[valid_data > stretch_range[1]] == 255)
112 changes: 0 additions & 112 deletions tests/handlers/test_singleband.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,115 +225,3 @@ def test_rgb_invalid_percentiles(use_testdb, stretch_range_params):
stretch_range=stretch_range,
)
assert stretch_range_params[2] in str(err.value)


def test_singleband_gamma_correction(use_testdb, testdb, raster_file_xyz):
import terracotta
from terracotta.xyz import get_tile_data
from terracotta.handlers import singleband
from terracotta import image

ds_keys = ["val21", "x", "val22"]
gamma_factor = 0.5

raw_img = singleband.singleband(
ds_keys,
tile_xyz=raster_file_xyz,
gamma_factor=gamma_factor,
)
img_data = np.asarray(Image.open(raw_img))

# get unstretched data to compare to
driver = terracotta.get_driver(testdb)

with driver.connect():
tile_data = get_tile_data(
driver, ds_keys, tile_xyz=raster_file_xyz, tile_size=img_data.shape
)

tile_metadata = driver.get_metadata(ds_keys)

# non-gamma corrected uint8 data
tile_uint8 = image.to_uint8(tile_data, *tile_metadata["range"])

# filter transparent values
valid_mask = ~tile_data.mask
assert np.all(img_data[~valid_mask] == 0)

valid_img = img_data[valid_mask]
valid_data = tile_uint8.compressed()

# gamma factor of 0.5 is x^2 in [0, 1]
assert np.all(valid_img < valid_data)


@pytest.mark.parametrize(
"gamma_factor_params",
[
['-1', "Invalid gamma factor"],
['2,2', "Invalid gamma factor"],
['[1]', "Invalid gamma factor"],
['0', "Invalid gamma factor"],
],
)
def test_singleband_invalid_gamma_factor(use_testdb, raster_file_xyz, gamma_factor_params):
from terracotta.handlers import singleband

ds_keys = ["val21", "x", "val22"]

gamma_factor = gamma_factor_params[:2]
with pytest.raises(exceptions.InvalidArgumentsError) as err:
singleband.singleband(
ds_keys,
raster_file_xyz,
gamma_factor=gamma_factor,
)
assert gamma_factor[1] in str(err.value)


def test_singleband_stretch_gamma(use_testdb, testdb, raster_file_xyz):
import terracotta
from terracotta.xyz import get_tile_data
from terracotta.handlers import singleband

ds_keys = ["val21", "x", "val22"]
gamma_factor = 2
pct_stretch_range = ["p2", "p98"]

raw_img = singleband.singleband(
ds_keys,
tile_xyz=raster_file_xyz,
gamma_factor=gamma_factor,
stretch_range=pct_stretch_range,
)
img_data = np.asarray(Image.open(raw_img))

# get unstretched data to compare to
driver = terracotta.get_driver(testdb)

with driver.connect():
tile_data = get_tile_data(
driver, ds_keys, tile_xyz=raster_file_xyz, tile_size=img_data.shape
)

band_metadata = driver.get_metadata(ds_keys)

stretch_range = [
band_metadata["percentiles"][1],
band_metadata["percentiles"][97],
]

# filter transparent values
valid_mask = ~tile_data.mask
assert np.all(img_data[~valid_mask] == 0)

valid_img = img_data[valid_mask]
valid_data = tile_data.compressed()

assert np.all(valid_img[valid_data < stretch_range[0]] == 1)
stretch_range_mask = (valid_data > stretch_range[0]) & (
valid_data < stretch_range[1]
)
assert np.all(valid_img[stretch_range_mask] >= 1)
assert np.all(valid_img[stretch_range_mask] <= 255)
assert np.all(valid_img[valid_data > stretch_range[1]] == 255)
28 changes: 0 additions & 28 deletions tests/server/test_flask_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,31 +588,3 @@ def test_get_rgb_invalid_stretch_percentile(
f"r_range={stretch_range}&b_range={stretch_range}&g_range={stretch_range}"
)
assert stretch_range_params[1] in str(exc.value)


@pytest.mark.parametrize(
"gamma_factor_params",
[
['-1', "Must be greater than 0"],
['2,2', "Not a valid number"],
['[1]', "Not a valid number"],
['0', "Must be greater than 0"],
],
)
def test_get_singleband_rgb_invalid_gamma_factor(
debug_client, use_testdb, raster_file_xyz, gamma_factor_params
):
x, y, z = raster_file_xyz
gamma_factor = gamma_factor_params[0]
with pytest.raises(marshmallow.ValidationError) as exc:
debug_client.get(
f"/rgb/val21/x/{z}/{x}/{y}.png?r=val22&g=val23&b=val24&"
f"gamma_factor={gamma_factor}"
)
assert gamma_factor_params[1] in str(exc.value)

with pytest.raises(marshmallow.ValidationError) as exc:
debug_client.get(
f"/singleband/val11/x/val21/{z}/{x}/{y}.png?gamma_factor={gamma_factor}"
)
assert gamma_factor_params[1] in str(exc.value)

0 comments on commit 21f2db2

Please sign in to comment.