Parse out Exif orientation

This commit is contained in:
Přemysl Eric Janouch 2021-11-26 03:31:33 +01:00
parent bafad1a67e
commit dd8461cebf
Signed by: p
GPG Key ID: A0420B94F92B9493
2 changed files with 28 additions and 6 deletions

View File

@ -994,8 +994,14 @@ open_gdkpixbuf(const gchar *data, gsize len, GError **error)
cairo_surface_t *surface = cairo_surface_t *surface =
gdk_cairo_surface_create_from_pixbuf(pixbuf, 1, NULL); gdk_cairo_surface_create_from_pixbuf(pixbuf, 1, NULL);
// TODO(p): Also pass the pre-decoded Exif "orientation" option, const char *orientation = gdk_pixbuf_get_option(pixbuf, "orientation");
// which is an ASCII digit from 1 to 8. if (orientation && strlen(orientation) == 1) {
int n = *orientation - '0';
if (n >= 1 && n <= 8)
cairo_surface_set_user_data(surface, &fastiv_io_key_orientation,
(void *) (uintptr_t) n, NULL);
}
const char *icc_profile = gdk_pixbuf_get_option(pixbuf, "icc-profile"); const char *icc_profile = gdk_pixbuf_get_option(pixbuf, "icc-profile");
if (icc_profile) { if (icc_profile) {
gsize out_len = 0; gsize out_len = 0;
@ -1014,6 +1020,7 @@ open_gdkpixbuf(const gchar *data, gsize len, GError **error)
#endif // HAVE_GDKPIXBUF ------------------------------------------------------ #endif // HAVE_GDKPIXBUF ------------------------------------------------------
cairo_user_data_key_t fastiv_io_key_exif; cairo_user_data_key_t fastiv_io_key_exif;
cairo_user_data_key_t fastiv_io_key_orientation;
cairo_user_data_key_t fastiv_io_key_icc; cairo_user_data_key_t fastiv_io_key_icc;
cairo_user_data_key_t fastiv_io_key_frame_next; cairo_user_data_key_t fastiv_io_key_frame_next;
@ -1120,6 +1127,19 @@ fastiv_io_open_from_data(const char *data, size_t len, const gchar *path,
set_error(error, "unsupported file type"); set_error(error, "unsupported file type");
} }
// gdk-pixbuf only gives out this single field--cater to its limitations,
// since we'd really like to have it.
GBytes *exif = NULL;
gsize exif_len = 0;
gconstpointer exif_data = NULL;
if (surface &&
(exif = cairo_surface_get_user_data(surface, &fastiv_io_key_exif)) &&
(exif_data = g_bytes_get_data(exif, &exif_len))) {
cairo_surface_set_user_data(surface, &fastiv_io_key_orientation,
(void *) (uintptr_t) fastiv_io_exif_orientation(
exif_data, exif_len), NULL);
}
return surface; return surface;
} }
@ -1160,11 +1180,11 @@ fastiv_io_exif_orientation(const guint8 *tiff, gsize len)
SBYTE, UNDEFINED, SSHORT, SLONG, SRATIONAL, FLOAT, DOUBLE }; SBYTE, UNDEFINED, SSHORT, SLONG, SRATIONAL, FLOAT, DOUBLE };
enum { Orientation = 274 }; enum { Orientation = 274 };
for (const guint8 *p = ifd0 + 2; fields-- && p + 12 <= end; p += 12) { for (const guint8 *p = ifd0 + 2; fields-- && p + 12 <= end; p += 12) {
uint16_t tag = u16(p), type = u16(p + 2); uint16_t tag = u16(p), type = u16(p + 2), value16 = u16(p + 8);
uint32_t count = u32(p + 4), value = u32(p + 8); uint32_t count = u32(p + 4);
if (tag == Orientation && type == SHORT && count == 1 && if (tag == Orientation && type == SHORT && count == 1 &&
value >= 1 && value <= 8) value16 >= 1 && value16 <= 8)
return value; return value16;
} }
return FastivIoOrientationUnknown; return FastivIoOrientationUnknown;
} }

View File

@ -29,6 +29,8 @@ char **fastiv_io_all_supported_media_types(void);
/// GBytes with plain Exif data. /// GBytes with plain Exif data.
extern cairo_user_data_key_t fastiv_io_key_exif; extern cairo_user_data_key_t fastiv_io_key_exif;
/// FastivIoOrientation, as a uintptr_t.
extern cairo_user_data_key_t fastiv_io_key_orientation;
/// GBytes with plain ICC profile data. /// GBytes with plain ICC profile data.
extern cairo_user_data_key_t fastiv_io_key_icc; extern cairo_user_data_key_t fastiv_io_key_icc;