Fix: Set tag type accordingly if IFDRational with 0 denominator

This commit is contained in:
Enric Pou 2025-05-21 13:48:46 +02:00
parent 3c71559804
commit 3ac0420d6c
3 changed files with 40 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,30 @@ 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)
assert math.isnan(reloaded.tag_v2[37380])
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

@ -74,3 +74,14 @@ 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, float("nan")),
],
)
def test_float_cast(numerator, denominator, expected_result):
float(IFDRational(numerator, denominator)) == expected_result

View File

@ -402,6 +402,9 @@ class IFDRational(Rational):
f = self._val.limit_denominator(max_denominator)
return f.numerator, f.denominator
def __float__(self):
return float(self._val)
def __repr__(self) -> str:
return str(float(self._val))
@ -688,7 +691,7 @@ class ImageFileDirectory_v2(_IFDv2Base):
if all(isinstance(v, IFDRational) for v in values):
for v in values:
assert isinstance(v, IFDRational)
if v < 0:
if v < 0 or (math.isnan(v) and v.numerator < 0):
self.tagtype[tag] = TiffTags.SIGNED_RATIONAL
break
else: