Fix #923: Wrong orientation in HEIC using EXIF
authorColin Clark <colin.clark@cclark.uk>
Sun, 12 Sep 2021 14:41:32 +0000 (15:41 +0100)
committerColin Clark <colin.clark@cclark.uk>
Sun, 12 Sep 2021 14:41:32 +0000 (15:41 +0100)
https://github.com/BestImageViewer/geeqie/issues/923

This is an excerpt from ISO/IEC 23008-12:2017(E):

---------
Metadata specified in Annex A or according to the item type and MIME
type values is descriptive and does not normatively affect the
presentation.
In particular, an image item can be rotated by 90°, 180°, or 270° using
the 'irot' transformative item property.
Rotation metadata, e.g. according to Annex A, is ignored in the
displaying process.

8.2 Metadata for image items
------------

Therefore libheif is rotating the image in accordance with the irot
property - and then Geeqie rotates it again using the Exif value.

If the libheif decoding option "ignore_transformations" is used, the
result is different on two systems I use - one one system the option is
ignored, and on the other system the option is used, but then no Exif
data is displayed for the file.
As the compiled code is the same in both cases, there must be an
influence from other system library files.

The implemented solution ignores the Exif rotation parameter and
inhibits writing manually applied rotation metadata for all files
processed by libheif.

src/filedata.c
src/image-load.c
src/image.c
src/layout_image.c
src/pan-view/pan-view.c
src/thumb.c
src/thumb_standard.c
src/typedefs.h

index f2c8795..e25b9d0 100644 (file)
@@ -716,6 +716,7 @@ static void file_data_free(FileData *fd)
        g_free(fd->owner);
        g_free(fd->group);
        g_free(fd->sym_link);
+       g_free(fd->format_name);
        g_assert(fd->sidecar_files == NULL); /* sidecar files must be freed before calling this */
 
        file_data_change_info_free(NULL, fd);
index 0b16457..e899ada 100644 (file)
@@ -887,6 +887,8 @@ static void image_loader_setup_loader(ImageLoader *il)
        g_free(format);
 #endif
 
+       il->fd->format_name = il->backend.get_format_name(il->loader);
+
        g_mutex_unlock(il->data_mutex);
 }
 
