mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-06 14:40:51 +03:00
Do not ignore SyntaxError when saving EXIF data (#8)
* Do not ignore SyntaxError when saving EXIF data * Do not save orientation in EXIF data * Do not save XMP and EXIF data from info dictionary --------- Co-authored-by: Andrew Murray <radarhere@users.noreply.github.com>
This commit is contained in:
parent
c40bcbfc87
commit
d76ae2f10c
|
@ -329,17 +329,8 @@ class TestFileAvif:
|
||||||
exif = im.getexif()
|
exif = im.getexif()
|
||||||
assert exif[274] == 3
|
assert exif[274] == 3
|
||||||
|
|
||||||
def test_exif_save_default(self, tmp_path: Path) -> None:
|
|
||||||
with Image.open("Tests/images/avif/exif.avif") as im:
|
|
||||||
test_file = str(tmp_path / "temp.avif")
|
|
||||||
im.save(test_file)
|
|
||||||
|
|
||||||
with Image.open(test_file) as reloaded:
|
|
||||||
exif = reloaded.getexif()
|
|
||||||
assert exif[274] == 1
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("bytes", [True, False])
|
@pytest.mark.parametrize("bytes", [True, False])
|
||||||
def test_exif_save_argument(self, tmp_path: Path, bytes: bool) -> None:
|
def test_exif_save(self, tmp_path: Path, bytes: bool) -> None:
|
||||||
exif = Image.Exif()
|
exif = Image.Exif()
|
||||||
exif[274] = 1
|
exif[274] = 1
|
||||||
exif_data = exif.tobytes()
|
exif_data = exif.tobytes()
|
||||||
|
@ -353,7 +344,7 @@ class TestFileAvif:
|
||||||
def test_exif_invalid(self, tmp_path: Path) -> None:
|
def test_exif_invalid(self, tmp_path: Path) -> None:
|
||||||
with Image.open(TEST_AVIF_FILE) as im:
|
with Image.open(TEST_AVIF_FILE) as im:
|
||||||
test_file = str(tmp_path / "temp.avif")
|
test_file = str(tmp_path / "temp.avif")
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(SyntaxError):
|
||||||
im.save(test_file, exif=b"invalid")
|
im.save(test_file, exif=b"invalid")
|
||||||
|
|
||||||
def test_xmp(self) -> None:
|
def test_xmp(self) -> None:
|
||||||
|
@ -362,24 +353,6 @@ class TestFileAvif:
|
||||||
assert_xmp_orientation(xmp, 3)
|
assert_xmp_orientation(xmp, 3)
|
||||||
|
|
||||||
def test_xmp_save(self, tmp_path: Path) -> None:
|
def test_xmp_save(self, tmp_path: Path) -> None:
|
||||||
with Image.open("Tests/images/avif/xmp_tags_orientation.avif") as im:
|
|
||||||
test_file = str(tmp_path / "temp.avif")
|
|
||||||
im.save(test_file)
|
|
||||||
|
|
||||||
with Image.open(test_file) as reloaded:
|
|
||||||
xmp = reloaded.info["xmp"]
|
|
||||||
assert_xmp_orientation(xmp, 3)
|
|
||||||
|
|
||||||
def test_xmp_save_from_png(self, tmp_path: Path) -> None:
|
|
||||||
with Image.open("Tests/images/xmp_tags_orientation.png") as im:
|
|
||||||
test_file = str(tmp_path / "temp.avif")
|
|
||||||
im.save(test_file)
|
|
||||||
|
|
||||||
with Image.open(test_file) as reloaded:
|
|
||||||
xmp = reloaded.info["xmp"]
|
|
||||||
assert_xmp_orientation(xmp, 3)
|
|
||||||
|
|
||||||
def test_xmp_save_argument(self, tmp_path: Path) -> None:
|
|
||||||
xmp_arg = "\n".join(
|
xmp_arg = "\n".join(
|
||||||
[
|
[
|
||||||
'<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>',
|
'<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>',
|
||||||
|
|
|
@ -168,24 +168,19 @@ def _save(
|
||||||
autotiling = bool(info.get("autotiling", tile_rows_log2 == tile_cols_log2 == 0))
|
autotiling = bool(info.get("autotiling", tile_rows_log2 == tile_cols_log2 == 0))
|
||||||
|
|
||||||
icc_profile = info.get("icc_profile", im.info.get("icc_profile"))
|
icc_profile = info.get("icc_profile", im.info.get("icc_profile"))
|
||||||
exif = info.get("exif", im.info.get("exif"))
|
exif = info.get("exif")
|
||||||
if isinstance(exif, Image.Exif):
|
|
||||||
exif = exif.tobytes()
|
|
||||||
|
|
||||||
exif_orientation = 0
|
|
||||||
if exif:
|
if exif:
|
||||||
exif_data = Image.Exif()
|
if isinstance(exif, Image.Exif):
|
||||||
try:
|
exif_data = exif
|
||||||
exif_data.load(exif)
|
exif = exif.tobytes()
|
||||||
except SyntaxError:
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
orientation_tag = next(
|
exif_data = Image.Exif()
|
||||||
k for k, v in ExifTags.TAGS.items() if v == "Orientation"
|
exif_data.load(exif)
|
||||||
)
|
exif_orientation = exif_data.pop(ExifTags.Base.Orientation, 1)
|
||||||
exif_orientation = exif_data.get(orientation_tag) or 0
|
else:
|
||||||
|
exif_orientation = 1
|
||||||
|
|
||||||
xmp = info.get("xmp", im.info.get("xmp") or im.info.get("XML:com.adobe.xmp"))
|
xmp = info.get("xmp")
|
||||||
|
|
||||||
if isinstance(xmp, str):
|
if isinstance(xmp, str):
|
||||||
xmp = xmp.encode("utf-8")
|
xmp = xmp.encode("utf-8")
|
||||||
|
|
15
src/_avif.c
15
src/_avif.c
|
@ -170,22 +170,7 @@ exif_orientation_to_irot_imir(avifImage *image, int orientation) {
|
||||||
image->imir.mode = 0; // ignored
|
image->imir.mode = 0; // ignored
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
default: // reserved
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The orientation tag is not mandatory (only recommended) according to JEITA
|
|
||||||
// CP-3451C section 4.6.8.A. The default value is 1 if the orientation tag is
|
|
||||||
// missing, meaning:
|
|
||||||
// The 0th row is at the visual top of the image, and the 0th column is the visual
|
|
||||||
// left-hand side.
|
|
||||||
image->transformFlags = otherFlags;
|
|
||||||
image->irot.angle = 0; // ignored
|
|
||||||
#if AVIF_VERSION_MAJOR >= 1
|
|
||||||
image->imir.axis = 0; // ignored
|
|
||||||
#else
|
|
||||||
image->imir.mode = 0; // ignored
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in New Issue
Block a user