This commit is contained in:
Enric Pou 2025-05-28 07:27:43 +01:00 committed by GitHub
commit f65a7e5bd7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 55 additions and 1 deletions

View File

@ -1,6 +1,7 @@
from __future__ import annotations
import io
import math
import struct
from pathlib import Path
@ -280,6 +281,33 @@ def test_writing_other_types_to_undefined(
assert reloaded.tag_v2[33723] == b"1"
@pytest.mark.parametrize(
"value, expected",
(
(IFDRational(1, 0), TiffTags.RATIONAL),
(IFDRational(-1, 0), TiffTags.SIGNED_RATIONAL),
),
)
def test_tagtype_on_zero_denominator(
value: IFDRational, expected: int, tmp_path: Path
) -> None:
info = TiffImagePlugin.ImageFileDirectory_v2()
info[37380] = value
assert info.tagtype[37380] == expected
im = hopper()
out = tmp_path / "temp.tiff"
im.save(out, tiffinfo=info)
with Image.open(out) as reloaded:
assert isinstance(reloaded, TiffImagePlugin.TiffImageFile)
if expected == TiffTags.RATIONAL:
assert reloaded.tag_v2[37380] == math.inf
elif TiffTags.SIGNED_RATIONAL:
assert reloaded.tag_v2[37380] == -math.inf
def test_undefined_zero(tmp_path: Path) -> None:
# Check that the tag has not been changed since this test was created
tag = TiffTags.TAGS_V2[45059]

View File

@ -1,5 +1,6 @@
from __future__ import annotations
import math
from fractions import Fraction
from pathlib import Path
@ -74,3 +75,20 @@ def test_ifd_rational_save(
with Image.open(out) as reloaded:
assert isinstance(reloaded, TiffImagePlugin.TiffImageFile)
assert float(IFDRational(301, 1)) == float(reloaded.tag_v2[282])
@pytest.mark.parametrize(
"numerator, denominator, expected_result",
[
(1, 1, 1.0),
(1, 0, math.inf),
(-1, 0, -math.inf),
(0, 0, float("nan")),
],
)
def test_float_cast(numerator: int, denominator: int, expected_result: float) -> None:
value = float(IFDRational(numerator, denominator))
if math.isnan(expected_result):
assert value
else:
assert value == expected_result

View File

@ -372,7 +372,12 @@ class IFDRational(Rational):
self._denominator = denominator
if denominator == 0:
self._val = float("nan")
if value == 0:
self._val = float("nan")
elif value > 0:
self._val = math.inf
else:
self._val = -math.inf
elif denominator == 1:
self._val = Fraction(value)
elif int(value) == value:
@ -402,6 +407,9 @@ class IFDRational(Rational):
f = self._val.limit_denominator(max_denominator)
return f.numerator, f.denominator
def __float__(self) -> float:
return float(self._val)
def __repr__(self) -> str:
return str(float(self._val))