#include <framework/mlt_cache.h>
#include <framework/mlt_log.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "../qimage/readexif.h"
#include <stdio.h>
#include <stdlib.h>
this->image = mlt_cache_item_data( this->image_cache, NULL );
// Check if user wants us to reload the image
- if ( mlt_properties_get_int( producer_props, "force_reload" ) || mlt_properties_get_int( producer_props, "_orientation" ) != mlt_properties_get_int( producer_props, "meta.attr.orientation" ) )
+ if ( mlt_properties_get_int( producer_props, "force_reload" ) )
{
pixbuf = NULL;
this->image = NULL;
this->image = NULL;
}
}
-
+ int disable_exif = mlt_properties_get_int( producer_props, "disable_exif" );
+
// optimization for subsequent iterations on single picture
if ( width != 0 && ( image_idx != this->image_idx || width != this->width || height != this->height ) )
this->image = NULL;
pixbuf = NULL;
mlt_log_debug( MLT_PRODUCER_SERVICE( producer ), "image %p pixbuf %p idx %d image_idx %d pixbuf_idx %d width %d\n",
this->image, pixbuf, image_idx, this->image_idx, this->pixbuf_idx, width );
- if ( !pixbuf && !this->image )
+ if ( ( !pixbuf && !this->image ) || mlt_properties_get_int( producer_props, "_disable_exif" ) != disable_exif )
{
this->image = NULL;
pixbuf = gdk_pixbuf_new_from_file( mlt_properties_get_value( this->filenames, image_idx ), &error );
if ( pixbuf )
{
- int exif_orientation = mlt_properties_get_int( producer_props, "meta.attr.orientation" );
-
- if ( exif_orientation > 1 )
- {
- GdkPixbuf *processed;
- GdkPixbufRotation matrix = GDK_PIXBUF_ROTATE_NONE;
-
- // Rotate image according to exif data
- switch ( exif_orientation ) {
- case 2:
- processed = gdk_pixbuf_flip ( pixbuf, TRUE );
- break;
- case 4:
- processed = gdk_pixbuf_flip ( pixbuf, FALSE );
- break;
- case 8:
- matrix = GDK_PIXBUF_ROTATE_CLOCKWISE;
- processed = pixbuf;
- break;
- case 3:
- matrix = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
- processed = pixbuf;
- break;
- case 6:
- matrix = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
- processed = pixbuf;
- break;
- case 5:
- matrix = GDK_PIXBUF_ROTATE_CLOCKWISE;
- processed = gdk_pixbuf_flip ( pixbuf, TRUE );
- break;
- case 7:
- matrix = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
- processed = gdk_pixbuf_flip ( pixbuf, TRUE );
- break;
-
- }
- pixbuf = gdk_pixbuf_rotate_simple( processed, matrix );
+ // Read the exif value for this file
+ if ( disable_exif == 0) {
+ int exif_orientation = check_exif_orientation(mlt_properties_get_value( this->filenames, image_idx ));
+
+ if ( exif_orientation > 1 )
+ {
+ GdkPixbuf *processed;
+ GdkPixbufRotation matrix = GDK_PIXBUF_ROTATE_NONE;
+
+ // Rotate image according to exif data
+ switch ( exif_orientation ) {
+ case 2:
+ processed = gdk_pixbuf_flip ( pixbuf, TRUE );
+ break;
+ case 3:
+ matrix = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
+ processed = pixbuf;
+ break;
+ case 4:
+ processed = gdk_pixbuf_flip ( pixbuf, FALSE );
+ break;
+ case 5:
+ matrix = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
+ processed = gdk_pixbuf_flip ( pixbuf, TRUE );
+ break;
+ case 6:
+ matrix = GDK_PIXBUF_ROTATE_CLOCKWISE;
+ processed = pixbuf;
+ break;
+ case 7:
+ matrix = GDK_PIXBUF_ROTATE_CLOCKWISE;
+ processed = gdk_pixbuf_flip ( pixbuf, TRUE );
+ break;
+ case 8:
+ matrix = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
+ processed = pixbuf;
+ break;
+ }
+ pixbuf = gdk_pixbuf_rotate_simple( processed, matrix );
+ }
}
// Register this pixbuf for destruction and reuse
mlt_cache_item_close( pixbuf_cache );
mlt_events_block( producer_props, NULL );
mlt_properties_set_int( producer_props, "_real_width", gdk_pixbuf_get_width( pixbuf ) );
mlt_properties_set_int( producer_props, "_real_height", gdk_pixbuf_get_height( pixbuf ) );
- mlt_properties_set_int( producer_props, "_orientation", exif_orientation );
+ mlt_properties_set_int( producer_props, "_disable_exif", disable_exif );
mlt_events_unblock( producer_props, NULL );
// Store the width/height of the pixbuf temporarily
*/
#include "qimage_wrapper.h"
+#include "readexif.h"
#ifdef USE_QT3
#include <qimage.h>
self->current_image = static_cast<uint8_t*>( mlt_cache_item_data( self->image_cache, NULL ) );
// Check if user wants us to reload the image
- if ( mlt_properties_get_int( producer_props, "force_reload" ) || mlt_properties_get_int( producer_props, "_orientation" ) != mlt_properties_get_int( producer_props, "meta.attr.orientation" ) )
+ if ( mlt_properties_get_int( producer_props, "force_reload" ) )
{
qimage = NULL;
self->current_image = NULL;
}
}
- // optimization for subsequent iterations on single picture
+ int disable_exif = mlt_properties_get_int( producer_props, "disable_exif" );
+
+ // optimization for subsequent iterations on single pictur
if ( width != 0 && ( image_idx != self->image_idx || width != self->current_width || height != self->current_height ) )
self->current_image = NULL;
if ( image_idx != self->qimage_idx )
qimage = NULL;
- if ( !qimage && !self->current_image )
+
+ if ( ( !qimage && !self->current_image ) || mlt_properties_get_int( producer_props, "_disable_exif" ) != disable_exif)
{
self->current_image = NULL;
qimage = new QImage( mlt_properties_get_value( self->filenames, image_idx ) );
if ( !qimage->isNull( ) )
{
- // Store the width/height of the qimage
- int exif_orientation = mlt_properties_get_int( producer_props, "meta.attr.orientation" );
-
- if ( exif_orientation > 1 )
- {
- // Rotate image according to exif data
- QImage processed;
- QMatrix matrix;
-
- switch ( exif_orientation ) {
- case 2:
- matrix.scale( -1, 1 );
- break;
- case 3:
- matrix.rotate( 180 );
- break;
- case 4:
- matrix.scale( 1, -1 );
- break;
- case 5:
- matrix.rotate( 270 );
- matrix.scale( -1, 1 );
- break;
- case 6:
- matrix.rotate( 90 );
- break;
- case 7:
- matrix.rotate( 90 );
- matrix.scale( -1, 1 );
- break;
- case 8:
- matrix.rotate( 270 );
- break;
- }
- processed = qimage->transformed( matrix );
- delete qimage;
- qimage = new QImage( processed );
+ // Read the exif value for this file
+ if ( disable_exif == 0) {
+ int exif_orientation = check_exif_orientation(mlt_properties_get_value( self->filenames, image_idx ));
+
+ if ( exif_orientation > 1 )
+ {
+ // Rotate image according to exif data
+ QImage processed;
+ QMatrix matrix;
+
+ switch ( exif_orientation ) {
+ case 2:
+ matrix.scale( -1, 1 );
+ break;
+ case 3:
+ matrix.rotate( 180 );
+ break;
+ case 4:
+ matrix.scale( 1, -1 );
+ break;
+ case 5:
+ matrix.rotate( 270 );
+ matrix.scale( -1, 1 );
+ break;
+ case 6:
+ matrix.rotate( 90 );
+ break;
+ case 7:
+ matrix.rotate( 90 );
+ matrix.scale( -1, 1 );
+ break;
+ case 8:
+ matrix.rotate( 270 );
+ break;
+ }
+ processed = qimage->transformed( matrix );
+ delete qimage;
+ qimage = new QImage( processed );
+ }
}
-
+
+ // Store the width/height of the qimage
self->current_width = qimage->width( );
self->current_height = qimage->height( );
mlt_events_block( producer_props, NULL );
mlt_properties_set_int( producer_props, "_real_width", self->current_width );
mlt_properties_set_int( producer_props, "_real_height", self->current_height );
- mlt_properties_set_int( producer_props, "_orientation", exif_orientation );
+ mlt_properties_set_int( producer_props, "_disable_exif", disable_exif );
mlt_events_unblock( producer_props, NULL );
}
else
--- /dev/null
+/*\r
+ * readexif.h\r
+ * \r
+ * Slightly modified for use in MLT by Jean-Baptiste Mardelle, 2010\r
+ * based on jpegexiforient.c, part of the `jpeg library' by the\r
+ * Independent JPEG Group (IJG)).\r
+ *\r
+ * The Exif orientation value gives the orientation of the camera\r
+ * relative to the scene when the image was captured. The relation\r
+ * of the '0th row' and '0th column' to visual position is shown as\r
+ * below.\r
+ * \r
+ *\r
+ * Value | 0th Row | 0th Column\r
+ * ------+-------------+-----------\r
+ * 1 | top | left side\r
+ * 2 | top | rigth side\r
+ * 3 | bottom | rigth side\r
+ * 4 | bottom | left side\r
+ * 5 | left side | top\r
+ * 6 | right side | top\r
+ * 7 | right side | bottom\r
+ * 8 | left side | bottom\r
+ *\r
+ * For convenience, here is what the letter F would look like if it were\r
+ * tagged correctly and displayed by a program that ignores the orientation\r
+ * tag:\r
+ *\r
+ * 1 2 3 4 5 6 7 8\r
+ *\r
+ * 888888 888888 88 88 8888888888 88 88 8888888888\r
+ * 88 88 88 88 88 88 88 88 88 88 88 88\r
+ * 8888 8888 8888 8888 88 8888888888 8888888888 88\r
+ * 88 88 88 88\r
+ * 88 88 888888 888888\r
+ *\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+static FILE * myfile;\r
+static unsigned char exif_data[65536L];\r
+\r
+/* Return next input byte, or EOF if no more */\r
+#define NEXTBYTE() getc(myfile)\r
+\r
+/* Error exit handler */\r
+#define ERREXIT(msg) (exit(0))\r
+\r
+/* Read one byte, testing for EOF */\r
+static int\r
+read_1_byte (void)\r
+{\r
+ int c;\r
+\r
+ c = NEXTBYTE();\r
+ if (c == EOF)\r
+ ERREXIT("Premature EOF in JPEG file");\r
+ return c;\r
+}\r
+\r
+/* Read 2 bytes, convert to unsigned int */\r
+/* All 2-byte quantities in JPEG markers are MSB first */\r
+static unsigned int\r
+read_2_bytes (void)\r
+{\r
+ int c1, c2;\r
+\r
+ c1 = NEXTBYTE();\r
+ if (c1 == EOF)\r
+ ERREXIT("Premature EOF in JPEG file");\r
+ c2 = NEXTBYTE();\r
+ if (c2 == EOF)\r
+ ERREXIT("Premature EOF in JPEG file");\r
+ return (((unsigned int) c1) << 8) + ((unsigned int) c2);\r
+}\r
+\r
+int check_exif_orientation(char *fname)\r
+{\r
+ int set_flag;\r
+ unsigned int length, i;\r
+ int is_motorola; /* Flag for byte order */\r
+ unsigned int offset, number_of_tags, tagnum;\r
+\r
+ if ((myfile = fopen(fname, "rb")) == NULL) {\r
+ fprintf(stderr, "can't open %s\n", fname);\r
+ return 0;\r
+ }\r
+\r
+ /* Read File head, check for JPEG SOI + Exif APP1 */\r
+ for (i = 0; i < 4; i++)\r
+ exif_data[i] = (unsigned char) read_1_byte();\r
+ if (exif_data[0] != 0xFF ||\r
+ exif_data[1] != 0xD8 ||\r
+ exif_data[2] != 0xFF ||\r
+ exif_data[3] != 0xE1)\r
+ return 0;\r
+ /* Get the marker parameter length count */\r
+ length = read_2_bytes();\r
+ /* Length includes itself, so must be at least 2 */\r
+ /* Following Exif data length must be at least 6 */\r
+ if (length < 8)\r
+ return 0;\r
+ length -= 8;\r
+ /* Read Exif head, check for "Exif" */\r
+ for (i = 0; i < 6; i++)\r
+ exif_data[i] = (unsigned char) read_1_byte();\r
+ if (exif_data[0] != 0x45 ||\r
+ exif_data[1] != 0x78 ||\r
+ exif_data[2] != 0x69 ||\r
+ exif_data[3] != 0x66 ||\r
+ exif_data[4] != 0 ||\r
+ exif_data[5] != 0)\r
+ return 0;\r
+ /* Read Exif body */\r
+ for (i = 0; i < length; i++)\r
+ exif_data[i] = (unsigned char) read_1_byte();\r
+\r
+ if (length < 12) return 0; /* Length of an IFD entry */\r
+\r
+ /* Discover byte order */\r
+ if (exif_data[0] == 0x49 && exif_data[1] == 0x49)\r
+ is_motorola = 0;\r
+ else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D)\r
+ is_motorola = 1;\r
+ else\r
+ return 0;\r
+\r
+ /* Check Tag Mark */\r
+ if (is_motorola) {\r
+ if (exif_data[2] != 0) return 0;\r
+ if (exif_data[3] != 0x2A) return 0;\r
+ } else {\r
+ if (exif_data[3] != 0) return 0;\r
+ if (exif_data[2] != 0x2A) return 0;\r
+ }\r
+\r
+ /* Get first IFD offset (offset to IFD0) */\r
+ if (is_motorola) {\r
+ if (exif_data[4] != 0) return 0;\r
+ if (exif_data[5] != 0) return 0;\r
+ offset = exif_data[6];\r
+ offset <<= 8;\r
+ offset += exif_data[7];\r
+ } else {\r
+ if (exif_data[7] != 0) return 0;\r
+ if (exif_data[6] != 0) return 0;\r
+ offset = exif_data[5];\r
+ offset <<= 8;\r
+ offset += exif_data[4];\r
+ }\r
+ if (offset > length - 2) return 0; /* check end of data segment */\r
+\r
+ /* Get the number of directory entries contained in this IFD */\r
+ if (is_motorola) {\r
+ number_of_tags = exif_data[offset];\r
+ number_of_tags <<= 8;\r
+ number_of_tags += exif_data[offset+1];\r
+ } else {\r
+ number_of_tags = exif_data[offset+1];\r
+ number_of_tags <<= 8;\r
+ number_of_tags += exif_data[offset];\r
+ }\r
+ if (number_of_tags == 0) return 0;\r
+ offset += 2;\r
+\r
+ /* Search for Orientation Tag in IFD0 */\r
+ for (;;) {\r
+ if (offset > length - 12) return 0; /* check end of data segment */\r
+ /* Get Tag number */\r
+ if (is_motorola) {\r
+ tagnum = exif_data[offset];\r
+ tagnum <<= 8;\r
+ tagnum += exif_data[offset+1];\r
+ } else {\r
+ tagnum = exif_data[offset+1];\r
+ tagnum <<= 8;\r
+ tagnum += exif_data[offset];\r
+ }\r
+ if (tagnum == 0x0112) break; /* found Orientation Tag */\r
+ if (--number_of_tags == 0) return 0;\r
+ offset += 12;\r
+ }\r
+ /* Get the Orientation value */\r
+ if (is_motorola) {\r
+ if (exif_data[offset+8] != 0) return 0;\r
+ set_flag = exif_data[offset+9];\r
+ } else {\r
+ if (exif_data[offset+9] != 0) return 0;\r
+ set_flag = exif_data[offset+8];\r
+ }\r
+ if (set_flag > 8) return 0;\r
+ return set_flag;\r
+}\r
+\r