index 889f241..30a4bc1 100644 (file)
@@ -589,7 +589,14 @@ void image_alter_orientation(ImageWindow *imd, FileData *fd_n, AlterType type)
        else
                if (options->metadata.write_orientation)
                        {
-                       orientation = metadata_read_int(fd_n, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                       if (g_strcmp0(imd->image_fd->format_name, "heif") == 0)
+                               {
+                               orientation = EXIF_ORIENTATION_TOP_LEFT;
+                               }
+                       else
+                               {
+                               orientation = metadata_read_int(fd_n, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                               }
                        }
        }
 
@@ -620,13 +627,21 @@ void image_alter_orientation(ImageWindow *imd, FileData *fd_n, AlterType type)
 
        if (orientation != (fd_n->exif_orientation ? fd_n->exif_orientation : 1))
                {
-               if (!options->metadata.write_orientation)
+               if (g_strcmp0(fd_n->format_name, "heif") != 0)
+                       {
+                       if (!options->metadata.write_orientation)
+                               {
+                               /* user_orientation does not work together with options->metadata.write_orientation,
+                                  use either one or the other.
+                                  we must however handle switching metadata.write_orientation on and off, therefore
+                                  we just disable referencing new fd's, not unreferencing the old ones
+                               */
+                               if (fd_n->user_orientation == 0) file_data_ref(fd_n);
+                               fd_n->user_orientation = orientation;
+                               }
+                       }
+               else
                        {
-                       /* user_orientation does not work together with options->metadata.write_orientation,
-                          use either one or the other.
-                          we must however handle switching metadata.write_orientation on and off, therefore
-                          we just disable referencing new fd's, not unreferencing the old ones
-                       */
                        if (fd_n->user_orientation == 0) file_data_ref(fd_n);
                        fd_n->user_orientation = orientation;
                        }
@@ -637,15 +652,18 @@ void image_alter_orientation(ImageWindow *imd, FileData *fd_n, AlterType type)
                fd_n->user_orientation = 0;
                }
 
-       if (options->metadata.write_orientation)
+       if (g_strcmp0(fd_n->format_name, "heif") != 0)
                {
-               if (type == ALTER_NONE)
-                       {
-                       metadata_write_revert(fd_n, ORIENTATION_KEY);
-                       }
-               else
+               if (options->metadata.write_orientation)
                        {
-                       metadata_write_int(fd_n, ORIENTATION_KEY, orientation);
+                       if (type == ALTER_NONE)
+                               {
+                               metadata_write_revert(fd_n, ORIENTATION_KEY);
+                               }
+                       else
+                               {
+                               metadata_write_int(fd_n, ORIENTATION_KEY, orientation);
+                               }
                        }
                }
 
@@ -1377,8 +1395,16 @@ void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom, gboo
                        }
                else if (options->image.exif_rotate_enable)
                        {
-                       imd->orientation = metadata_read_int(imd->image_fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
-                       imd->image_fd->exif_orientation = imd->orientation;
+                       if (g_strcmp0(imd->image_fd->format_name, "heif") == 0)
+                               {
+                               imd->orientation = EXIF_ORIENTATION_TOP_LEFT;
+                               imd->image_fd->exif_orientation = imd->orientation;
+                               }
+                       else
+                               {
+                               imd->orientation = metadata_read_int(imd->image_fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                               imd->image_fd->exif_orientation = imd->orientation;
+                               }
                        }
                }
 
index b26f956..83e4170 100644 (file)
@@ -1279,7 +1279,14 @@ void layout_image_reset_orientation(LayoutWindow *lw)
 
        if (options->image.exif_rotate_enable)
                {
-               imd->orientation = metadata_read_int(imd->image_fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+               if (g_strcmp0(imd->image_fd->format_name, "heif") != 0)
+                       {
+                       imd->orientation = metadata_read_int(imd->image_fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                       }
+               else
+                       {
+                       imd->orientation = EXIF_ORIENTATION_TOP_LEFT;
+                       }
                }
        else
                {
index 956ec92..a17962e 100644 (file)
@@ -147,7 +147,14 @@ static void pan_queue_image_done_cb(ImageLoader *il, gpointer data)
                        {
                        if (!il->fd->exif_orientation)
                                {
-                               il->fd->exif_orientation = metadata_read_int(il->fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                               if (g_strcmp0(il->fd->format_name, "heif") != 0)
+                                       {
+                                       il->fd->exif_orientation = metadata_read_int(il->fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                                       }
+                               else
+                                       {
+                                       il->fd->exif_orientation = EXIF_ORIENTATION_TOP_LEFT;
+                                       }
                                }
 
                        if (il->fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT)
index 65b0387..2ab21c6 100644 (file)
@@ -155,7 +155,14 @@ static void thumb_loader_done_cb(ImageLoader *il, gpointer data)
                {
                if (!tl->fd->exif_orientation)
                        {
-                       tl->fd->exif_orientation = metadata_read_int(tl->fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                       if (g_strcmp0(il->fd->format_name, "heif") != 0)
+                               {
+                               tl->fd->exif_orientation = metadata_read_int(tl->fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                               }
+                       else
+                               {
+                               tl->fd->exif_orientation = EXIF_ORIENTATION_TOP_LEFT;
+                               }
                        }
 
                if (tl->fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT)
index 3ac2b4b..3f7a5cc 100644 (file)
@@ -497,7 +497,14 @@ static GdkPixbuf *thumb_loader_std_finish(ThumbLoaderStd *tl, GdkPixbuf *pixbuf,
                {
                if (!tl->fd->exif_orientation)
                        {
-                       tl->fd->exif_orientation = metadata_read_int(tl->fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                       if (g_strcmp0(tl->fd->format_name, "heif") != 0)
+                               {
+                               tl->fd->exif_orientation = metadata_read_int(tl->fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                               }
+                       else
+                               {
+                               tl->fd->exif_orientation = EXIF_ORIENTATION_TOP_LEFT;
+                               }
                        }
 
                if (tl->fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT)
index 1625b51..7d6095f 100644 (file)
@@ -599,6 +599,7 @@ struct _FileData {
        const gchar *extension;
        gchar *extended_extension;
        FileFormatClass format_class;
+       gchar *format_name; /**< set by the image loader */
        gchar *collate_key_name;
        gchar *collate_key_name_nocase;
        gint64 size;