summaryrefslogtreecommitdiff
path: root/plugins/AdvaImg/src/Metadata/Exif.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/AdvaImg/src/Metadata/Exif.cpp')
-rw-r--r--plugins/AdvaImg/src/Metadata/Exif.cpp158
1 files changed, 145 insertions, 13 deletions
diff --git a/plugins/AdvaImg/src/Metadata/Exif.cpp b/plugins/AdvaImg/src/Metadata/Exif.cpp
index ed667b0974..abc840607b 100644
--- a/plugins/AdvaImg/src/Metadata/Exif.cpp
+++ b/plugins/AdvaImg/src/Metadata/Exif.cpp
@@ -515,17 +515,18 @@ processExifTag(FIBITMAP *dib, FITAG *tag, char *pval, BOOL msb_order, TagLib::MD
}
/**
- Process Exif directory
-
- @param dib Input FIBITMAP
- @param tiffp Pointer to the TIFF header
- @param offset 0th IFD offset
- @param length Length of the datafile
- @param msb_order Endianess order of the datafile
- @return
+Process Exif directory
+
+@param dib Input FIBITMAP
+@param tiffp Pointer to the TIFF header
+@param offset 0th IFD offset
+@param length Length of the datafile
+@param msb_order Endianess order of the datafile
+@param starting_md_model Metadata model of the IFD (should be TagLib::EXIF_MAIN for a jpeg)
+@return Returns TRUE if sucessful, returns FALSE otherwise
*/
static BOOL
-jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsigned int length, BOOL msb_order) {
+jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsigned int length, BOOL msb_order, TagLib::MDMODEL starting_md_model) {
WORD de, nde;
std::stack<WORD> destack; // directory entries stack
@@ -548,7 +549,7 @@ jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsig
// set the metadata model to Exif
- TagLib::MDMODEL md_model = TagLib::EXIF_MAIN;
+ TagLib::MDMODEL md_model = starting_md_model;
// set the pointer to the first IFD (0th IFD) and follow it were it leads.
@@ -787,6 +788,8 @@ jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsig
return TRUE;
}
+// --------------------------------------------------------------------------
+
/**
Read and decode JPEG_APP1 marker (Exif profile)
@param dib Input FIBITMAP
@@ -795,7 +798,7 @@ jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsig
@return Returns TRUE if successful, FALSE otherwise
*/
BOOL
-jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
+jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned datalen) {
// marker identifying string for Exif = "Exif\0\0"
BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
BYTE lsb_first[4] = { 0x49, 0x49, 0x2A, 0x00 }; // Intel order
@@ -849,11 +852,140 @@ jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen)
}
*/
- // process Exif directories
- return jpeg_read_exif_dir(dib, profile, first_offset, length, bMotorolaOrder);
+ // process Exif directories, starting with Exif-TIFF IFD
+ return jpeg_read_exif_dir(dib, profile, first_offset, length, bMotorolaOrder, TagLib::EXIF_MAIN);
}
return FALSE;
}
+/**
+ Read JPEG_APP1 marker (Exif profile)
+ @param dib Input FIBITMAP
+ @param dataptr Pointer to the APP1 marker
+ @param datalen APP1 marker length
+ @return Returns TRUE if successful, FALSE otherwise
+*/
+BOOL
+jpeg_read_exif_profile_raw(FIBITMAP *dib, const BYTE *profile, unsigned length) {
+ // marker identifying string for Exif = "Exif\0\0"
+ BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
+
+ // verify the identifying string
+ if(memcmp(exif_signature, profile, sizeof(exif_signature)) != 0) {
+ // not an Exif profile
+ return FALSE;
+ }
+
+ // create a tag
+ FITAG *tag = FreeImage_CreateTag();
+ if(tag) {
+ FreeImage_SetTagKey(tag, g_TagLib_ExifRawFieldName);
+ FreeImage_SetTagLength(tag, (DWORD)length);
+ FreeImage_SetTagCount(tag, (DWORD)length);
+ FreeImage_SetTagType(tag, FIDT_BYTE);
+ FreeImage_SetTagValue(tag, profile);
+
+ // store the tag
+ FreeImage_SetMetadata(FIMD_EXIF_RAW, dib, FreeImage_GetTagKey(tag), tag);
+
+ // destroy the tag
+ FreeImage_DeleteTag(tag);
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+Read and decode JPEG-XR Exif IFD
+@param dib Input FIBITMAP
+@param profile Pointer to the Exif marker
+@param length Exif marker length
+@return Returns TRUE if successful, FALSE otherwise
+*/
+BOOL
+jpegxr_read_exif_profile(FIBITMAP *dib, const BYTE *profile, unsigned length) {
+ // assume Little Endian order
+ BOOL bMotorolaOrder = FALSE;
+
+ // process Exif specific IFD
+ return jpeg_read_exif_dir(dib, profile, 0, length, bMotorolaOrder, TagLib::EXIF_EXIF);
+}
+
+/**
+Read and decode JPEG-XR Exif-GPS IFD
+@param dib Input FIBITMAP
+@param profile Pointer to the Exif-GPS marker
+@param length Exif-GPS marker length
+@return Returns TRUE if successful, FALSE otherwise
+*/
+BOOL
+jpegxr_read_exif_gps_profile(FIBITMAP *dib, const BYTE *profile, unsigned length) {
+ // assume Little Endian order
+ BOOL bMotorolaOrder = FALSE;
+
+ // process Exif GPS IFD
+ return jpeg_read_exif_dir(dib, profile, 0, length, bMotorolaOrder, TagLib::EXIF_GPS);
+}
+
+/**
+Rotate a dib according to Exif info
+@param dib Input / Output dib to rotate
+@see PluginJPEG.cpp
+*/
+void
+RotateExif(FIBITMAP **dib) {
+ // check for Exif rotation
+ if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, *dib)) {
+ FIBITMAP *rotated = NULL;
+ // process Exif rotation
+ FITAG *tag = NULL;
+ FreeImage_GetMetadata(FIMD_EXIF_MAIN, *dib, "Orientation", &tag);
+ if(tag != NULL) {
+ if(FreeImage_GetTagID(tag) == TAG_ORIENTATION) {
+ unsigned short orientation = *((unsigned short *)FreeImage_GetTagValue(tag));
+ switch (orientation) {
+ case 1: // "top, left side" => 0°
+ break;
+ case 2: // "top, right side" => flip left-right
+ FreeImage_FlipHorizontal(*dib);
+ break;
+ case 3: // "bottom, right side"; => -180°
+ rotated = FreeImage_Rotate(*dib, 180);
+ FreeImage_Unload(*dib);
+ *dib = rotated;
+ break;
+ case 4: // "bottom, left side" => flip up-down
+ FreeImage_FlipVertical(*dib);
+ break;
+ case 5: // "left side, top" => +90° + flip up-down
+ rotated = FreeImage_Rotate(*dib, 90);
+ FreeImage_Unload(*dib);
+ *dib = rotated;
+ FreeImage_FlipVertical(*dib);
+ break;
+ case 6: // "right side, top" => -90°
+ rotated = FreeImage_Rotate(*dib, -90);
+ FreeImage_Unload(*dib);
+ *dib = rotated;
+ break;
+ case 7: // "right side, bottom" => -90° + flip up-down
+ rotated = FreeImage_Rotate(*dib, -90);
+ FreeImage_Unload(*dib);
+ *dib = rotated;
+ FreeImage_FlipVertical(*dib);
+ break;
+ case 8: // "left side, bottom" => +90°
+ rotated = FreeImage_Rotate(*dib, 90);
+ FreeImage_Unload(*dib);
+ *dib = rotated;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+}