From af1d2a51b37e7e57b39ee5a0e17cec275ef09a78 Mon Sep 17 00:00:00 2001 From: Frankie Dintino Date: Wed, 2 Apr 2025 21:56:24 -0400 Subject: [PATCH 1/2] fix: conversion of AVIF image rotation property to EXIF orientation This implements a fix for the issue identified in AOMediaCodec/libavif#2727 and fixed in AOMediaCodec/libavif#2729. The code to convert irot and imir properties to EXIF orientation when decoding AVIF images in Pillow was repurposed from libavif, so it suffers the same bug. --- src/_avif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_avif.c b/src/_avif.c index eabd9958e10..72b0997ec42 100644 --- a/src/_avif.c +++ b/src/_avif.c @@ -59,7 +59,7 @@ irot_imir_to_exif_orientation(const avifImage *image) { return axis ? 7 // 90 degrees anti-clockwise then swap left and right. : 5; // 90 degrees anti-clockwise then swap top and bottom. } - return 6; // 90 degrees anti-clockwise. + return 8; // 90 degrees anti-clockwise. } if (angle == 2) { if (imir) { @@ -75,7 +75,7 @@ irot_imir_to_exif_orientation(const avifImage *image) { ? 5 // 270 degrees anti-clockwise then swap left and right. : 7; // 270 degrees anti-clockwise then swap top and bottom. } - return 8; // 270 degrees anti-clockwise. + return 6; // 270 degrees anti-clockwise. } } if (imir) { From f7fc268a77c66b236d6069fe92cd4851241ac351 Mon Sep 17 00:00:00 2001 From: Frankie Dintino Date: Wed, 2 Apr 2025 22:39:06 -0400 Subject: [PATCH 2/2] add test --- Tests/test_file_avif.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/test_file_avif.py b/Tests/test_file_avif.py index 392a4bbd5b0..bd87947c014 100644 --- a/Tests/test_file_avif.py +++ b/Tests/test_file_avif.py @@ -309,7 +309,7 @@ def test_exif(self) -> None: assert exif[274] == 3 @pytest.mark.parametrize("use_bytes", [True, False]) - @pytest.mark.parametrize("orientation", [1, 2]) + @pytest.mark.parametrize("orientation", [1, 2, 3, 4, 5, 6, 7, 8]) def test_exif_save( self, tmp_path: Path, @@ -327,6 +327,7 @@ def test_exif_save( if orientation == 1: assert "exif" not in reloaded.info else: + assert reloaded.getexif()[274] == orientation assert reloaded.info["exif"] == exif_data def test_exif_without_orientation(self, tmp_path: Path) -> None: