summaryrefslogtreecommitdiff
path: root/plugins/FreeImage/Source/Metadata
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2012-05-30 17:27:49 +0000
committerGeorge Hazan <george.hazan@gmail.com>2012-05-30 17:27:49 +0000
commit88708cffa15662dcd2755fce699112d24a10a087 (patch)
tree55d362220b42a52b52eaef2254f894c9a61fb4fd /plugins/FreeImage/Source/Metadata
parent7fa5563a954339f3feeb156285ef56bfde7cbec8 (diff)
update for zlib & FreeImage
git-svn-id: http://svn.miranda-ng.org/main/trunk@238 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/FreeImage/Source/Metadata')
-rw-r--r--plugins/FreeImage/Source/Metadata/Exif.cpp1677
-rw-r--r--plugins/FreeImage/Source/Metadata/FIRational.cpp352
-rw-r--r--plugins/FreeImage/Source/Metadata/FIRational.h216
-rw-r--r--plugins/FreeImage/Source/Metadata/FreeImageTag.cpp605
-rw-r--r--plugins/FreeImage/Source/Metadata/FreeImageTag.h912
-rw-r--r--plugins/FreeImage/Source/Metadata/IPTC.cpp650
-rw-r--r--plugins/FreeImage/Source/Metadata/TagConversion.cpp128
-rw-r--r--plugins/FreeImage/Source/Metadata/TagLib.cpp2993
-rw-r--r--plugins/FreeImage/Source/Metadata/XTIFF.cpp188
9 files changed, 4157 insertions, 3564 deletions
diff --git a/plugins/FreeImage/Source/Metadata/Exif.cpp b/plugins/FreeImage/Source/Metadata/Exif.cpp
index bf6347da2b..ed667b0974 100644
--- a/plugins/FreeImage/Source/Metadata/Exif.cpp
+++ b/plugins/FreeImage/Source/Metadata/Exif.cpp
@@ -1,818 +1,859 @@
-// ==========================================================
-// Metadata functions implementation
-// Exif metadata model
-//
-// Design and implementation by
-// - Hervé Drolon (drolon@infonie.fr)
-// - Mihail Naydenov (mnaydenov@users.sourceforge.net)
-//
-// Based on the following implementations:
-// - metadata-extractor : http://www.drewnoakes.com/code/exif/
-// - jhead : http://www.sentex.net/~mwandel/jhead/
-// - ImageMagick : http://www.imagemagick.org/
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#ifdef _MSC_VER
-#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
-#endif
-
-#include "FreeImage.h"
-#include "Utilities.h"
-#include "FreeImageTag.h"
-
-// ==========================================================
-// Exif JPEG routines
-// ==========================================================
-
-#define EXIF_NUM_FORMATS 12
-
-#define TAG_EXIF_OFFSET 0x8769 // Exif IFD Pointer
-#define TAG_GPS_OFFSET 0x8825 // GPS Info IFD Pointer
-#define TAG_INTEROP_OFFSET 0xA005 // Interoperability IFD Pointer
-#define TAG_MAKER_NOTE 0x927C // Maker note
-
-// CANON cameras have some funny bespoke fields that need further processing...
-#define TAG_CANON_CAMERA_STATE_0x01 0x0001 // tags under tag 0x001 (CameraSettings)
-#define TAG_CANON_CAMERA_STATE_0x02 0x0002 // tags under tag 0x002 (FocalLength)
-#define TAG_CANON_CAMERA_STATE_0x04 0x0004 // tags under tag 0x004 (ShotInfo)
-#define TAG_CANON_CAMERA_STATE_0x12 0x0012 // tags under tag 0x012 (AFInfo)
-#define TAG_CANON_CAMERA_STATE_0xA0 0x00A0 // tags under tag 0x0A0 (ProcessingInfo)
-#define TAG_CANON_CAMERA_STATE_0xE0 0x00E0 // tags under tag 0x0E0 (SensorInfo)
-
-
-// =====================================================================
-// Reimplementation of strnicmp (it is not supported on some systems)
-// =====================================================================
-
-static int
-FreeImage_strnicmp(const char *s1, const char *s2, size_t len) {
- unsigned char c1, c2;
-
- if(!s1 || !s2) return -1;
-
- c1 = 0; c2 = 0;
- if(len) {
- do {
- c1 = *s1; c2 = *s2;
- s1++; s2++;
- if (!c1)
- break;
- if (!c2)
- break;
- if (c1 == c2)
- continue;
- c1 = (BYTE)tolower(c1);
- c2 = (BYTE)tolower(c2);
- if (c1 != c2)
- break;
- } while (--len);
- }
- return (int)c1 - (int)c2;
-}
-
-
-// ----------------------------------------------------------
-// Little Endian / Big Endian io routines
-// ----------------------------------------------------------
-
-static short
-ReadInt16(BOOL msb_order, const void *buffer) {
- short value;
-
- if(msb_order) {
- value = (short)((((BYTE*) buffer)[0] << 8) | ((BYTE*) buffer)[1]);
- return value;
- }
- value = (short)((((BYTE*) buffer)[1] << 8) | ((BYTE*) buffer)[0]);
- return value;
-}
-
-static LONG
-ReadInt32(BOOL msb_order, const void *buffer) {
- LONG value;
-
- if(msb_order) {
- value = (LONG)((((BYTE*) buffer)[0] << 24) | (((BYTE*) buffer)[1] << 16) | (((BYTE*) buffer)[2] << 8) | (((BYTE*) buffer)[3]));
- return value;
- }
- value = (LONG)((((BYTE*) buffer)[3] << 24) | (((BYTE*) buffer)[2] << 16) | (((BYTE*) buffer)[1] << 8 ) | (((BYTE*) buffer)[0]));
- return value;
-}
-
-static unsigned short
-ReadUint16(BOOL msb_order, const void *buffer) {
- unsigned short value;
-
- if(msb_order) {
- value = (unsigned short) ((((BYTE*) buffer)[0] << 8) | ((BYTE*) buffer)[1]);
- return value;
- }
- value = (unsigned short) ((((BYTE*) buffer)[1] << 8) | ((BYTE*) buffer)[0]);
- return value;
-}
-
-static DWORD
-ReadUint32(BOOL msb_order, const void *buffer) {
- return ((DWORD) ReadInt32(msb_order, buffer) & 0xFFFFFFFF);
-}
-
-// ----------------------------------------------------------
-// Exif JPEG markers routines
-// ----------------------------------------------------------
-
-/**
-Process a IFD offset
-Returns the offset and the metadata model for this tag
-*/
-static void
-processIFDOffset(FITAG *tag, char *pval, BOOL msb_order, DWORD *subdirOffset, TagLib::MDMODEL *md_model) {
- // get the IFD offset
- *subdirOffset = (DWORD) ReadUint32(msb_order, pval);
-
- // select a tag info table
- switch(FreeImage_GetTagID(tag)) {
- case TAG_EXIF_OFFSET:
- *md_model = TagLib::EXIF_EXIF;
- break;
- case TAG_GPS_OFFSET:
- *md_model = TagLib::EXIF_GPS;
- break;
- case TAG_INTEROP_OFFSET:
- *md_model = TagLib::EXIF_INTEROP;
- break;
- }
-
-}
-
-/**
-Process a maker note IFD offset
-Returns the offset and the metadata model for this tag
-*/
-static void
-processMakerNote(FIBITMAP *dib, char *pval, BOOL msb_order, DWORD *subdirOffset, TagLib::MDMODEL *md_model) {
- FITAG *tagMake = NULL;
-
- *subdirOffset = 0;
- *md_model = TagLib::UNKNOWN;
-
- // Determine the camera model and makernote format
- // WARNING: note that Maker may be NULL sometimes so check its value before using it
- // (NULL pointer checking is done by FreeImage_strnicmp)
- FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "Make", &tagMake);
- const char *Maker = (char*)FreeImage_GetTagValue(tagMake);
-
- if((strncmp("OLYMP\x00\x01", pval, 7) == 0) || (strncmp("OLYMP\x00\x02", pval, 7) == 0) || (strncmp("EPSON", pval, 5) == 0) || (strncmp("AGFA", pval, 4) == 0)) {
- // Olympus Type 1 Makernote
- // Epson and Agfa use Olympus maker note standard,
- // see: http://www.ozhiker.com/electronics/pjmt/jpeg_info/
- *md_model = TagLib::EXIF_MAKERNOTE_OLYMPUSTYPE1;
- *subdirOffset = 8;
- }
- else if(strncmp("OLYMPUS\x00\x49\x49\x03\x00", pval, 12) == 0) {
- // Olympus Type 2 Makernote
- // !!! NOT YET SUPPORTED !!!
- *subdirOffset = 0;
- *md_model = TagLib::UNKNOWN;
- }
- else if(strncmp("Nikon", pval, 5) == 0) {
- /* There are two scenarios here:
- * Type 1:
- * :0000: 4E 69 6B 6F 6E 00 01 00-05 00 02 00 02 00 06 00 Nikon...........
- * :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................
- * Type 3:
- * :0000: 4E 69 6B 6F 6E 00 02 00-00 00 4D 4D 00 2A 00 00 Nikon....MM.*...
- * :0010: 00 08 00 1E 00 01 00 07-00 00 00 04 30 32 30 30 ............0200
- */
- if (pval[6] == 1) {
- // Nikon type 1 Makernote
- *md_model = TagLib::EXIF_MAKERNOTE_NIKONTYPE1;
- *subdirOffset = 8;
- } else if (pval[6] == 2) {
- // Nikon type 3 Makernote
- *md_model = TagLib::EXIF_MAKERNOTE_NIKONTYPE3;
- *subdirOffset = 18;
- } else {
- // Unsupported makernote data ignored
- *md_model = TagLib::UNKNOWN;
- }
- } else if(Maker && (FreeImage_strnicmp("NIKON", Maker, 5) == 0)) {
- // Nikon type 2 Makernote
- *md_model = TagLib::EXIF_MAKERNOTE_NIKONTYPE2;
- *subdirOffset = 0;
- } else if(Maker && (FreeImage_strnicmp("Canon", Maker, 5) == 0)) {
- // Canon Makernote
- *md_model = TagLib::EXIF_MAKERNOTE_CANON;
- *subdirOffset = 0;
- } else if(Maker && (FreeImage_strnicmp("Casio", Maker, 5) == 0)) {
- // Casio Makernote
- if(strncmp("QVC\x00\x00\x00", pval, 6) == 0) {
- // Casio Type 2 Makernote
- *md_model = TagLib::EXIF_MAKERNOTE_CASIOTYPE2;
- *subdirOffset = 6;
- } else {
- // Casio Type 1 Makernote
- *md_model = TagLib::EXIF_MAKERNOTE_CASIOTYPE1;
- *subdirOffset = 0;
- }
- } else if ((strncmp("FUJIFILM", pval, 8) == 0) || (Maker && (FreeImage_strnicmp("Fujifilm", Maker, 8) == 0))) {
- // Fujifile Makernote
- // Fujifilm's Makernote always use Intel order altough the Exif section maybe in Intel order or in Motorola order.
- // If msb_order == TRUE, the Makernote won't be read:
- // the value of ifdStart will be 0x0c000000 instead of 0x0000000c and the MakerNote section will be discarded later
- // in jpeg_read_exif_dir because the IFD is too high
- *md_model = TagLib::EXIF_MAKERNOTE_FUJIFILM;
- DWORD ifdStart = (DWORD) ReadUint32(msb_order, pval + 8);
- *subdirOffset = ifdStart;
- }
- else if(memcmp("KYOCERA \x00\x00\x00", pval, 22) == 0) {
- *md_model = TagLib::EXIF_MAKERNOTE_KYOCERA;
- *subdirOffset = 22;
- }
- else if(Maker && (FreeImage_strnicmp("Minolta", Maker, 7) == 0)) {
- // Minolta maker note
- *md_model = TagLib::EXIF_MAKERNOTE_MINOLTA;
- *subdirOffset = 0;
- }
- else if(memcmp("Panasonic\x00\x00\x00", pval, 12) == 0) {
- // Panasonic maker note
- *md_model = TagLib::EXIF_MAKERNOTE_PANASONIC;
- *subdirOffset = 12;
- }
- else if(Maker && ((FreeImage_strnicmp("Pentax", Maker, 6) == 0) || (FreeImage_strnicmp("Asahi", Maker, 5) == 0))) {
- // Pentax maker note
- if(strncmp("AOC\x00", pval, 4) == 0) {
- // Type 2 Pentax Makernote
- *md_model = TagLib::EXIF_MAKERNOTE_PENTAX;
- *subdirOffset = 6;
- } else {
- // Type 1 Pentax Makernote
- *md_model = TagLib::EXIF_MAKERNOTE_ASAHI;
- *subdirOffset = 0;
- }
- }
- else if((strncmp("SONY CAM", pval, 8) == 0) || (strncmp("SONY DSC", pval, 8) == 0)) {
- *md_model = TagLib::EXIF_MAKERNOTE_SONY;
- *subdirOffset = 12;
- }
-}
-
-/**
-Process a Canon maker note tag.
-A single Canon tag may contain many other tags within.
-*/
-static BOOL
-processCanonMakerNoteTag(FIBITMAP *dib, FITAG *tag) {
- char defaultKey[16];
- DWORD startIndex = 0;
- TagLib& s = TagLib::instance();
-
- WORD tag_id = FreeImage_GetTagID(tag);
-
- int subTagTypeBase = 0;
-
- switch(tag_id) {
- case TAG_CANON_CAMERA_STATE_0x01:
- subTagTypeBase = 0xC100;
- startIndex = 1;
- break;
- case TAG_CANON_CAMERA_STATE_0x02:
- subTagTypeBase = 0xC200;
- startIndex = 0;
- break;
- case TAG_CANON_CAMERA_STATE_0x04:
- subTagTypeBase = 0xC400;
- startIndex = 1;
- break;
- case TAG_CANON_CAMERA_STATE_0x12:
- subTagTypeBase = 0x1200;
- startIndex = 0;
- break;
- case TAG_CANON_CAMERA_STATE_0xA0:
- subTagTypeBase = 0xCA00;
- startIndex = 1;
- break;
- case TAG_CANON_CAMERA_STATE_0xE0:
- subTagTypeBase = 0xCE00;
- startIndex = 1;
- break;
-
- default:
- {
- // process as a normal tag
-
- // get the tag key and description
- const char *key = s.getTagFieldName(TagLib::EXIF_MAKERNOTE_CANON, tag_id, defaultKey);
- FreeImage_SetTagKey(tag, key);
- const char *description = s.getTagDescription(TagLib::EXIF_MAKERNOTE_CANON, tag_id);
- FreeImage_SetTagDescription(tag, description);
-
- // store the tag
- if(key) {
- FreeImage_SetMetadata(FIMD_EXIF_MAKERNOTE, dib, key, tag);
- }
-
- return TRUE;
- }
- break;
-
- }
-
- WORD *pvalue = (WORD*)FreeImage_GetTagValue(tag);
-
- // create a tag
- FITAG *canonTag = FreeImage_CreateTag();
- if(!canonTag) return FALSE;
-
- // we intentionally skip the first array member (if needed)
- for (DWORD i = startIndex; i < FreeImage_GetTagCount(tag); i++) {
-
- tag_id = (WORD)(subTagTypeBase + i);
-
- FreeImage_SetTagID(canonTag, tag_id);
- FreeImage_SetTagType(canonTag, FIDT_SHORT);
- FreeImage_SetTagCount(canonTag, 1);
- FreeImage_SetTagLength(canonTag, 2);
- FreeImage_SetTagValue(canonTag, &pvalue[i]);
-
- // get the tag key and description
- const char *key = s.getTagFieldName(TagLib::EXIF_MAKERNOTE_CANON, tag_id, defaultKey);
- FreeImage_SetTagKey(canonTag, key);
- const char *description = s.getTagDescription(TagLib::EXIF_MAKERNOTE_CANON, tag_id);
- FreeImage_SetTagDescription(canonTag, description);
-
- // store the tag
- if(key) {
- FreeImage_SetMetadata(FIMD_EXIF_MAKERNOTE, dib, key, canonTag);
- }
- }
-
- // delete the tag
- FreeImage_DeleteTag(canonTag);
-
- return TRUE;
-}
-
-/**
-Process a standard Exif tag
-*/
-static void
-processExifTag(FIBITMAP *dib, FITAG *tag, char *pval, BOOL msb_order, TagLib::MDMODEL md_model) {
- char defaultKey[16];
- int n;
- DWORD i;
-
- // allocate a buffer to store the tag value
- BYTE *exif_value = (BYTE*)malloc(FreeImage_GetTagLength(tag) * sizeof(BYTE));
- if(NULL == exif_value) {
- // out of memory ...
- return;
- }
- memset(exif_value, 0, FreeImage_GetTagLength(tag) * sizeof(BYTE));
-
- // get the tag value
- switch(FreeImage_GetTagType(tag)) {
-
- case FIDT_SHORT:
- {
- WORD *value = (WORD*)&exif_value[0];
- for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
- value[i] = ReadUint16(msb_order, pval + i * sizeof(WORD));
- }
- FreeImage_SetTagValue(tag, value);
- break;
- }
- case FIDT_SSHORT:
- {
- short *value = (short*)&exif_value[0];
- for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
- value[i] = ReadInt16(msb_order, pval + i * sizeof(short));
- }
- FreeImage_SetTagValue(tag, value);
- break;
- }
- case FIDT_LONG:
- {
- DWORD *value = (DWORD*)&exif_value[0];
- for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
- value[i] = ReadUint32(msb_order, pval + i * sizeof(DWORD));
- }
- FreeImage_SetTagValue(tag, value);
- break;
- }
- case FIDT_SLONG:
- {
- LONG *value = (LONG*)&exif_value[0];
- for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
- value[i] = ReadInt32(msb_order, pval + i * sizeof(LONG));
- }
- FreeImage_SetTagValue(tag, value);
- break;
- }
- case FIDT_RATIONAL:
- {
- n = sizeof(DWORD);
-
- DWORD *value = (DWORD*)&exif_value[0];
- for(i = 0; i < 2 * FreeImage_GetTagCount(tag); i++) {
- // read a sequence of (numerator, denominator)
- value[i] = ReadUint32(msb_order, n*i + (char*)pval);
- }
- FreeImage_SetTagValue(tag, value);
- break;
- }
- case FIDT_SRATIONAL:
- {
- n = sizeof(LONG);
-
- LONG *value = (LONG*)&exif_value[0];
- for(i = 0; i < 2 * FreeImage_GetTagCount(tag); i++) {
- // read a sequence of (numerator, denominator)
- value[i] = ReadInt32(msb_order, n*i + (char*)pval);
- }
- FreeImage_SetTagValue(tag, value);
- break;
- }
- case FIDT_BYTE:
- case FIDT_ASCII:
- case FIDT_SBYTE:
- case FIDT_UNDEFINED:
- case FIDT_FLOAT:
- case FIDT_DOUBLE:
- default:
- FreeImage_SetTagValue(tag, pval);
- break;
- }
-
- if(md_model == TagLib::EXIF_MAKERNOTE_CANON) {
- // A single Canon tag can have multiple values within
- processCanonMakerNoteTag(dib, tag);
- }
- else {
- TagLib& s = TagLib::instance();
-
- WORD tag_id = FreeImage_GetTagID(tag);
-
- // get the tag key and description
- const char *key = s.getTagFieldName(md_model, tag_id, defaultKey);
- FreeImage_SetTagKey(tag, key);
- const char *description = s.getTagDescription(md_model, tag_id);
- FreeImage_SetTagDescription(tag, description);
-
- // store the tag
- if(key) {
- FreeImage_SetMetadata(s.getFreeImageModel(md_model), dib, key, tag);
- }
- }
-
-
- // free the temporary buffer
- free(exif_value);
-
-}
-
-/**
- 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
-*/
-static BOOL
-jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsigned int length, BOOL msb_order) {
- WORD de, nde;
-
- std::stack<WORD> destack; // directory entries stack
- std::stack<const BYTE*> ifdstack; // IFD stack
- std::stack<TagLib::MDMODEL> modelstack; // metadata model stack
-
- // Keep a list of already visited IFD to avoid stack overflows
- // when recursive/cyclic directory structures exist.
- // This kind of recursive Exif file was encountered with Kodak images coming from
- // KODAK PROFESSIONAL DCS Photo Desk JPEG Export v3.2 W
- std::map<DWORD, int> visitedIFD;
-
- /*
- "An Image File Directory (IFD) consists of a 2-byte count of the number of directory
- entries (i.e. the number of fields), followed by a sequence of 12-byte field
- entries, followed by a 4-byte offset of the next IFD (or 0 if none)."
- The "next IFD" (1st IFD) is the thumbnail.
- */
- #define DIR_ENTRY_ADDR(_start, _entry) (_start + 2 + (12 * _entry))
-
- // set the metadata model to Exif
-
- TagLib::MDMODEL md_model = TagLib::EXIF_MAIN;
-
- // set the pointer to the first IFD (0th IFD) and follow it were it leads.
-
- const BYTE *ifd0th = (BYTE*)tiffp + offset;
-
- const BYTE *ifdp = ifd0th;
-
- de = 0;
-
- do {
- // if there is anything on the stack then pop it off
- if(!destack.empty()) {
- ifdp = ifdstack.top(); ifdstack.pop();
- de = destack.top(); destack.pop();
- md_model = modelstack.top(); modelstack.pop();
- }
-
- // remember that we've visited this directory and entry so that we don't visit it again later
- DWORD visited = (DWORD)( (((size_t)ifdp & 0xFFFF) << 16) | (size_t)de );
- if(visitedIFD.find(visited) != visitedIFD.end()) {
- continue;
- } else {
- visitedIFD[visited] = 1; // processed
- }
-
- // determine how many entries there are in the current IFD
- nde = ReadUint16(msb_order, ifdp);
-
- for(; de < nde; de++) {
- char *pde = NULL; // pointer to the directory entry
- char *pval = NULL; // pointer to the tag value
-
- // create a tag
- FITAG *tag = FreeImage_CreateTag();
- if(!tag) return FALSE;
-
- // point to the directory entry
- pde = (char*) DIR_ENTRY_ADDR(ifdp, de);
-
- // get the tag ID
- FreeImage_SetTagID(tag, ReadUint16(msb_order, pde));
- // get the tag type
- WORD tag_type = (WORD)ReadUint16(msb_order, pde + 2);
- if((tag_type - 1) >= EXIF_NUM_FORMATS) {
- // a problem occured : delete the tag (not free'd after)
- FreeImage_DeleteTag(tag);
- // break out of the for loop
- break;
- }
- FreeImage_SetTagType(tag, (FREE_IMAGE_MDTYPE)tag_type);
-
- // get number of components
- FreeImage_SetTagCount(tag, ReadUint32(msb_order, pde + 4));
- // check that tag length (size of the tag value in bytes) will fit in a DWORD
- int tag_data_width = FreeImage_TagDataWidth(FreeImage_GetTagType(tag));
- if (tag_data_width != 0 && FreeImage_GetTagCount(tag) > ~(DWORD)0 / tag_data_width) {
- FreeImage_DeleteTag(tag);
- // jump to next entry
- continue;
- }
- FreeImage_SetTagLength(tag, FreeImage_GetTagCount(tag) * tag_data_width);
-
- if(FreeImage_GetTagLength(tag) <= 4) {
- // 4 bytes or less and value is in the dir entry itself
- pval = pde + 8;
- } else {
- // if its bigger than 4 bytes, the directory entry contains an offset
- // first check if offset exceeds buffer, at this stage FreeImage_GetTagLength may return invalid data
- DWORD offset_value = ReadUint32(msb_order, pde + 8);
- if(offset_value > length) {
- // a problem occured : delete the tag (not free'd after)
- FreeImage_DeleteTag(tag);
- // jump to next entry
- continue;
- }
- // now check that length does not exceed the buffer size
- if(FreeImage_GetTagLength(tag) > length - offset_value){
- // a problem occured : delete the tag (not free'd after)
- FreeImage_DeleteTag(tag);
- // jump to next entry
- continue;
- }
- pval = (char*)(tiffp + offset_value);
- }
-
- // check for a IFD offset
- BOOL isIFDOffset = FALSE;
- switch(FreeImage_GetTagID(tag)) {
- case TAG_EXIF_OFFSET:
- case TAG_GPS_OFFSET:
- case TAG_INTEROP_OFFSET:
- case TAG_MAKER_NOTE:
- isIFDOffset = TRUE;
- break;
- }
- if(isIFDOffset) {
- DWORD sub_offset = 0;
- TagLib::MDMODEL next_mdmodel = md_model;
- const BYTE *next_ifd = ifdp;
-
- // get offset and metadata model
- if (FreeImage_GetTagID(tag) == TAG_MAKER_NOTE) {
- processMakerNote(dib, pval, msb_order, &sub_offset, &next_mdmodel);
- next_ifd = (BYTE*)pval + sub_offset;
- } else {
- processIFDOffset(tag, pval, msb_order, &sub_offset, &next_mdmodel);
- next_ifd = (BYTE*)tiffp + sub_offset;
- }
-
- if((sub_offset < (DWORD) length) && (next_mdmodel != TagLib::UNKNOWN)) {
- // push our current directory state onto the stack
- ifdstack.push(ifdp);
- // bump to the next entry
- de++;
- destack.push(de);
-
- // push our current metadata model
- modelstack.push(md_model);
-
- // push new state onto of stack to cause a jump
- ifdstack.push(next_ifd);
- destack.push(0);
-
- // select a new metadata model
- modelstack.push(next_mdmodel);
-
- // delete the tag as it won't be stored nor deleted in the for() loop
- FreeImage_DeleteTag(tag);
-
- break; // break out of the for loop
- }
- else {
- // unsupported camera model, canon maker tag or something unknown
- // process as a standard tag
- processExifTag(dib, tag, pval, msb_order, md_model);
- }
-
- } else {
- // process as a standard tag
- processExifTag(dib, tag, pval, msb_order, md_model);
- }
-
- // delete the tag
- FreeImage_DeleteTag(tag);
-
- } // for(nde)
-
- // additional thumbnail data is skipped
-
- } while (!destack.empty());
-
- //
- // --- handle thumbnail data ---
- //
-
- const WORD entriesCount0th = ReadUint16(msb_order, ifd0th);
-
- DWORD next_offset = ReadUint32(msb_order, DIR_ENTRY_ADDR(ifd0th, entriesCount0th));
- if((next_offset == 0) || (next_offset >= length)) {
- return TRUE; //< no thumbnail
- }
-
- const BYTE* const ifd1st = (BYTE*)tiffp + next_offset;
- const WORD entriesCount1st = ReadUint16(msb_order, ifd1st);
-
- unsigned thCompression = 0;
- unsigned thOffset = 0;
- unsigned thSize = 0;
-
- for(int e = 0; e < entriesCount1st; e++) {
-
- // point to the directory entry
- const BYTE* base = DIR_ENTRY_ADDR(ifd1st, e);
-
- // get the tag ID
- WORD tag = ReadUint16(msb_order, base);
- // get the tag type
- WORD type = ReadUint16(msb_order, base + sizeof(WORD));
- // get number of components
- DWORD count = ReadUint32(msb_order, base + sizeof(WORD) + sizeof(WORD));
- // get the tag value
- DWORD offset = ReadUint32(msb_order, base + sizeof(WORD) + sizeof(WORD) + sizeof(DWORD));
-
- switch(tag) {
- case TAG_COMPRESSION:
- // Tiff Compression Tag (should be COMPRESSION_OJPEG (6), but is not always respected)
- thCompression = offset;
- break;
- case TAG_JPEG_INTERCHANGE_FORMAT:
- // Tiff JPEGInterchangeFormat Tag
- thOffset = offset;
- break;
- case TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
- // Tiff JPEGInterchangeFormatLength Tag
- thSize = offset;
- break;
- // ### X and Y Resolution ignored, orientation ignored
- case TAG_X_RESOLUTION: // XResolution
- case TAG_Y_RESOLUTION: // YResolution
- case TAG_RESOLUTION_UNIT: // ResolutionUnit
- case TAG_ORIENTATION: // Orientation
- break;
- default:
- break;
- }
- }
-
- if(/*thCompression != 6 ||*/ thOffset == 0 || thSize == 0) {
- return TRUE;
- }
-
- if(thOffset + thSize > length) {
- return TRUE;
- }
-
- // load the thumbnail
-
- const BYTE *thLocation = tiffp + thOffset;
-
- FIMEMORY* hmem = FreeImage_OpenMemory(const_cast<BYTE*>(thLocation), thSize);
- FIBITMAP* thumbnail = FreeImage_LoadFromMemory(FIF_JPEG, hmem);
- FreeImage_CloseMemory(hmem);
-
- // store the thumbnail
- FreeImage_SetThumbnail(dib, thumbnail);
- // then delete it
- FreeImage_Unload(thumbnail);
-
- return TRUE;
-}
-
-/**
- Read and decode 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(FIBITMAP *dib, const BYTE *dataptr, unsigned int 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
- BYTE msb_first[4] = { 0x4D, 0x4D, 0x00, 0x2A }; // Motorola order
-
- unsigned int length = datalen;
- BYTE *profile = (BYTE*)dataptr;
-
- // verify the identifying string
-
- if(memcmp(exif_signature, profile, sizeof(exif_signature)) == 0) {
- // Exif profile - TIFF header with 2 IFDs. 0th - the image attributes, 1st - may be used for thumbnail
-
- profile += sizeof(exif_signature);
- length -= sizeof(exif_signature);
-
- // read the TIFF header (8 bytes)
-
- // check the endianess order
-
- BOOL bMotorolaOrder = TRUE;
-
- if(memcmp(profile, lsb_first, sizeof(lsb_first)) == 0) {
- // Exif section in Intel order
- bMotorolaOrder = FALSE;
- } else {
- if(memcmp(profile, msb_first, sizeof(msb_first)) == 0) {
- // Exif section in Motorola order
- bMotorolaOrder = TRUE;
- } else {
- // Invalid Exif alignment marker
- return FALSE;
- }
- }
-
- // this is the offset to the first IFD (Image File Directory)
- unsigned long first_offset = ReadUint32(bMotorolaOrder, profile + 4);
-
- /*
- Note: as FreeImage 3.14.0, this test is no longer needed for images with similar suspicious offset
- => tested with Pentax Optio 230, FujiFilm SP-2500 and Canon EOS 300D
- if (first_offset < 8 || first_offset > 16) {
- // This is usually set to 8
- // but PENTAX Optio 230 has it set differently, and uses it as offset.
- FreeImage_OutputMessageProc(FIF_JPEG, "Exif: Suspicious offset of first IFD value");
- return FALSE;
- }
- */
-
- // process Exif directories
- return jpeg_read_exif_dir(dib, profile, first_offset, length, bMotorolaOrder);
- }
-
- return FALSE;
-}
-
-
+// ==========================================================
+// Metadata functions implementation
+// Exif metadata model
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Mihail Naydenov (mnaydenov@users.sourceforge.net)
+//
+// Based on the following implementations:
+// - metadata-extractor : http://www.drewnoakes.com/code/exif/
+// - jhead : http://www.sentex.net/~mwandel/jhead/
+// - ImageMagick : http://www.imagemagick.org/
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageTag.h"
+
+// ==========================================================
+// Exif JPEG routines
+// ==========================================================
+
+#define EXIF_NUM_FORMATS 12
+
+#define TAG_EXIF_OFFSET 0x8769 // Exif IFD Pointer
+#define TAG_GPS_OFFSET 0x8825 // GPS Info IFD Pointer
+#define TAG_INTEROP_OFFSET 0xA005 // Interoperability IFD Pointer
+#define TAG_MAKER_NOTE 0x927C // Maker note
+
+// CANON cameras have some funny bespoke fields that need further processing...
+#define TAG_CANON_CAMERA_STATE_0x01 0x0001 // tags under tag 0x001 (CameraSettings)
+#define TAG_CANON_CAMERA_STATE_0x02 0x0002 // tags under tag 0x002 (FocalLength)
+#define TAG_CANON_CAMERA_STATE_0x04 0x0004 // tags under tag 0x004 (ShotInfo)
+#define TAG_CANON_CAMERA_STATE_0x12 0x0012 // tags under tag 0x012 (AFInfo)
+#define TAG_CANON_CAMERA_STATE_0xA0 0x00A0 // tags under tag 0x0A0 (ProcessingInfo)
+#define TAG_CANON_CAMERA_STATE_0xE0 0x00E0 // tags under tag 0x0E0 (SensorInfo)
+
+
+// =====================================================================
+// Reimplementation of strnicmp (it is not supported on some systems)
+// =====================================================================
+
+/**
+Compare characters of two strings without regard to case.
+@param s1 Null-terminated string to compare.
+@param s2 Null-terminated string to compare.
+@param len Number of characters to compare
+@return Returns 0 if s1 substring identical to s2 substring
+*/
+static int
+FreeImage_strnicmp(const char *s1, const char *s2, size_t len) {
+ unsigned char c1, c2;
+
+ if(!s1 || !s2) return -1;
+
+ c1 = 0; c2 = 0;
+ if(len) {
+ do {
+ c1 = *s1; c2 = *s2;
+ s1++; s2++;
+ if (!c1)
+ break;
+ if (!c2)
+ break;
+ if (c1 == c2)
+ continue;
+ c1 = (BYTE)tolower(c1);
+ c2 = (BYTE)tolower(c2);
+ if (c1 != c2)
+ break;
+ } while (--len);
+ }
+ return (int)c1 - (int)c2;
+}
+
+
+// ----------------------------------------------------------
+// Little Endian / Big Endian io routines
+// ----------------------------------------------------------
+
+static short
+ReadInt16(BOOL msb_order, const void *buffer) {
+ short value;
+
+ if(msb_order) {
+ value = (short)((((BYTE*) buffer)[0] << 8) | ((BYTE*) buffer)[1]);
+ return value;
+ }
+ value = (short)((((BYTE*) buffer)[1] << 8) | ((BYTE*) buffer)[0]);
+ return value;
+}
+
+static LONG
+ReadInt32(BOOL msb_order, const void *buffer) {
+ LONG value;
+
+ if(msb_order) {
+ value = (LONG)((((BYTE*) buffer)[0] << 24) | (((BYTE*) buffer)[1] << 16) | (((BYTE*) buffer)[2] << 8) | (((BYTE*) buffer)[3]));
+ return value;
+ }
+ value = (LONG)((((BYTE*) buffer)[3] << 24) | (((BYTE*) buffer)[2] << 16) | (((BYTE*) buffer)[1] << 8 ) | (((BYTE*) buffer)[0]));
+ return value;
+}
+
+static unsigned short
+ReadUint16(BOOL msb_order, const void *buffer) {
+ unsigned short value;
+
+ if(msb_order) {
+ value = (unsigned short) ((((BYTE*) buffer)[0] << 8) | ((BYTE*) buffer)[1]);
+ return value;
+ }
+ value = (unsigned short) ((((BYTE*) buffer)[1] << 8) | ((BYTE*) buffer)[0]);
+ return value;
+}
+
+static DWORD
+ReadUint32(BOOL msb_order, const void *buffer) {
+ return ((DWORD) ReadInt32(msb_order, buffer) & 0xFFFFFFFF);
+}
+
+// ----------------------------------------------------------
+// Exif JPEG markers routines
+// ----------------------------------------------------------
+
+/**
+Process a IFD offset
+Returns the offset and the metadata model for this tag
+*/
+static void
+processIFDOffset(FITAG *tag, char *pval, BOOL msb_order, DWORD *subdirOffset, TagLib::MDMODEL *md_model) {
+ // get the IFD offset
+ *subdirOffset = (DWORD) ReadUint32(msb_order, pval);
+
+ // select a tag info table
+ switch(FreeImage_GetTagID(tag)) {
+ case TAG_EXIF_OFFSET:
+ *md_model = TagLib::EXIF_EXIF;
+ break;
+ case TAG_GPS_OFFSET:
+ *md_model = TagLib::EXIF_GPS;
+ break;
+ case TAG_INTEROP_OFFSET:
+ *md_model = TagLib::EXIF_INTEROP;
+ break;
+ }
+
+}
+
+/**
+Process a maker note IFD offset
+Returns the offset and the metadata model for this tag
+*/
+static void
+processMakerNote(FIBITMAP *dib, char *pval, BOOL msb_order, DWORD *subdirOffset, TagLib::MDMODEL *md_model) {
+ FITAG *tagMake = NULL;
+
+ *subdirOffset = 0;
+ *md_model = TagLib::UNKNOWN;
+
+ // Determine the camera model and makernote format
+ // WARNING: note that Maker may be NULL sometimes so check its value before using it
+ // (NULL pointer checking is done by FreeImage_strnicmp)
+ FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "Make", &tagMake);
+ const char *Maker = (char*)FreeImage_GetTagValue(tagMake);
+
+ if((memcmp("OLYMP\x00\x01", pval, 7) == 0) || (memcmp("OLYMP\x00\x02", pval, 7) == 0) || (memcmp("EPSON", pval, 5) == 0) || (memcmp("AGFA", pval, 4) == 0)) {
+ // Olympus Type 1 Makernote
+ // Epson and Agfa use Olympus maker note standard,
+ // see: http://www.ozhiker.com/electronics/pjmt/jpeg_info/
+ *md_model = TagLib::EXIF_MAKERNOTE_OLYMPUSTYPE1;
+ *subdirOffset = 8;
+ }
+ else if(memcmp("OLYMPUS\x00\x49\x49\x03\x00", pval, 12) == 0) {
+ // Olympus Type 2 Makernote
+ // !!! NOT YET SUPPORTED !!!
+ *subdirOffset = 0;
+ *md_model = TagLib::UNKNOWN;
+ }
+ else if(memcmp("Nikon", pval, 5) == 0) {
+ /* There are two scenarios here:
+ * Type 1:
+ * :0000: 4E 69 6B 6F 6E 00 01 00-05 00 02 00 02 00 06 00 Nikon...........
+ * :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................
+ * Type 3:
+ * :0000: 4E 69 6B 6F 6E 00 02 00-00 00 4D 4D 00 2A 00 00 Nikon....MM.*...
+ * :0010: 00 08 00 1E 00 01 00 07-00 00 00 04 30 32 30 30 ............0200
+ */
+ if (pval[6] == 1) {
+ // Nikon type 1 Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_NIKONTYPE1;
+ *subdirOffset = 8;
+ } else if (pval[6] == 2) {
+ // Nikon type 3 Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_NIKONTYPE3;
+ *subdirOffset = 18;
+ } else {
+ // Unsupported makernote data ignored
+ *subdirOffset = 0;
+ *md_model = TagLib::UNKNOWN;
+ }
+ } else if(Maker && (FreeImage_strnicmp("NIKON", Maker, 5) == 0)) {
+ // Nikon type 2 Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_NIKONTYPE2;
+ *subdirOffset = 0;
+ } else if(Maker && (FreeImage_strnicmp("Canon", Maker, 5) == 0)) {
+ // Canon Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_CANON;
+ *subdirOffset = 0;
+ } else if(Maker && (FreeImage_strnicmp("Casio", Maker, 5) == 0)) {
+ // Casio Makernote
+ if(memcmp("QVC\x00\x00\x00", pval, 6) == 0) {
+ // Casio Type 2 Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_CASIOTYPE2;
+ *subdirOffset = 6;
+ } else {
+ // Casio Type 1 Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_CASIOTYPE1;
+ *subdirOffset = 0;
+ }
+ } else if ((memcmp("FUJIFILM", pval, 8) == 0) || (Maker && (FreeImage_strnicmp("Fujifilm", Maker, 8) == 0))) {
+ // Fujifile Makernote
+ // Fujifilm's Makernote always use Intel order altough the Exif section maybe in Intel order or in Motorola order.
+ // If msb_order == TRUE, the Makernote won't be read:
+ // the value of ifdStart will be 0x0c000000 instead of 0x0000000c and the MakerNote section will be discarded later
+ // in jpeg_read_exif_dir because the IFD is too high
+ *md_model = TagLib::EXIF_MAKERNOTE_FUJIFILM;
+ DWORD ifdStart = (DWORD) ReadUint32(msb_order, pval + 8);
+ *subdirOffset = ifdStart;
+ }
+ else if(memcmp("KYOCERA\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x00\x00\x00", pval, 22) == 0) {
+ *md_model = TagLib::EXIF_MAKERNOTE_KYOCERA;
+ *subdirOffset = 22;
+ }
+ else if(Maker && (FreeImage_strnicmp("Minolta", Maker, 7) == 0)) {
+ // Minolta maker note
+ *md_model = TagLib::EXIF_MAKERNOTE_MINOLTA;
+ *subdirOffset = 0;
+ }
+ else if(memcmp("Panasonic\x00\x00\x00", pval, 12) == 0) {
+ // Panasonic maker note
+ *md_model = TagLib::EXIF_MAKERNOTE_PANASONIC;
+ *subdirOffset = 12;
+ }
+ else if(Maker && (FreeImage_strnicmp("LEICA", Maker, 5) == 0)) {
+ // Leica maker note
+ if(memcmp("LEICA\x00\x00\x00", pval, 8) == 0) {
+ // not yet supported makernote data ignored
+ *subdirOffset = 0;
+ *md_model = TagLib::UNKNOWN;
+ }
+ }
+ else if(Maker && ((FreeImage_strnicmp("Pentax", Maker, 6) == 0) || (FreeImage_strnicmp("Asahi", Maker, 5) == 0))) {
+ // Pentax maker note
+ if(memcmp("AOC\x00", pval, 4) == 0) {
+ // Type 2 Pentax Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_PENTAX;
+ *subdirOffset = 6;
+ } else {
+ // Type 1 Pentax Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_ASAHI;
+ *subdirOffset = 0;
+ }
+ }
+ else if((memcmp("SONY CAM\x20\x00\x00\x00", pval, 12) == 0) || (memcmp("SONY DSC\x20\x00\x00\x00", pval, 12) == 0)) {
+ *md_model = TagLib::EXIF_MAKERNOTE_SONY;
+ *subdirOffset = 12;
+ }
+ else if((memcmp("SIGMA\x00\x00\x00", pval, 8) == 0) || (memcmp("FOVEON\x00\x00", pval, 8) == 0)) {
+ FITAG *tagModel = NULL;
+ FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "Model", &tagModel);
+ const char *Model = (char*)FreeImage_GetTagValue(tagModel);
+ if(Model && (memcmp("SIGMA SD1\x00", Model, 10) == 0)) {
+ // Sigma SD1 maker note
+ *subdirOffset = 10;
+ *md_model = TagLib::EXIF_MAKERNOTE_SIGMA_SD1;
+ } else {
+ // Sigma / Foveon makernote
+ *subdirOffset = 10;
+ *md_model = TagLib::EXIF_MAKERNOTE_SIGMA_FOVEON;
+ }
+ }
+}
+
+/**
+Process a Canon maker note tag.
+A single Canon tag may contain many other tags within.
+*/
+static BOOL
+processCanonMakerNoteTag(FIBITMAP *dib, FITAG *tag) {
+ char defaultKey[16];
+ DWORD startIndex = 0;
+ TagLib& s = TagLib::instance();
+
+ WORD tag_id = FreeImage_GetTagID(tag);
+
+ int subTagTypeBase = 0;
+
+ switch(tag_id) {
+ case TAG_CANON_CAMERA_STATE_0x01:
+ subTagTypeBase = 0xC100;
+ startIndex = 1;
+ break;
+ case TAG_CANON_CAMERA_STATE_0x02:
+ subTagTypeBase = 0xC200;
+ startIndex = 0;
+ break;
+ case TAG_CANON_CAMERA_STATE_0x04:
+ subTagTypeBase = 0xC400;
+ startIndex = 1;
+ break;
+ case TAG_CANON_CAMERA_STATE_0x12:
+ subTagTypeBase = 0x1200;
+ startIndex = 0;
+ break;
+ case TAG_CANON_CAMERA_STATE_0xA0:
+ subTagTypeBase = 0xCA00;
+ startIndex = 1;
+ break;
+ case TAG_CANON_CAMERA_STATE_0xE0:
+ subTagTypeBase = 0xCE00;
+ startIndex = 1;
+ break;
+
+ default:
+ {
+ // process as a normal tag
+
+ // get the tag key and description
+ const char *key = s.getTagFieldName(TagLib::EXIF_MAKERNOTE_CANON, tag_id, defaultKey);
+ FreeImage_SetTagKey(tag, key);
+ const char *description = s.getTagDescription(TagLib::EXIF_MAKERNOTE_CANON, tag_id);
+ FreeImage_SetTagDescription(tag, description);
+
+ // store the tag
+ if(key) {
+ FreeImage_SetMetadata(FIMD_EXIF_MAKERNOTE, dib, key, tag);
+ }
+
+ return TRUE;
+ }
+ break;
+
+ }
+
+ WORD *pvalue = (WORD*)FreeImage_GetTagValue(tag);
+
+ // create a tag
+ FITAG *canonTag = FreeImage_CreateTag();
+ if(!canonTag) return FALSE;
+
+ // we intentionally skip the first array member (if needed)
+ for (DWORD i = startIndex; i < FreeImage_GetTagCount(tag); i++) {
+
+ tag_id = (WORD)(subTagTypeBase + i);
+
+ FreeImage_SetTagID(canonTag, tag_id);
+ FreeImage_SetTagType(canonTag, FIDT_SHORT);
+ FreeImage_SetTagCount(canonTag, 1);
+ FreeImage_SetTagLength(canonTag, 2);
+ FreeImage_SetTagValue(canonTag, &pvalue[i]);
+
+ // get the tag key and description
+ const char *key = s.getTagFieldName(TagLib::EXIF_MAKERNOTE_CANON, tag_id, defaultKey);
+ FreeImage_SetTagKey(canonTag, key);
+ const char *description = s.getTagDescription(TagLib::EXIF_MAKERNOTE_CANON, tag_id);
+ FreeImage_SetTagDescription(canonTag, description);
+
+ // store the tag
+ if(key) {
+ FreeImage_SetMetadata(FIMD_EXIF_MAKERNOTE, dib, key, canonTag);
+ }
+ }
+
+ // delete the tag
+ FreeImage_DeleteTag(canonTag);
+
+ return TRUE;
+}
+
+/**
+Process a standard Exif tag
+*/
+static void
+processExifTag(FIBITMAP *dib, FITAG *tag, char *pval, BOOL msb_order, TagLib::MDMODEL md_model) {
+ char defaultKey[16];
+ int n;
+ DWORD i;
+
+ // allocate a buffer to store the tag value
+ BYTE *exif_value = (BYTE*)malloc(FreeImage_GetTagLength(tag) * sizeof(BYTE));
+ if(NULL == exif_value) {
+ // out of memory ...
+ return;
+ }
+ memset(exif_value, 0, FreeImage_GetTagLength(tag) * sizeof(BYTE));
+
+ // get the tag value
+ switch(FreeImage_GetTagType(tag)) {
+
+ case FIDT_SHORT:
+ {
+ WORD *value = (WORD*)&exif_value[0];
+ for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
+ value[i] = ReadUint16(msb_order, pval + i * sizeof(WORD));
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_SSHORT:
+ {
+ short *value = (short*)&exif_value[0];
+ for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
+ value[i] = ReadInt16(msb_order, pval + i * sizeof(short));
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_LONG:
+ {
+ DWORD *value = (DWORD*)&exif_value[0];
+ for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
+ value[i] = ReadUint32(msb_order, pval + i * sizeof(DWORD));
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_SLONG:
+ {
+ LONG *value = (LONG*)&exif_value[0];
+ for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
+ value[i] = ReadInt32(msb_order, pval + i * sizeof(LONG));
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_RATIONAL:
+ {
+ n = sizeof(DWORD);
+
+ DWORD *value = (DWORD*)&exif_value[0];
+ for(i = 0; i < 2 * FreeImage_GetTagCount(tag); i++) {
+ // read a sequence of (numerator, denominator)
+ value[i] = ReadUint32(msb_order, n*i + (char*)pval);
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_SRATIONAL:
+ {
+ n = sizeof(LONG);
+
+ LONG *value = (LONG*)&exif_value[0];
+ for(i = 0; i < 2 * FreeImage_GetTagCount(tag); i++) {
+ // read a sequence of (numerator, denominator)
+ value[i] = ReadInt32(msb_order, n*i + (char*)pval);
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_BYTE:
+ case FIDT_ASCII:
+ case FIDT_SBYTE:
+ case FIDT_UNDEFINED:
+ case FIDT_FLOAT:
+ case FIDT_DOUBLE:
+ default:
+ FreeImage_SetTagValue(tag, pval);
+ break;
+ }
+
+ if(md_model == TagLib::EXIF_MAKERNOTE_CANON) {
+ // A single Canon tag can have multiple values within
+ processCanonMakerNoteTag(dib, tag);
+ }
+ else {
+ TagLib& s = TagLib::instance();
+
+ WORD tag_id = FreeImage_GetTagID(tag);
+
+ // get the tag key and description
+ const char *key = s.getTagFieldName(md_model, tag_id, defaultKey);
+ FreeImage_SetTagKey(tag, key);
+ const char *description = s.getTagDescription(md_model, tag_id);
+ FreeImage_SetTagDescription(tag, description);
+
+ // store the tag
+ if(key) {
+ FreeImage_SetMetadata(s.getFreeImageModel(md_model), dib, key, tag);
+ }
+ }
+
+
+ // free the temporary buffer
+ free(exif_value);
+
+}
+
+/**
+ 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
+*/
+static BOOL
+jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsigned int length, BOOL msb_order) {
+ WORD de, nde;
+
+ std::stack<WORD> destack; // directory entries stack
+ std::stack<const BYTE*> ifdstack; // IFD stack
+ std::stack<TagLib::MDMODEL> modelstack; // metadata model stack
+
+ // Keep a list of already visited IFD to avoid stack overflows
+ // when recursive/cyclic directory structures exist.
+ // This kind of recursive Exif file was encountered with Kodak images coming from
+ // KODAK PROFESSIONAL DCS Photo Desk JPEG Export v3.2 W
+ std::map<DWORD, int> visitedIFD;
+
+ /*
+ "An Image File Directory (IFD) consists of a 2-byte count of the number of directory
+ entries (i.e. the number of fields), followed by a sequence of 12-byte field
+ entries, followed by a 4-byte offset of the next IFD (or 0 if none)."
+ The "next IFD" (1st IFD) is the thumbnail.
+ */
+ #define DIR_ENTRY_ADDR(_start, _entry) (_start + 2 + (12 * _entry))
+
+ // set the metadata model to Exif
+
+ TagLib::MDMODEL md_model = TagLib::EXIF_MAIN;
+
+ // set the pointer to the first IFD (0th IFD) and follow it were it leads.
+
+ const BYTE *ifd0th = (BYTE*)tiffp + offset;
+
+ const BYTE *ifdp = ifd0th;
+
+ de = 0;
+
+ do {
+ // if there is anything on the stack then pop it off
+ if(!destack.empty()) {
+ ifdp = ifdstack.top(); ifdstack.pop();
+ de = destack.top(); destack.pop();
+ md_model = modelstack.top(); modelstack.pop();
+ }
+
+ // remember that we've visited this directory and entry so that we don't visit it again later
+ DWORD visited = (DWORD)( (((size_t)ifdp & 0xFFFF) << 16) | (size_t)de );
+ if(visitedIFD.find(visited) != visitedIFD.end()) {
+ continue;
+ } else {
+ visitedIFD[visited] = 1; // processed
+ }
+
+ // determine how many entries there are in the current IFD
+ nde = ReadUint16(msb_order, ifdp);
+
+ for(; de < nde; de++) {
+ char *pde = NULL; // pointer to the directory entry
+ char *pval = NULL; // pointer to the tag value
+
+ // create a tag
+ FITAG *tag = FreeImage_CreateTag();
+ if(!tag) return FALSE;
+
+ // point to the directory entry
+ pde = (char*) DIR_ENTRY_ADDR(ifdp, de);
+
+ // get the tag ID
+ FreeImage_SetTagID(tag, ReadUint16(msb_order, pde));
+ // get the tag type
+ WORD tag_type = (WORD)ReadUint16(msb_order, pde + 2);
+ if((tag_type - 1) >= EXIF_NUM_FORMATS) {
+ // a problem occured : delete the tag (not free'd after)
+ FreeImage_DeleteTag(tag);
+ // break out of the for loop
+ break;
+ }
+ FreeImage_SetTagType(tag, (FREE_IMAGE_MDTYPE)tag_type);
+
+ // get number of components
+ FreeImage_SetTagCount(tag, ReadUint32(msb_order, pde + 4));
+ // check that tag length (size of the tag value in bytes) will fit in a DWORD
+ unsigned tag_data_width = FreeImage_TagDataWidth(FreeImage_GetTagType(tag));
+ if (tag_data_width != 0 && FreeImage_GetTagCount(tag) > ~(DWORD)0 / tag_data_width) {
+ FreeImage_DeleteTag(tag);
+ // jump to next entry
+ continue;
+ }
+ FreeImage_SetTagLength(tag, FreeImage_GetTagCount(tag) * tag_data_width);
+
+ if(FreeImage_GetTagLength(tag) <= 4) {
+ // 4 bytes or less and value is in the dir entry itself
+ pval = pde + 8;
+ } else {
+ // if its bigger than 4 bytes, the directory entry contains an offset
+ // first check if offset exceeds buffer, at this stage FreeImage_GetTagLength may return invalid data
+ DWORD offset_value = ReadUint32(msb_order, pde + 8);
+ if(offset_value > length) {
+ // a problem occured : delete the tag (not free'd after)
+ FreeImage_DeleteTag(tag);
+ // jump to next entry
+ continue;
+ }
+ // now check that length does not exceed the buffer size
+ if(FreeImage_GetTagLength(tag) > length - offset_value){
+ // a problem occured : delete the tag (not free'd after)
+ FreeImage_DeleteTag(tag);
+ // jump to next entry
+ continue;
+ }
+ pval = (char*)(tiffp + offset_value);
+ }
+
+ // check for a IFD offset
+ BOOL isIFDOffset = FALSE;
+ switch(FreeImage_GetTagID(tag)) {
+ case TAG_EXIF_OFFSET:
+ case TAG_GPS_OFFSET:
+ case TAG_INTEROP_OFFSET:
+ case TAG_MAKER_NOTE:
+ isIFDOffset = TRUE;
+ break;
+ }
+ if(isIFDOffset) {
+ DWORD sub_offset = 0;
+ TagLib::MDMODEL next_mdmodel = md_model;
+ const BYTE *next_ifd = ifdp;
+
+ // get offset and metadata model
+ if (FreeImage_GetTagID(tag) == TAG_MAKER_NOTE) {
+ processMakerNote(dib, pval, msb_order, &sub_offset, &next_mdmodel);
+ next_ifd = (BYTE*)pval + sub_offset;
+ } else {
+ processIFDOffset(tag, pval, msb_order, &sub_offset, &next_mdmodel);
+ next_ifd = (BYTE*)tiffp + sub_offset;
+ }
+
+ if((sub_offset < (DWORD) length) && (next_mdmodel != TagLib::UNKNOWN)) {
+ // push our current directory state onto the stack
+ ifdstack.push(ifdp);
+ // bump to the next entry
+ de++;
+ destack.push(de);
+
+ // push our current metadata model
+ modelstack.push(md_model);
+
+ // push new state onto of stack to cause a jump
+ ifdstack.push(next_ifd);
+ destack.push(0);
+
+ // select a new metadata model
+ modelstack.push(next_mdmodel);
+
+ // delete the tag as it won't be stored nor deleted in the for() loop
+ FreeImage_DeleteTag(tag);
+
+ break; // break out of the for loop
+ }
+ else {
+ // unsupported camera model, canon maker tag or something unknown
+ // process as a standard tag
+ processExifTag(dib, tag, pval, msb_order, md_model);
+ }
+
+ } else {
+ // process as a standard tag
+ processExifTag(dib, tag, pval, msb_order, md_model);
+ }
+
+ // delete the tag
+ FreeImage_DeleteTag(tag);
+
+ } // for(nde)
+
+ // additional thumbnail data is skipped
+
+ } while (!destack.empty());
+
+ //
+ // --- handle thumbnail data ---
+ //
+
+ const WORD entriesCount0th = ReadUint16(msb_order, ifd0th);
+
+ DWORD next_offset = ReadUint32(msb_order, DIR_ENTRY_ADDR(ifd0th, entriesCount0th));
+ if((next_offset == 0) || (next_offset >= length)) {
+ return TRUE; //< no thumbnail
+ }
+
+ const BYTE* const ifd1st = (BYTE*)tiffp + next_offset;
+ const WORD entriesCount1st = ReadUint16(msb_order, ifd1st);
+
+ unsigned thCompression = 0;
+ unsigned thOffset = 0;
+ unsigned thSize = 0;
+
+ for(int e = 0; e < entriesCount1st; e++) {
+
+ // point to the directory entry
+ const BYTE* base = DIR_ENTRY_ADDR(ifd1st, e);
+
+ // check for buffer overflow
+ const size_t remaining = (size_t)base + 12 - (size_t)tiffp;
+ if(remaining >= length) {
+ // bad IFD1 directory, ignore it
+ return FALSE;
+ }
+
+ // get the tag ID
+ WORD tag = ReadUint16(msb_order, base);
+ // get the tag type
+ WORD type = ReadUint16(msb_order, base + sizeof(WORD));
+ // get number of components
+ DWORD count = ReadUint32(msb_order, base + sizeof(WORD) + sizeof(WORD));
+ // get the tag value
+ DWORD offset = ReadUint32(msb_order, base + sizeof(WORD) + sizeof(WORD) + sizeof(DWORD));
+
+ switch(tag) {
+ case TAG_COMPRESSION:
+ // Tiff Compression Tag (should be COMPRESSION_OJPEG (6), but is not always respected)
+ thCompression = offset;
+ break;
+ case TAG_JPEG_INTERCHANGE_FORMAT:
+ // Tiff JPEGInterchangeFormat Tag
+ thOffset = offset;
+ break;
+ case TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
+ // Tiff JPEGInterchangeFormatLength Tag
+ thSize = offset;
+ break;
+ // ### X and Y Resolution ignored, orientation ignored
+ case TAG_X_RESOLUTION: // XResolution
+ case TAG_Y_RESOLUTION: // YResolution
+ case TAG_RESOLUTION_UNIT: // ResolutionUnit
+ case TAG_ORIENTATION: // Orientation
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(/*thCompression != 6 ||*/ thOffset == 0 || thSize == 0) {
+ return TRUE;
+ }
+
+ if(thOffset + thSize > length) {
+ return TRUE;
+ }
+
+ // load the thumbnail
+
+ const BYTE *thLocation = tiffp + thOffset;
+
+ FIMEMORY* hmem = FreeImage_OpenMemory(const_cast<BYTE*>(thLocation), thSize);
+ FIBITMAP* thumbnail = FreeImage_LoadFromMemory(FIF_JPEG, hmem);
+ FreeImage_CloseMemory(hmem);
+
+ // store the thumbnail
+ FreeImage_SetThumbnail(dib, thumbnail);
+ // then delete it
+ FreeImage_Unload(thumbnail);
+
+ return TRUE;
+}
+
+/**
+ Read and decode 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(FIBITMAP *dib, const BYTE *dataptr, unsigned int 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
+ BYTE msb_first[4] = { 0x4D, 0x4D, 0x00, 0x2A }; // Motorola order
+
+ unsigned int length = datalen;
+ BYTE *profile = (BYTE*)dataptr;
+
+ // verify the identifying string
+
+ if(memcmp(exif_signature, profile, sizeof(exif_signature)) == 0) {
+ // Exif profile - TIFF header with 2 IFDs. 0th - the image attributes, 1st - may be used for thumbnail
+
+ profile += sizeof(exif_signature);
+ length -= sizeof(exif_signature);
+
+ // read the TIFF header (8 bytes)
+
+ // check the endianess order
+
+ BOOL bMotorolaOrder = TRUE;
+
+ if(memcmp(profile, lsb_first, sizeof(lsb_first)) == 0) {
+ // Exif section in Intel order
+ bMotorolaOrder = FALSE;
+ } else {
+ if(memcmp(profile, msb_first, sizeof(msb_first)) == 0) {
+ // Exif section in Motorola order
+ bMotorolaOrder = TRUE;
+ } else {
+ // Invalid Exif alignment marker
+ return FALSE;
+ }
+ }
+
+ // this is the offset to the first IFD (Image File Directory)
+ unsigned long first_offset = ReadUint32(bMotorolaOrder, profile + 4);
+ if (first_offset > length) {
+ // bad Exif data
+ return FALSE;
+ }
+
+ /*
+ Note: as FreeImage 3.14.0, this test is no longer needed for images with similar suspicious offset
+ => tested with Pentax Optio 230, FujiFilm SP-2500 and Canon EOS 300D
+ if (first_offset < 8 || first_offset > 16) {
+ // This is usually set to 8
+ // but PENTAX Optio 230 has it set differently, and uses it as offset.
+ FreeImage_OutputMessageProc(FIF_JPEG, "Exif: Suspicious offset of first IFD value");
+ return FALSE;
+ }
+ */
+
+ // process Exif directories
+ return jpeg_read_exif_dir(dib, profile, first_offset, length, bMotorolaOrder);
+ }
+
+ return FALSE;
+}
+
+
diff --git a/plugins/FreeImage/Source/Metadata/FIRational.cpp b/plugins/FreeImage/Source/Metadata/FIRational.cpp
index 969c06489a..d383c8d38f 100644
--- a/plugins/FreeImage/Source/Metadata/FIRational.cpp
+++ b/plugins/FreeImage/Source/Metadata/FIRational.cpp
@@ -1,176 +1,176 @@
-// ==========================================================
-// Helper class for rational numbers
-//
-// Design and implementation by
-// - Hervé Drolon <drolon@infonie.fr>
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#include "FreeImage.h"
-#include "Utilities.h"
-#include "FIRational.h"
-
-/// Initialize and normalize a rational number
-void FIRational::initialize(LONG n, LONG d) {
- if(d) {
- _numerator = n;
- _denominator = d;
- // normalize rational
- normalize();
- } else {
- _numerator = 0;
- _denominator = 0;
- }
-}
-
-/// Default constructor
-FIRational::FIRational() {
- _numerator = 0;
- _denominator = 0;
-}
-
-/// Constructor with longs
-FIRational::FIRational(LONG n, LONG d) {
- initialize(n, d);
-}
-
-/// Constructor with FITAG
-FIRational::FIRational(const FITAG *tag) {
- switch(FreeImage_GetTagType((FITAG*)tag)) {
- case FIDT_RATIONAL: // 64-bit unsigned fraction
- {
- DWORD *pvalue = (DWORD*)FreeImage_GetTagValue((FITAG*)tag);
- initialize((LONG)pvalue[0], (LONG)pvalue[1]);
- break;
- }
-
- case FIDT_SRATIONAL: // 64-bit signed fraction
- {
- LONG *pvalue = (LONG*)FreeImage_GetTagValue((FITAG*)tag);
- initialize((LONG)pvalue[0], (LONG)pvalue[1]);
- break;
- }
- }
-}
-
-FIRational::FIRational(float value) {
- if (value == (float)((LONG)value)) {
- _numerator = (LONG)value;
- _denominator = 1L;
- } else {
- int k, count;
- LONG n[4];
-
- float x = fabs(value);
- int sign = (value > 0) ? 1 : -1;
-
- // make a continued-fraction expansion of x
- count = -1;
- for(k = 0; k < 4; k++) {
- n[k] = (LONG)floor(x);
- count++;
- x -= (float)n[k];
- if(x == 0) break;
- x = 1 / x;
- }
- // compute the rational
- _numerator = 1;
- _denominator = n[count];
-
- for(int i = count - 1; i >= 0; i--) {
- if(n[i] == 0) break;
- LONG _num = (n[i] * _numerator + _denominator);
- LONG _den = _numerator;
- _numerator = _num;
- _denominator = _den;
- }
- _numerator *= sign;
- }
-}
-
-/// Copy constructor
-FIRational::FIRational (const FIRational& r) {
- initialize(r._numerator, r._denominator);
-}
-
-/// Destructor
-FIRational::~FIRational() {
-}
-
-/// Assignement operator
-FIRational& FIRational::operator=(FIRational& r) {
- if(this != &r) {
- initialize(r._numerator, r._denominator);
- }
- return *this;
-}
-
-/// Get the numerator
-LONG FIRational::getNumerator() {
- return _numerator;
-}
-
-/// Get the denominator
-LONG FIRational::getDenominator() {
- return _denominator;
-}
-
-/// Calculate GCD
-LONG FIRational::gcd(LONG a, LONG b) {
- LONG temp;
- while (b) { // While non-zero value
- temp = b; // Save current value
- b = a % b; // Assign remainder of division
- a = temp; // Copy old value
- }
- return a; // Return GCD of numbers
-}
-
-/// Normalize numerator / denominator
-void FIRational::normalize() {
- if (_numerator != 1 && _denominator != 1) { // Is there something to do?
- // Calculate GCD
- LONG common = gcd(_numerator, _denominator);
- if (common != 1) { // If GCD is not one
- _numerator /= common; // Calculate new numerator
- _denominator /= common; // Calculate new denominator
- }
- }
- if(_denominator < 0) { // If sign is in denominator
- _numerator *= -1; // Multiply num and den by -1
- _denominator *= -1; // To keep sign in numerator
- }
-}
-
-/// Checks if this rational number is an Integer, either positive or negative
-BOOL FIRational::isInteger() {
- if(_denominator == 1 || (_denominator != 0 && (_numerator % _denominator == 0)) || (_denominator == 0 && _numerator == 0))
- return TRUE;
- return FALSE;
-}
-
-/// Convert as "numerator/denominator"
-std::string FIRational::toString() {
- std::ostringstream s;
- if(isInteger()) {
- s << intValue();
- } else {
- s << _numerator << "/" << _denominator;
- }
- return s.str();
-}
-
-
+// ==========================================================
+// Helper class for rational numbers
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FIRational.h"
+
+/// Initialize and normalize a rational number
+void FIRational::initialize(LONG n, LONG d) {
+ if(d) {
+ _numerator = n;
+ _denominator = d;
+ // normalize rational
+ normalize();
+ } else {
+ _numerator = 0;
+ _denominator = 0;
+ }
+}
+
+/// Default constructor
+FIRational::FIRational() {
+ _numerator = 0;
+ _denominator = 0;
+}
+
+/// Constructor with longs
+FIRational::FIRational(LONG n, LONG d) {
+ initialize(n, d);
+}
+
+/// Constructor with FITAG
+FIRational::FIRational(const FITAG *tag) {
+ switch(FreeImage_GetTagType((FITAG*)tag)) {
+ case FIDT_RATIONAL: // 64-bit unsigned fraction
+ {
+ DWORD *pvalue = (DWORD*)FreeImage_GetTagValue((FITAG*)tag);
+ initialize((LONG)pvalue[0], (LONG)pvalue[1]);
+ break;
+ }
+
+ case FIDT_SRATIONAL: // 64-bit signed fraction
+ {
+ LONG *pvalue = (LONG*)FreeImage_GetTagValue((FITAG*)tag);
+ initialize((LONG)pvalue[0], (LONG)pvalue[1]);
+ break;
+ }
+ }
+}
+
+FIRational::FIRational(float value) {
+ if (value == (float)((LONG)value)) {
+ _numerator = (LONG)value;
+ _denominator = 1L;
+ } else {
+ int k, count;
+ LONG n[4];
+
+ float x = fabs(value);
+ int sign = (value > 0) ? 1 : -1;
+
+ // make a continued-fraction expansion of x
+ count = -1;
+ for(k = 0; k < 4; k++) {
+ n[k] = (LONG)floor(x);
+ count++;
+ x -= (float)n[k];
+ if(x == 0) break;
+ x = 1 / x;
+ }
+ // compute the rational
+ _numerator = 1;
+ _denominator = n[count];
+
+ for(int i = count - 1; i >= 0; i--) {
+ if(n[i] == 0) break;
+ LONG _num = (n[i] * _numerator + _denominator);
+ LONG _den = _numerator;
+ _numerator = _num;
+ _denominator = _den;
+ }
+ _numerator *= sign;
+ }
+}
+
+/// Copy constructor
+FIRational::FIRational (const FIRational& r) {
+ initialize(r._numerator, r._denominator);
+}
+
+/// Destructor
+FIRational::~FIRational() {
+}
+
+/// Assignement operator
+FIRational& FIRational::operator=(FIRational& r) {
+ if(this != &r) {
+ initialize(r._numerator, r._denominator);
+ }
+ return *this;
+}
+
+/// Get the numerator
+LONG FIRational::getNumerator() {
+ return _numerator;
+}
+
+/// Get the denominator
+LONG FIRational::getDenominator() {
+ return _denominator;
+}
+
+/// Calculate GCD
+LONG FIRational::gcd(LONG a, LONG b) {
+ LONG temp;
+ while (b) { // While non-zero value
+ temp = b; // Save current value
+ b = a % b; // Assign remainder of division
+ a = temp; // Copy old value
+ }
+ return a; // Return GCD of numbers
+}
+
+/// Normalize numerator / denominator
+void FIRational::normalize() {
+ if (_numerator != 1 && _denominator != 1) { // Is there something to do?
+ // Calculate GCD
+ LONG common = gcd(_numerator, _denominator);
+ if (common != 1) { // If GCD is not one
+ _numerator /= common; // Calculate new numerator
+ _denominator /= common; // Calculate new denominator
+ }
+ }
+ if(_denominator < 0) { // If sign is in denominator
+ _numerator *= -1; // Multiply num and den by -1
+ _denominator *= -1; // To keep sign in numerator
+ }
+}
+
+/// Checks if this rational number is an Integer, either positive or negative
+BOOL FIRational::isInteger() {
+ if(_denominator == 1 || (_denominator != 0 && (_numerator % _denominator == 0)) || (_denominator == 0 && _numerator == 0))
+ return TRUE;
+ return FALSE;
+}
+
+/// Convert as "numerator/denominator"
+std::string FIRational::toString() {
+ std::ostringstream s;
+ if(isInteger()) {
+ s << intValue();
+ } else {
+ s << _numerator << "/" << _denominator;
+ }
+ return s.str();
+}
+
+
diff --git a/plugins/FreeImage/Source/Metadata/FIRational.h b/plugins/FreeImage/Source/Metadata/FIRational.h
index 7af6e52018..bd3ee13e07 100644
--- a/plugins/FreeImage/Source/Metadata/FIRational.h
+++ b/plugins/FreeImage/Source/Metadata/FIRational.h
@@ -1,108 +1,108 @@
-// ==========================================================
-// Helper class for rational numbers
-//
-// Design and implementation by
-// - Hervé Drolon <drolon@infonie.fr>
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#ifndef FIRATIONAL_H
-#define FIRATIONAL_H
-
-/**
-Helper class to deal with rational numbers.
-NB: LONG data type is assumed to be a signed 32-bit number.
-*/
-class FIRational {
-private:
- /// numerator
- LONG _numerator;
- /// denominator
- LONG _denominator;
-
-public:
- /// Default constructor
- FIRational();
-
- /// Constructor with longs
- FIRational(LONG n, LONG d = 1);
-
- /// Constructor with FITAG
- FIRational(const FITAG *tag);
-
- /// Constructor with a float
- FIRational(float value);
-
- /// Copy constructor
- FIRational (const FIRational& r);
-
- /// Destructor
- ~FIRational();
-
- /// Assignement operator
- FIRational& operator=(FIRational& r);
-
- /// Get the numerator
- LONG getNumerator();
-
- /// Get the denominator
- LONG getDenominator();
-
- /// Converts rational value by truncating towards zero
- LONG truncate() {
- // Return truncated rational
- return _denominator ? (LONG) (_numerator / _denominator) : 0;
- }
-
- /**@name Implicit conversions */
- //@{
- short shortValue() {
- return (short)truncate();
- }
- int intValue() {
- return (int)truncate();
- }
- LONG longValue() {
- return (LONG)truncate();
- }
- float floatValue() {
- return _denominator ? ((float)_numerator)/((float)_denominator) : 0;
- }
- double doubleValue() {
- return _denominator ? ((double)_numerator)/((double)_denominator) : 0;
- }
- //@}
-
- /// Checks if this rational number is an integer, either positive or negative
- BOOL isInteger();
-
- /// Convert as "numerator/denominator"
- std::string toString();
-
-private:
- /// Initialize and normalize a rational number
- void initialize(LONG n, LONG d);
-
- /// Calculate GCD
- LONG gcd(LONG a, LONG b);
-
- /// Normalize numerator / denominator
- void normalize();
-
-};
-
-#endif // FIRATIONAL_H
-
+// ==========================================================
+// Helper class for rational numbers
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef FIRATIONAL_H
+#define FIRATIONAL_H
+
+/**
+Helper class to deal with rational numbers.
+NB: LONG data type is assumed to be a signed 32-bit number.
+*/
+class FIRational {
+private:
+ /// numerator
+ LONG _numerator;
+ /// denominator
+ LONG _denominator;
+
+public:
+ /// Default constructor
+ FIRational();
+
+ /// Constructor with longs
+ FIRational(LONG n, LONG d = 1);
+
+ /// Constructor with FITAG
+ FIRational(const FITAG *tag);
+
+ /// Constructor with a float
+ FIRational(float value);
+
+ /// Copy constructor
+ FIRational (const FIRational& r);
+
+ /// Destructor
+ ~FIRational();
+
+ /// Assignement operator
+ FIRational& operator=(FIRational& r);
+
+ /// Get the numerator
+ LONG getNumerator();
+
+ /// Get the denominator
+ LONG getDenominator();
+
+ /// Converts rational value by truncating towards zero
+ LONG truncate() {
+ // Return truncated rational
+ return _denominator ? (LONG) (_numerator / _denominator) : 0;
+ }
+
+ /**@name Implicit conversions */
+ //@{
+ short shortValue() {
+ return (short)truncate();
+ }
+ int intValue() {
+ return (int)truncate();
+ }
+ LONG longValue() {
+ return (LONG)truncate();
+ }
+ float floatValue() {
+ return _denominator ? ((float)_numerator)/((float)_denominator) : 0;
+ }
+ double doubleValue() {
+ return _denominator ? ((double)_numerator)/((double)_denominator) : 0;
+ }
+ //@}
+
+ /// Checks if this rational number is an integer, either positive or negative
+ BOOL isInteger();
+
+ /// Convert as "numerator/denominator"
+ std::string toString();
+
+private:
+ /// Initialize and normalize a rational number
+ void initialize(LONG n, LONG d);
+
+ /// Calculate GCD
+ LONG gcd(LONG a, LONG b);
+
+ /// Normalize numerator / denominator
+ void normalize();
+
+};
+
+#endif // FIRATIONAL_H
+
diff --git a/plugins/FreeImage/Source/Metadata/FreeImageTag.cpp b/plugins/FreeImage/Source/Metadata/FreeImageTag.cpp
index 9936d53312..5d9f3034ec 100644
--- a/plugins/FreeImage/Source/Metadata/FreeImageTag.cpp
+++ b/plugins/FreeImage/Source/Metadata/FreeImageTag.cpp
@@ -1,287 +1,318 @@
-// ==========================================================
-// Tag manipulation functions
-//
-// Design and implementation by
-// - Hervé Drolon <drolon@infonie.fr>
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#ifdef _MSC_VER
-#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
-#endif
-
-#include "FreeImage.h"
-#include "Utilities.h"
-#include "FreeImageTag.h"
-
-// --------------------------------------------------------------------------
-// FITAG header definition
-// --------------------------------------------------------------------------
-
-FI_STRUCT (FITAGHEADER) {
- char *key; // tag field name
- char *description; // tag description
- WORD id; // tag ID
- WORD type; // tag data type (see FREE_IMAGE_MDTYPE)
- DWORD count; // number of components (in 'tag data types' units)
- DWORD length; // value length in bytes
- void *value; // tag value
-};
-
-// --------------------------------------------------------------------------
-// FITAG creation / destruction
-// --------------------------------------------------------------------------
-
-FITAG * DLL_CALLCONV
-FreeImage_CreateTag() {
- FITAG *tag = (FITAG *)malloc(sizeof(FITAG));
-
- if (tag != NULL) {
- unsigned tag_size = sizeof(FITAGHEADER);
- tag->data = (BYTE *)malloc(tag_size * sizeof(BYTE));
- if (tag->data != NULL) {
- memset(tag->data, 0, tag_size);
- return tag;
- }
- free(tag);
- }
-
- return NULL;
-}
-
-void DLL_CALLCONV
-FreeImage_DeleteTag(FITAG *tag) {
- if (NULL != tag) {
- if (NULL != tag->data) {
- FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
- // delete tag members
- free(tag_header->key);
- free(tag_header->description);
- free(tag_header->value);
- // delete the tag
- free(tag->data);
- }
- // and the wrapper
- free(tag);
- }
-}
-
-FITAG * DLL_CALLCONV
-FreeImage_CloneTag(FITAG *tag) {
- if(!tag) return NULL;
-
- // allocate a new tag
- FITAG *clone = FreeImage_CreateTag();
- if(!clone) return NULL;
-
- // copy the tag
- FITAGHEADER *src_tag = (FITAGHEADER *)tag->data;
- FITAGHEADER *dst_tag = (FITAGHEADER *)clone->data;
-
- // tag ID
- dst_tag->id = src_tag->id;
- // tag key
- if(src_tag->key) {
- dst_tag->key = (char*)malloc((strlen(src_tag->key) + 1) * sizeof(char));
- strcpy(dst_tag->key, src_tag->key);
- }
- // tag description
- if(src_tag->description) {
- dst_tag->description = (char*)malloc((strlen(src_tag->description) + 1) * sizeof(char));
- strcpy(dst_tag->description, src_tag->description);
- }
- // tag data type
- dst_tag->type = src_tag->type;
- // tag count
- dst_tag->count = src_tag->count;
- // tag length
- dst_tag->length = src_tag->length;
- // tag value
- switch(dst_tag->type) {
- case FIDT_ASCII:
- dst_tag->value = (char*)malloc((strlen((char*)src_tag->value) + 1) * sizeof(char));
- strcpy((char*)dst_tag->value, (char*)src_tag->value);
- break;
- default:
- dst_tag->value = (BYTE*)malloc(src_tag->length * sizeof(BYTE));
- memcpy(dst_tag->value, src_tag->value, src_tag->length);
- break;
- }
-
- return clone;
-}
-
-// --------------------------------------------------------------------------
-// FITAG getters / setters
-// --------------------------------------------------------------------------
-
-const char * DLL_CALLCONV
-FreeImage_GetTagKey(FITAG *tag) {
- return tag ? ((FITAGHEADER *)tag->data)->key : 0;
-}
-
-const char * DLL_CALLCONV
-FreeImage_GetTagDescription(FITAG *tag) {
- return tag ? ((FITAGHEADER *)tag->data)->description : 0;
-}
-
-WORD DLL_CALLCONV
-FreeImage_GetTagID(FITAG *tag) {
- return tag ? ((FITAGHEADER *)tag->data)->id : 0;
-}
-
-FREE_IMAGE_MDTYPE DLL_CALLCONV
-FreeImage_GetTagType(FITAG *tag) {
- return tag ? (FREE_IMAGE_MDTYPE)(((FITAGHEADER *)tag->data)->type) : FIDT_NOTYPE;
-}
-
-DWORD DLL_CALLCONV
-FreeImage_GetTagCount(FITAG *tag) {
- return tag ? ((FITAGHEADER *)tag->data)->count : 0;
-}
-
-DWORD DLL_CALLCONV
-FreeImage_GetTagLength(FITAG *tag) {
- return tag ? ((FITAGHEADER *)tag->data)->length : 0;
-}
-
-const void *DLL_CALLCONV
-FreeImage_GetTagValue(FITAG *tag) {
- return tag ? ((FITAGHEADER *)tag->data)->value : 0;
-}
-
-BOOL DLL_CALLCONV
-FreeImage_SetTagKey(FITAG *tag, const char *key) {
- if(tag && key) {
- FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
- if(tag_header->key) free(tag_header->key);
- tag_header->key = (char*)malloc(strlen(key) + 1);
- strcpy(tag_header->key, key);
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL DLL_CALLCONV
-FreeImage_SetTagDescription(FITAG *tag, const char *description) {
- if(tag && description) {
- FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
- if(tag_header->description) free(tag_header->description);
- tag_header->description = (char*)malloc(strlen(description) + 1);
- strcpy(tag_header->description, description);
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL DLL_CALLCONV
-FreeImage_SetTagID(FITAG *tag, WORD id) {
- if(tag) {
- FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
- tag_header->id = id;
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL DLL_CALLCONV
-FreeImage_SetTagType(FITAG *tag, FREE_IMAGE_MDTYPE type) {
- if(tag) {
- FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
- tag_header->type = (WORD)type;
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL DLL_CALLCONV
-FreeImage_SetTagCount(FITAG *tag, DWORD count) {
- if(tag) {
- FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
- tag_header->count = count;
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL DLL_CALLCONV
-FreeImage_SetTagLength(FITAG *tag, DWORD length) {
- if(tag) {
- FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
- tag_header->length = length;
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL DLL_CALLCONV
-FreeImage_SetTagValue(FITAG *tag, const void *value) {
- if(tag && value) {
- FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
- // first, check the tag
- if(tag_header->count * FreeImage_TagDataWidth((FREE_IMAGE_MDTYPE)tag_header->type) != tag_header->length) {
- // invalid data count ?
- return FALSE;
- }
-
- if(tag_header->value) {
- free(tag_header->value);
- }
-
- switch(tag_header->type) {
- case FIDT_ASCII:
- {
- tag_header->value = (char*)malloc((tag_header->length + 1) * sizeof(char));
- if(!tag_header->value) {
- return FALSE;
- }
- char *src_data = (char*)value;
- char *dst_data = (char*)tag_header->value;
- for(DWORD i = 0; i < tag_header->length; i++) {
- dst_data[i] = src_data[i];
- }
- dst_data[tag_header->length] = '\0';
- }
- break;
-
- default:
- tag_header->value = malloc(tag_header->length * sizeof(BYTE));
- if(!tag_header->value) {
- return FALSE;
- }
- memcpy(tag_header->value, value, tag_header->length);
- break;
- }
- return TRUE;
- }
- return FALSE;
-}
-
-
-// --------------------------------------------------------------------------
-// FITAG internal helper functions
-// --------------------------------------------------------------------------
-
-int
-FreeImage_TagDataWidth(FREE_IMAGE_MDTYPE type) {
- static const int format_bytes[] = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4, 4 };
-
- return (type < (sizeof(format_bytes)/sizeof(format_bytes[0]))) ?
- format_bytes[type] : 0;
-}
-
-
-
+// ==========================================================
+// Tag manipulation functions
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageTag.h"
+
+// --------------------------------------------------------------------------
+// FITAG header definition
+// --------------------------------------------------------------------------
+
+FI_STRUCT (FITAGHEADER) {
+ char *key; // tag field name
+ char *description; // tag description
+ WORD id; // tag ID
+ WORD type; // tag data type (see FREE_IMAGE_MDTYPE)
+ DWORD count; // number of components (in 'tag data types' units)
+ DWORD length; // value length in bytes
+ void *value; // tag value
+};
+
+// --------------------------------------------------------------------------
+// FITAG creation / destruction
+// --------------------------------------------------------------------------
+
+FITAG * DLL_CALLCONV
+FreeImage_CreateTag() {
+ FITAG *tag = (FITAG *)malloc(sizeof(FITAG));
+
+ if (tag != NULL) {
+ unsigned tag_size = sizeof(FITAGHEADER);
+ tag->data = (BYTE *)malloc(tag_size * sizeof(BYTE));
+ if (tag->data != NULL) {
+ memset(tag->data, 0, tag_size);
+ return tag;
+ }
+ free(tag);
+ }
+
+ return NULL;
+}
+
+void DLL_CALLCONV
+FreeImage_DeleteTag(FITAG *tag) {
+ if (NULL != tag) {
+ if (NULL != tag->data) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ // delete tag members
+ free(tag_header->key);
+ free(tag_header->description);
+ free(tag_header->value);
+ // delete the tag
+ free(tag->data);
+ }
+ // and the wrapper
+ free(tag);
+ }
+}
+
+FITAG * DLL_CALLCONV
+FreeImage_CloneTag(FITAG *tag) {
+ if(!tag) return NULL;
+
+ // allocate a new tag
+ FITAG *clone = FreeImage_CreateTag();
+ if(!clone) return NULL;
+
+ try {
+ // copy the tag
+ FITAGHEADER *src_tag = (FITAGHEADER *)tag->data;
+ FITAGHEADER *dst_tag = (FITAGHEADER *)clone->data;
+
+ // tag ID
+ dst_tag->id = src_tag->id;
+ // tag key
+ if(src_tag->key) {
+ dst_tag->key = (char*)malloc((strlen(src_tag->key) + 1) * sizeof(char));
+ if(!dst_tag->key) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+ strcpy(dst_tag->key, src_tag->key);
+ }
+ // tag description
+ if(src_tag->description) {
+ dst_tag->description = (char*)malloc((strlen(src_tag->description) + 1) * sizeof(char));
+ if(!dst_tag->description) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+ strcpy(dst_tag->description, src_tag->description);
+ }
+ // tag data type
+ dst_tag->type = src_tag->type;
+ // tag count
+ dst_tag->count = src_tag->count;
+ // tag length
+ dst_tag->length = src_tag->length;
+ // tag value
+ dst_tag->value = (BYTE*)malloc(src_tag->length * sizeof(BYTE));
+ if(!dst_tag->value) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+ memcpy(dst_tag->value, src_tag->value, src_tag->length);
+
+ return clone;
+
+ } catch(const char *message) {
+ FreeImage_DeleteTag(clone);
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, message);
+ return NULL;
+ }
+}
+
+// --------------------------------------------------------------------------
+// FITAG getters / setters
+// --------------------------------------------------------------------------
+
+const char * DLL_CALLCONV
+FreeImage_GetTagKey(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->key : 0;
+}
+
+const char * DLL_CALLCONV
+FreeImage_GetTagDescription(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->description : 0;
+}
+
+WORD DLL_CALLCONV
+FreeImage_GetTagID(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->id : 0;
+}
+
+FREE_IMAGE_MDTYPE DLL_CALLCONV
+FreeImage_GetTagType(FITAG *tag) {
+ return tag ? (FREE_IMAGE_MDTYPE)(((FITAGHEADER *)tag->data)->type) : FIDT_NOTYPE;
+}
+
+DWORD DLL_CALLCONV
+FreeImage_GetTagCount(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->count : 0;
+}
+
+DWORD DLL_CALLCONV
+FreeImage_GetTagLength(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->length : 0;
+}
+
+const void *DLL_CALLCONV
+FreeImage_GetTagValue(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->value : 0;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagKey(FITAG *tag, const char *key) {
+ if(tag && key) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ if(tag_header->key) free(tag_header->key);
+ tag_header->key = (char*)malloc(strlen(key) + 1);
+ strcpy(tag_header->key, key);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagDescription(FITAG *tag, const char *description) {
+ if(tag && description) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ if(tag_header->description) free(tag_header->description);
+ tag_header->description = (char*)malloc(strlen(description) + 1);
+ strcpy(tag_header->description, description);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagID(FITAG *tag, WORD id) {
+ if(tag) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ tag_header->id = id;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagType(FITAG *tag, FREE_IMAGE_MDTYPE type) {
+ if(tag) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ tag_header->type = (WORD)type;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagCount(FITAG *tag, DWORD count) {
+ if(tag) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ tag_header->count = count;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagLength(FITAG *tag, DWORD length) {
+ if(tag) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ tag_header->length = length;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagValue(FITAG *tag, const void *value) {
+ if(tag && value) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ // first, check the tag
+ if(tag_header->count * FreeImage_TagDataWidth((FREE_IMAGE_MDTYPE)tag_header->type) != tag_header->length) {
+ // invalid data count ?
+ return FALSE;
+ }
+
+ if(tag_header->value) {
+ free(tag_header->value);
+ }
+
+ switch(tag_header->type) {
+ case FIDT_ASCII:
+ {
+ tag_header->value = (char*)malloc((tag_header->length + 1) * sizeof(char));
+ if(!tag_header->value) {
+ return FALSE;
+ }
+ char *src_data = (char*)value;
+ char *dst_data = (char*)tag_header->value;
+ for(DWORD i = 0; i < tag_header->length; i++) {
+ dst_data[i] = src_data[i];
+ }
+ dst_data[tag_header->length] = '\0';
+ }
+ break;
+
+ default:
+ tag_header->value = malloc(tag_header->length * sizeof(BYTE));
+ if(!tag_header->value) {
+ return FALSE;
+ }
+ memcpy(tag_header->value, value, tag_header->length);
+ break;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+// --------------------------------------------------------------------------
+// FITAG internal helper functions
+// --------------------------------------------------------------------------
+
+/**
+Given a FREE_IMAGE_MDTYPE, calculate the size of this type in bytes unit
+@param type Input data type
+@return Returns the size of the data type, in bytes unit
+*/
+unsigned
+FreeImage_TagDataWidth(FREE_IMAGE_MDTYPE type) {
+ static const unsigned format_bytes[] = {
+ 0, // FIDT_NOTYPE = 0, // placeholder
+ 1, // FIDT_BYTE = 1, // 8-bit unsigned integer
+ 1, // FIDT_ASCII = 2, // 8-bit bytes w/ last byte null
+ 2, // FIDT_SHORT = 3, // 16-bit unsigned integer
+ 4, // FIDT_LONG = 4, // 32-bit unsigned integer
+ 8, // FIDT_RATIONAL = 5, // 64-bit unsigned fraction
+ 1, // FIDT_SBYTE = 6, // 8-bit signed integer
+ 1, // FIDT_UNDEFINED= 7, // 8-bit untyped data
+ 2, // FIDT_SSHORT = 8, // 16-bit signed integer
+ 4, // FIDT_SLONG = 9, // 32-bit signed integer
+ 8, // FIDT_SRATIONAL= 10, // 64-bit signed fraction
+ 4, // FIDT_FLOAT = 11, // 32-bit IEEE floating point
+ 8, // FIDT_DOUBLE = 12, // 64-bit IEEE floating point
+ 4, // FIDT_IFD = 13, // 32-bit unsigned integer (offset)
+ 4, // FIDT_PALETTE = 14 // 32-bit RGBQUAD
+ 0, // placeholder (15)
+ 8, // FIDT_LONG8 = 16, // 64-bit unsigned integer
+ 8, // FIDT_SLONG8 = 17, // 64-bit signed integer
+ 8 // FIDT_IFD8 = 18 // 64-bit unsigned integer (offset)
+ };
+
+ return (type < (sizeof(format_bytes)/sizeof(format_bytes[0]))) ?
+ format_bytes[type] : 0;
+}
+
diff --git a/plugins/FreeImage/Source/Metadata/FreeImageTag.h b/plugins/FreeImage/Source/Metadata/FreeImageTag.h
index baa78743c6..f412603e8d 100644
--- a/plugins/FreeImage/Source/Metadata/FreeImageTag.h
+++ b/plugins/FreeImage/Source/Metadata/FreeImageTag.h
@@ -1,438 +1,474 @@
-// ==========================================================
-// Tag manipulation functions
-//
-// Design and implementation by
-// - Hervé Drolon <drolon@infonie.fr>
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#ifndef FREEIMAGETAG_H
-#define FREEIMAGETAG_H
-
-// ==========================================================
-// Exif JPEG tags
-// ==========================================================
-
-// ----------------------------------------------------------
-// TIFF Rev. 6.0 Attribute Information Used in Exif
-// ----------------------------------------------------------
-
-// Tags relating to image data structure
-
-#define TAG_IMAGE_WIDTH 0x0100
-#define TAG_IMAGE_HEIGHT 0x0101
-#define TAG_BITS_PER_SAMPLE 0x0102
-#define TAG_COMPRESSION 0x0103
-#define TAG_PHOTOMETRIC_INTERPRETATION 0x0106
-#define TAG_ORIENTATION 0x0112
-#define TAG_SAMPLES_PER_PIXEL 0x0115
-#define TAG_PLANAR_CONFIGURATION 0x011C
-#define TAG_YCBCR_SUBSAMPLING 0x0212
-#define TAG_YCBCR_POSITIONING 0x0213
-#define TAG_X_RESOLUTION 0x011A
-#define TAG_Y_RESOLUTION 0x011B
-#define TAG_RESOLUTION_UNIT 0x0128
-
-// Tags relating to recording offset
-
-#define TAG_STRIP_OFFSETS 0x0111
-#define TAG_ROWS_PER_STRIP 0x0116
-#define TAG_STRIP_BYTE_COUNTS 0x0117
-#define TAG_JPEG_INTERCHANGE_FORMAT 0x0201
-#define TAG_JPEG_INTERCHANGE_FORMAT_LENGTH 0x0202
-
-// Tags relating to image data characteristics
-
-#define TAG_TRANSFER_FUNCTION 0x012D
-#define TAG_WHITE_POINT 0x013E
-#define TAG_PRIMARY_CHROMATICITIES 0x013F
-#define TAG_YCBCR_COEFFICIENTS 0x0211
-#define TAG_REFERENCE_BLACK_WHITE 0x0214
-
-// Other tags
-
-#define TAG_DATETIME 0x0132
-#define TAG_IMAGE_DESCRIPTION 0x010E
-#define TAG_MAKE 0x010F
-#define TAG_MODEL 0x0110
-#define TAG_SOFTWARE 0x0131
-#define TAG_ARTIST 0x013B
-#define TAG_COPYRIGHT 0x8298
-
-// ----------------------------------------------------------
-// Exif IFD Attribute Information
-// ----------------------------------------------------------
-
-// Tags relating to version
-
-#define TAG_EXIF_VERSION 0x9000
-#define TAG_FLASHPIX_VERSION 0xA000
-
-// Tag relating to image data characteristics
-
-#define TAG_COLOR_SPACE 0xA001
-
-// Tags relating to image configuration
-
-#define TAG_COMPONENTS_CONFIGURATION 0x9101
-#define TAG_COMPRESSED_BITS_PER_PIXEL 0x9102
-#define TAG_PIXEL_X_DIMENSION 0xA002
-#define TAG_PIXEL_Y_DIMENSION 0xA003
-
-// Tags relating to user information
-
-#define TAG_MARKER_NOTE 0x927C
-#define TAG_USER_COMMENT 0x9286
-
-// Tag relating to related file information
-
-#define TAG_RELATED_SOUND_FILE 0xA004
-
-// Tags relating to date and time
-
-#define TAG_DATETIME_ORIGINAL 0x9003
-#define TAG_DATETIME_DIGITIZED 0x9004
-#define TAG_SUBSECOND_TIME 0x9290
-#define TAG_SUBSECOND_TIME_ORIGINAL 0x9291
-#define TAG_SUBSECOND_TIME_DIGITIZED 0x9292
-
-// Tags relating to picture-taking conditions
-
-#define TAG_EXPOSURE_TIME 0x829A
-#define TAG_FNUMBER 0x829D
-#define TAG_EXPOSURE_PROGRAM 0x8822
-#define TAG_SPECTRAL_SENSITIVITY 0x8824
-#define TAG_ISO_SPEED_RATINGS 0x8827
-#define TAG_OECF 0x8828
-#define TAG_SHUTTER_SPEED_VALUE 0x9201
-#define TAG_APERTURE_VALUE 0x9202
-#define TAG_BRIGHTNESS_VALUE 0x9203
-#define TAG_EXPOSURE_BIAS_VALUE 0x9204
-#define TAG_MAX_APERTURE_VALUE 0x9205
-#define TAG_SUBJECT_DISTANCE 0x9206
-#define TAG_METERING_MODE 0x9207
-#define TAG_LIGHT_SOURCE 0x9208
-#define TAG_FLASH 0x9209
-#define TAG_FOCAL_LENGTH 0x920A
-#define TAG_SUBJECT_AREA 0x9214
-#define TAG_FLASH_ENERGY 0xA20B
-#define TAG_SPATIAL_FREQ_RESPONSE 0xA20C
-#define TAG_FOCAL_PLANE_X_RES 0xA20E
-#define TAG_FOCAL_PLANE_Y_RES 0xA20F
-#define TAG_FOCAL_PLANE_UNIT 0xA210
-#define TAG_SUBJECT_LOCATION 0xA214
-#define TAG_EXPOSURE_INDEX 0xA215
-#define TAG_SENSING_METHOD 0xA217
-#define TAG_FILE_SOURCE 0xA300
-#define TAG_SCENE_TYPE 0xA301
-#define TAG_CFA_PATTERN 0xA302
-#define TAG_CUSTOM_RENDERED 0xA401
-#define TAG_EXPOSURE_MODE 0xA402
-#define TAG_WHITE_BALANCE 0xA403
-#define TAG_DIGITAL_ZOOM_RATIO 0xA404
-#define TAG_FOCAL_LENGTH_IN_35MM_FILM 0xA405
-#define TAG_SCENE_CAPTURE_TYPE 0xA406
-#define TAG_GAIN_CONTROL 0xA407
-#define TAG_CONTRAST 0xA408
-#define TAG_SATURATION 0xA409
-#define TAG_SHARPNESS 0xA40A
-#define TAG_DEVICE_SETTING_DESCRIPTION 0xA40B
-#define TAG_SUBJECT_DISTANCE_RANGE 0xA40C
-
-// Other tags
-
-#define TAG_IMAGE_UNIQUE_ID 0xA420
-
-// ----------------------------------------------------------
-// GPS Attribute Information
-// ----------------------------------------------------------
-
-#define TAG_GPS_VERSION_ID 0x0000
-#define TAG_GPS_LATITUDE_REF 0x0001
-#define TAG_GPS_LATITUDE 0x0002
-#define TAG_GPS_LONGITUDE_REF 0x0003
-#define TAG_GPS_LONGITUDE 0x0004
-#define TAG_GPS_ALTITUDE_REF 0x0005
-#define TAG_GPS_ALTITUDE 0x0006
-#define TAG_GPS_TIME_STAMP 0x0007
-#define TAG_GPS_SATELLITES 0x0008
-#define TAG_GPS_STATUS 0x0009
-#define TAG_GPS_MEASURE_MODE 0x000A
-#define TAG_GPS_DOP 0x000B
-#define TAG_GPS_SPEED_REF 0x000C
-#define TAG_GPS_SPEED 0x000D
-#define TAG_GPS_TRACK_REF 0x000E
-#define TAG_GPS_TRACK 0x000F
-#define TAG_GPS_IMG_DIRECTION_REF 0x0010
-#define TAG_GPS_IMG_DIRECTION 0x0011
-#define TAG_GPS_MAP_DATUM 0x0012
-#define TAG_GPS_DEST_LATITUDE_REF 0x0013
-#define TAG_GPS_DEST_LATITUDE 0x0014
-#define TAG_GPS_DEST_LONGITUDE_REF 0x0015
-#define TAG_GPS_DEST_LONGITUDE 0x0016
-#define TAG_GPS_DEST_BEARING_REF 0x0017
-#define TAG_GPS_DEST_BEARING 0x0018
-#define TAG_GPS_DEST_DISTANCE_REF 0x0019
-#define TAG_GPS_DEST_DISTANCE 0x001A
-#define TAG_GPS_PROCESSING_METHOD 0x001B
-#define TAG_GPS_AREA_INFORMATION 0x001C
-#define TAG_GPS_DATE_STAMP 0x001D
-#define TAG_GPS_DIFFERENTIAL 0x001E
-
-// ==========================================================
-// IPTC/NAA tags
-// ==========================================================
-
-#define TAG_RECORD_VERSION 0x0200
-#define TAG_CAPTION 0x0278
-#define TAG_WRITER 0x027A
-#define TAG_HEADLINE 0x0269
-#define TAG_SPECIAL_INSTRUCTIONS 0x0228
-#define TAG_BY_LINE 0x0250
-#define TAG_BY_LINE_TITLE 0x0255
-#define TAG_CREDIT 0x026E
-#define TAG_SOURCE 0x0273
-#define TAG_OBJECT_NAME 0x0205
-#define TAG_DATE_CREATED 0x0237
-#define TAG_CITY 0x025A
-#define TAG_PROVINCE_OR_STATE 0x025F
-#define TAG_COUNTRY_OR_PRIMARY_LOCATION 0x0265
-#define TAG_ORIGINAL_TRANSMISSION_REFERENCE 0x0267
-#define TAG_CATEGORY 0x020F
-#define TAG_SUPPLEMENTAL_CATEGORIES 0x0214
-#define TAG_URGENCY 0x020A
-#define TAG_KEYWORDS 0x0219
-#define TAG_COPYRIGHT_NOTICE 0x0274
-#define TAG_RELEASE_DATE 0x021E
-#define TAG_RELEASE_TIME 0x0223
-#define TAG_TIME_CREATED 0x023C
-#define TAG_ORIGINATING_PROGRAM 0x0241
-
-// ==========================================================
-// GeoTIFF tags
-// ==========================================================
-
-// tags 33550 is a private tag registered to SoftDesk, Inc
-#define TIFFTAG_GEOPIXELSCALE 33550
-// tags 33920-33921 are private tags registered to Intergraph, Inc
-#define TIFFTAG_INTERGRAPH_MATRIX 33920
-#define TIFFTAG_GEOTIEPOINTS 33922
-// tags 34263-34264 are private tags registered to NASA-JPL Carto Group
-#define TIFFTAG_JPL_CARTO_IFD 34263
-#define TIFFTAG_GEOTRANSMATRIX 34264 /* New Matrix Tag replaces 33920 */
-// tags 34735-3438 are private tags registered to SPOT Image, Inc
-#define TIFFTAG_GEOKEYDIRECTORY 34735
-#define TIFFTAG_GEODOUBLEPARAMS 34736
-#define TIFFTAG_GEOASCIIPARAMS 34737
-
-// ==========================================================
-// FreeImage Animation tags
-// ==========================================================
-
-#define ANIMTAG_LOGICALWIDTH 0x0001
-#define ANIMTAG_LOGICALHEIGHT 0x0002
-#define ANIMTAG_GLOBALPALETTE 0x0003
-#define ANIMTAG_LOOP 0x0004
-#define ANIMTAG_FRAMELEFT 0x1001
-#define ANIMTAG_FRAMETOP 0x1002
-#define ANIMTAG_NOLOCALPALETTE 0x1003
-#define ANIMTAG_INTERLACED 0x1004
-#define ANIMTAG_FRAMETIME 0x1005
-#define ANIMTAG_DISPOSALMETHOD 0x1006
-
-// --------------------------------------------------------------------------
-// Helper functions to deal with the FITAG structure
-// --------------------------------------------------------------------------
-
-/**
-Describes the tag format descriptor
-@param type Tag data type
-@return Returns the width of a single element, in bytes
-@see FREE_IMAGE_MDTYPE
-*/
-int FreeImage_TagDataWidth(FREE_IMAGE_MDTYPE type);
-
-// --------------------------------------------------------------------------
-
-/**
- Structure to hold a tag information
-*/
-typedef struct tagTagInfo {
- WORD tag; // Tag ID (required)
- char *fieldname; // Field name (required)
- char *description; // Field description (may be NULL)
-} TagInfo;
-
-
-/**
- Class to hold tag information (based on Meyers’ Singleton).<br>
-
- Sample usage :<br>
- <code>
- TagLib& s = TagLib::instance();
- TagInfo *tag_info = s.getTagInfo(EXIF_MAIN, 0x0100);
- </code>
-
-*/
-
-class TagLib {
-public:
-
- /**
- internal tag info tables registered in TagLib
- */
- enum MDMODEL {
- UNKNOWN,
- EXIF_MAIN,
- EXIF_EXIF,
- EXIF_GPS,
- EXIF_INTEROP,
- EXIF_MAKERNOTE_CANON,
- EXIF_MAKERNOTE_CASIOTYPE1,
- EXIF_MAKERNOTE_CASIOTYPE2,
- EXIF_MAKERNOTE_FUJIFILM,
- EXIF_MAKERNOTE_KYOCERA,
- EXIF_MAKERNOTE_MINOLTA,
- EXIF_MAKERNOTE_NIKONTYPE1,
- EXIF_MAKERNOTE_NIKONTYPE2,
- EXIF_MAKERNOTE_NIKONTYPE3,
- EXIF_MAKERNOTE_OLYMPUSTYPE1,
- EXIF_MAKERNOTE_PANASONIC,
- EXIF_MAKERNOTE_ASAHI,
- EXIF_MAKERNOTE_PENTAX,
- EXIF_MAKERNOTE_SONY,
- IPTC,
- GEOTIFF,
- ANIMATION
- };
-
-private:
-
- typedef std::map<WORD, TagInfo*> TAGINFO;
- typedef std::map<int, TAGINFO*> TABLEMAP;
-
- /// store hash tables for all known tag info tables
- TABLEMAP _table_map;
-
-private:
- /**
- Constructor (private)<br>
- This is where the tag info tables are initialized.
- @see addMetadataModel
- */
- TagLib();
-
- /// Assignement operator (disabled)
- void operator=(TagLib&);
-
- /// Copy constructor (disabled)
- TagLib(const TagLib&);
-
- /**
- Used in the constructor to initialize the tag tables
- @param md_model Internal metadata model
- @param tag_table Tag info table
- @return Returns TRUE if successful, returns FALSE otherwise
- */
- BOOL addMetadataModel(MDMODEL md_model, TagInfo *tag_table);
-
-public:
- /// Destructor
- ~TagLib();
-
- /**
- @return Returns a reference to the TagLib instance
- */
- static TagLib& instance();
-
- /**
- Given a tag ID, returns its TagInfo descriptor
- @param md_model Internal metadata model
- @param tagID tag ID
- @return Returns the TagInfo descriptor if successful, returns NULL otherwise
- */
- const TagInfo* getTagInfo(MDMODEL md_model, WORD tagID);
-
- /**
- Given a tag ID, returns its tag field name.
- When the tag is unknown and defaultKey is not NULL, a string such as "Tag 0x1234" is returned.
- This string is contained in the provided defaultKey buffer (assumed to be an array of at least 16 chars).
- @param md_model Internal metadata model
- @param tagID tag ID
- @param defaultKey Assumed to be an array of 16 chars. If not NULL, build a key for unknown tags
- @return Returns the tag field name if successful, returns an 'unknown tag' string contained in defaultKey otherwise
- */
- const char* getTagFieldName(MDMODEL md_model, WORD tagID, char *defaultKey);
-
- /**
- Given a tag ID, returns its description.
- When the tag has no description, a NULL value is returned.
- @param md_model Internal metadata model
- @param tagID tag ID
- @return Returns the tag description if successful, returns NULL otherwise
- */
- const char* getTagDescription(MDMODEL md_model, WORD tagID);
-
- /**
- Given a tag field name, returns its tag ID.
- When the tag doesn't exists, a value '-1' is returned.
- @param md_model Internal metadata model
- @param key tag field name
- @return Returns the tag ID if successful, returns -1 otherwise
- */
- int getTagID(MDMODEL md_model, const char *key);
-
- /**
- Perform a conversion between internal metadata models and FreeImage public metadata models
- @param md_model Internal metadata model
- */
- FREE_IMAGE_MDMODEL getFreeImageModel(MDMODEL model);
-
-};
-
-// --------------------------------------------------------------------------
-// Constant strings
-// --------------------------------------------------------------------------
-
-/// Name of the XMP field
-static char *g_TagLib_XMPFieldName = "XMLPacket";
-
-/// Name of the Exif raw field
-static char *g_TagLib_ExifRawFieldName = "ExifRaw";
-
-// --------------------------------------------------------------------------
-// Metadata routines
-// --------------------------------------------------------------------------
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-// JPEG Exif profile
-BOOL jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen);
-
-// JPEG / TIFF IPTC profile
-BOOL read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen);
-BOOL write_iptc_profile(FIBITMAP *dib, BYTE **profile, unsigned *profile_size);
-
-#if defined(__cplusplus)
-}
-#endif
-
-
-#endif // FREEIMAGETAG_H
-
-
+// ==========================================================
+// Tag manipulation functions
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef FREEIMAGETAG_H
+#define FREEIMAGETAG_H
+
+// ==========================================================
+// Exif JPEG tags
+// ==========================================================
+
+// ----------------------------------------------------------
+// TIFF Rev. 6.0 Attribute Information Used in Exif
+// ----------------------------------------------------------
+
+// Tags relating to image data structure
+
+#define TAG_IMAGE_WIDTH 0x0100
+#define TAG_IMAGE_HEIGHT 0x0101
+#define TAG_BITS_PER_SAMPLE 0x0102
+#define TAG_COMPRESSION 0x0103
+#define TAG_PHOTOMETRIC_INTERPRETATION 0x0106
+#define TAG_ORIENTATION 0x0112
+#define TAG_SAMPLES_PER_PIXEL 0x0115
+#define TAG_PLANAR_CONFIGURATION 0x011C
+#define TAG_YCBCR_SUBSAMPLING 0x0212
+#define TAG_YCBCR_POSITIONING 0x0213
+#define TAG_X_RESOLUTION 0x011A
+#define TAG_Y_RESOLUTION 0x011B
+#define TAG_RESOLUTION_UNIT 0x0128
+
+// LibTIF compression modes
+
+#define TAG_COMPRESSION_NONE 1 /* dump mode */
+#define TAG_COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */
+#define TAG_COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */
+#define TAG_COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */
+#define TAG_COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */
+#define TAG_COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */
+#define TAG_COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */
+#define TAG_COMPRESSION_OJPEG 6 /* !6.0 JPEG */
+#define TAG_COMPRESSION_JPEG 7 /* %JPEG DCT compression */
+#define TAG_COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */
+#define TAG_COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */
+#define TAG_COMPRESSION_PACKBITS 32773 /* Macintosh RLE */
+#define TAG_COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */
+/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */
+#define TAG_COMPRESSION_IT8CTPAD 32895 /* IT8 CT w/padding */
+#define TAG_COMPRESSION_IT8LW 32896 /* IT8 Linework RLE */
+#define TAG_COMPRESSION_IT8MP 32897 /* IT8 Monochrome picture */
+#define TAG_COMPRESSION_IT8BL 32898 /* IT8 Binary line art */
+/* compression codes 32908-32911 are reserved for Pixar */
+#define TAG_COMPRESSION_PIXARFILM 32908 /* Pixar companded 10bit LZW */
+#define TAG_COMPRESSION_PIXARLOG 32909 /* Pixar companded 11bit ZIP */
+#define TAG_COMPRESSION_DEFLATE 32946 /* Deflate compression */
+#define TAG_COMPRESSION_ADOBE_DEFLATE 8 /* Deflate compression,
+ as recognized by Adobe */
+/* compression code 32947 is reserved for Oceana Matrix <dev@oceana.com> */
+#define TAG_COMPRESSION_DCS 32947 /* Kodak DCS encoding */
+#define TAG_COMPRESSION_JBIG 34661 /* ISO JBIG */
+#define TAG_COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */
+#define TAG_COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */
+#define TAG_COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */
+#define TAG_COMPRESSION_LZMA 34925 /* LZMA2 */
+
+// Tags relating to recording offset
+
+#define TAG_STRIP_OFFSETS 0x0111
+#define TAG_ROWS_PER_STRIP 0x0116
+#define TAG_STRIP_BYTE_COUNTS 0x0117
+#define TAG_JPEG_INTERCHANGE_FORMAT 0x0201
+#define TAG_JPEG_INTERCHANGE_FORMAT_LENGTH 0x0202
+
+// Tags relating to image data characteristics
+
+#define TAG_TRANSFER_FUNCTION 0x012D
+#define TAG_WHITE_POINT 0x013E
+#define TAG_PRIMARY_CHROMATICITIES 0x013F
+#define TAG_YCBCR_COEFFICIENTS 0x0211
+#define TAG_REFERENCE_BLACK_WHITE 0x0214
+
+// Other tags
+
+#define TAG_DATETIME 0x0132
+#define TAG_IMAGE_DESCRIPTION 0x010E
+#define TAG_MAKE 0x010F
+#define TAG_MODEL 0x0110
+#define TAG_SOFTWARE 0x0131
+#define TAG_ARTIST 0x013B
+#define TAG_COPYRIGHT 0x8298
+
+// ----------------------------------------------------------
+// Exif IFD Attribute Information
+// ----------------------------------------------------------
+
+// Tags relating to version
+
+#define TAG_EXIF_VERSION 0x9000
+#define TAG_FLASHPIX_VERSION 0xA000
+
+// Tag relating to image data characteristics
+
+#define TAG_COLOR_SPACE 0xA001
+
+// Tags relating to image configuration
+
+#define TAG_COMPONENTS_CONFIGURATION 0x9101
+#define TAG_COMPRESSED_BITS_PER_PIXEL 0x9102
+#define TAG_PIXEL_X_DIMENSION 0xA002
+#define TAG_PIXEL_Y_DIMENSION 0xA003
+
+// Tags relating to user information
+
+#define TAG_MARKER_NOTE 0x927C
+#define TAG_USER_COMMENT 0x9286
+
+// Tag relating to related file information
+
+#define TAG_RELATED_SOUND_FILE 0xA004
+
+// Tags relating to date and time
+
+#define TAG_DATETIME_ORIGINAL 0x9003
+#define TAG_DATETIME_DIGITIZED 0x9004
+#define TAG_SUBSECOND_TIME 0x9290
+#define TAG_SUBSECOND_TIME_ORIGINAL 0x9291
+#define TAG_SUBSECOND_TIME_DIGITIZED 0x9292
+
+// Tags relating to picture-taking conditions
+
+#define TAG_EXPOSURE_TIME 0x829A
+#define TAG_FNUMBER 0x829D
+#define TAG_EXPOSURE_PROGRAM 0x8822
+#define TAG_SPECTRAL_SENSITIVITY 0x8824
+#define TAG_ISO_SPEED_RATINGS 0x8827
+#define TAG_OECF 0x8828
+#define TAG_SHUTTER_SPEED_VALUE 0x9201
+#define TAG_APERTURE_VALUE 0x9202
+#define TAG_BRIGHTNESS_VALUE 0x9203
+#define TAG_EXPOSURE_BIAS_VALUE 0x9204
+#define TAG_MAX_APERTURE_VALUE 0x9205
+#define TAG_SUBJECT_DISTANCE 0x9206
+#define TAG_METERING_MODE 0x9207
+#define TAG_LIGHT_SOURCE 0x9208
+#define TAG_FLASH 0x9209
+#define TAG_FOCAL_LENGTH 0x920A
+#define TAG_SUBJECT_AREA 0x9214
+#define TAG_FLASH_ENERGY 0xA20B
+#define TAG_SPATIAL_FREQ_RESPONSE 0xA20C
+#define TAG_FOCAL_PLANE_X_RES 0xA20E
+#define TAG_FOCAL_PLANE_Y_RES 0xA20F
+#define TAG_FOCAL_PLANE_UNIT 0xA210
+#define TAG_SUBJECT_LOCATION 0xA214
+#define TAG_EXPOSURE_INDEX 0xA215
+#define TAG_SENSING_METHOD 0xA217
+#define TAG_FILE_SOURCE 0xA300
+#define TAG_SCENE_TYPE 0xA301
+#define TAG_CFA_PATTERN 0xA302
+#define TAG_CUSTOM_RENDERED 0xA401
+#define TAG_EXPOSURE_MODE 0xA402
+#define TAG_WHITE_BALANCE 0xA403
+#define TAG_DIGITAL_ZOOM_RATIO 0xA404
+#define TAG_FOCAL_LENGTH_IN_35MM_FILM 0xA405
+#define TAG_SCENE_CAPTURE_TYPE 0xA406
+#define TAG_GAIN_CONTROL 0xA407
+#define TAG_CONTRAST 0xA408
+#define TAG_SATURATION 0xA409
+#define TAG_SHARPNESS 0xA40A
+#define TAG_DEVICE_SETTING_DESCRIPTION 0xA40B
+#define TAG_SUBJECT_DISTANCE_RANGE 0xA40C
+
+// Other tags
+
+#define TAG_IMAGE_UNIQUE_ID 0xA420
+
+// ----------------------------------------------------------
+// GPS Attribute Information
+// ----------------------------------------------------------
+
+#define TAG_GPS_VERSION_ID 0x0000
+#define TAG_GPS_LATITUDE_REF 0x0001
+#define TAG_GPS_LATITUDE 0x0002
+#define TAG_GPS_LONGITUDE_REF 0x0003
+#define TAG_GPS_LONGITUDE 0x0004
+#define TAG_GPS_ALTITUDE_REF 0x0005
+#define TAG_GPS_ALTITUDE 0x0006
+#define TAG_GPS_TIME_STAMP 0x0007
+#define TAG_GPS_SATELLITES 0x0008
+#define TAG_GPS_STATUS 0x0009
+#define TAG_GPS_MEASURE_MODE 0x000A
+#define TAG_GPS_DOP 0x000B
+#define TAG_GPS_SPEED_REF 0x000C
+#define TAG_GPS_SPEED 0x000D
+#define TAG_GPS_TRACK_REF 0x000E
+#define TAG_GPS_TRACK 0x000F
+#define TAG_GPS_IMG_DIRECTION_REF 0x0010
+#define TAG_GPS_IMG_DIRECTION 0x0011
+#define TAG_GPS_MAP_DATUM 0x0012
+#define TAG_GPS_DEST_LATITUDE_REF 0x0013
+#define TAG_GPS_DEST_LATITUDE 0x0014
+#define TAG_GPS_DEST_LONGITUDE_REF 0x0015
+#define TAG_GPS_DEST_LONGITUDE 0x0016
+#define TAG_GPS_DEST_BEARING_REF 0x0017
+#define TAG_GPS_DEST_BEARING 0x0018
+#define TAG_GPS_DEST_DISTANCE_REF 0x0019
+#define TAG_GPS_DEST_DISTANCE 0x001A
+#define TAG_GPS_PROCESSING_METHOD 0x001B
+#define TAG_GPS_AREA_INFORMATION 0x001C
+#define TAG_GPS_DATE_STAMP 0x001D
+#define TAG_GPS_DIFFERENTIAL 0x001E
+
+// ==========================================================
+// IPTC/NAA tags
+// ==========================================================
+
+#define TAG_RECORD_VERSION 0x0200
+#define TAG_CAPTION 0x0278
+#define TAG_WRITER 0x027A
+#define TAG_HEADLINE 0x0269
+#define TAG_SPECIAL_INSTRUCTIONS 0x0228
+#define TAG_BY_LINE 0x0250
+#define TAG_BY_LINE_TITLE 0x0255
+#define TAG_CREDIT 0x026E
+#define TAG_SOURCE 0x0273
+#define TAG_OBJECT_NAME 0x0205
+#define TAG_DATE_CREATED 0x0237
+#define TAG_CITY 0x025A
+#define TAG_PROVINCE_OR_STATE 0x025F
+#define TAG_COUNTRY_OR_PRIMARY_LOCATION 0x0265
+#define TAG_ORIGINAL_TRANSMISSION_REFERENCE 0x0267
+#define TAG_CATEGORY 0x020F
+#define TAG_SUPPLEMENTAL_CATEGORIES 0x0214
+#define TAG_URGENCY 0x020A
+#define TAG_KEYWORDS 0x0219
+#define TAG_COPYRIGHT_NOTICE 0x0274
+#define TAG_RELEASE_DATE 0x021E
+#define TAG_RELEASE_TIME 0x0223
+#define TAG_TIME_CREATED 0x023C
+#define TAG_ORIGINATING_PROGRAM 0x0241
+
+// ==========================================================
+// GeoTIFF tags
+// ==========================================================
+
+// tags 33550 is a private tag registered to SoftDesk, Inc
+#define TIFFTAG_GEOPIXELSCALE 33550
+// tags 33920-33921 are private tags registered to Intergraph, Inc
+#define TIFFTAG_INTERGRAPH_MATRIX 33920
+#define TIFFTAG_GEOTIEPOINTS 33922
+// tags 34263-34264 are private tags registered to NASA-JPL Carto Group
+#define TIFFTAG_JPL_CARTO_IFD 34263
+#define TIFFTAG_GEOTRANSMATRIX 34264 /* New Matrix Tag replaces 33920 */
+// tags 34735-3438 are private tags registered to SPOT Image, Inc
+#define TIFFTAG_GEOKEYDIRECTORY 34735
+#define TIFFTAG_GEODOUBLEPARAMS 34736
+#define TIFFTAG_GEOASCIIPARAMS 34737
+
+// ==========================================================
+// FreeImage Animation tags
+// ==========================================================
+
+#define ANIMTAG_LOGICALWIDTH 0x0001
+#define ANIMTAG_LOGICALHEIGHT 0x0002
+#define ANIMTAG_GLOBALPALETTE 0x0003
+#define ANIMTAG_LOOP 0x0004
+#define ANIMTAG_FRAMELEFT 0x1001
+#define ANIMTAG_FRAMETOP 0x1002
+#define ANIMTAG_NOLOCALPALETTE 0x1003
+#define ANIMTAG_INTERLACED 0x1004
+#define ANIMTAG_FRAMETIME 0x1005
+#define ANIMTAG_DISPOSALMETHOD 0x1006
+
+// --------------------------------------------------------------------------
+// Helper functions to deal with the FITAG structure
+// --------------------------------------------------------------------------
+
+/**
+Describes the tag format descriptor
+@param type Tag data type
+@return Returns the width of a single element, in bytes
+@see FREE_IMAGE_MDTYPE
+*/
+unsigned FreeImage_TagDataWidth(FREE_IMAGE_MDTYPE type);
+
+// --------------------------------------------------------------------------
+
+/**
+ Structure to hold a tag information
+*/
+typedef struct tagTagInfo {
+ WORD tag; // Tag ID (required)
+ char *fieldname; // Field name (required)
+ char *description; // Field description (may be NULL)
+} TagInfo;
+
+
+/**
+ Class to hold tag information (based on Meyers’ Singleton).<br>
+
+ Sample usage :<br>
+ <code>
+ TagLib& s = TagLib::instance();
+ TagInfo *tag_info = s.getTagInfo(EXIF_MAIN, 0x0100);
+ </code>
+
+*/
+
+class TagLib {
+public:
+
+ /**
+ internal tag info tables registered in TagLib
+ */
+ enum MDMODEL {
+ UNKNOWN,
+ EXIF_MAIN,
+ EXIF_EXIF,
+ EXIF_GPS,
+ EXIF_INTEROP,
+ EXIF_MAKERNOTE_CANON,
+ EXIF_MAKERNOTE_CASIOTYPE1,
+ EXIF_MAKERNOTE_CASIOTYPE2,
+ EXIF_MAKERNOTE_FUJIFILM,
+ EXIF_MAKERNOTE_KYOCERA,
+ EXIF_MAKERNOTE_MINOLTA,
+ EXIF_MAKERNOTE_NIKONTYPE1,
+ EXIF_MAKERNOTE_NIKONTYPE2,
+ EXIF_MAKERNOTE_NIKONTYPE3,
+ EXIF_MAKERNOTE_OLYMPUSTYPE1,
+ EXIF_MAKERNOTE_PANASONIC,
+ EXIF_MAKERNOTE_ASAHI,
+ EXIF_MAKERNOTE_PENTAX,
+ EXIF_MAKERNOTE_SONY,
+ EXIF_MAKERNOTE_SIGMA_SD1,
+ EXIF_MAKERNOTE_SIGMA_FOVEON,
+ IPTC,
+ GEOTIFF,
+ ANIMATION
+ };
+
+private:
+
+ typedef std::map<WORD, TagInfo*> TAGINFO;
+ typedef std::map<int, TAGINFO*> TABLEMAP;
+
+ /// store hash tables for all known tag info tables
+ TABLEMAP _table_map;
+
+private:
+ /**
+ Constructor (private)<br>
+ This is where the tag info tables are initialized.
+ @see addMetadataModel
+ */
+ TagLib();
+
+ /// Assignement operator (disabled)
+ void operator=(TagLib&);
+
+ /// Copy constructor (disabled)
+ TagLib(const TagLib&);
+
+ /**
+ Used in the constructor to initialize the tag tables
+ @param md_model Internal metadata model
+ @param tag_table Tag info table
+ @return Returns TRUE if successful, returns FALSE otherwise
+ */
+ BOOL addMetadataModel(MDMODEL md_model, TagInfo *tag_table);
+
+public:
+ /// Destructor
+ ~TagLib();
+
+ /**
+ @return Returns a reference to the TagLib instance
+ */
+ static TagLib& instance();
+
+ /**
+ Given a tag ID, returns its TagInfo descriptor
+ @param md_model Internal metadata model
+ @param tagID tag ID
+ @return Returns the TagInfo descriptor if successful, returns NULL otherwise
+ */
+ const TagInfo* getTagInfo(MDMODEL md_model, WORD tagID);
+
+ /**
+ Given a tag ID, returns its tag field name.
+ When the tag is unknown and defaultKey is not NULL, a string such as "Tag 0x1234" is returned.
+ This string is contained in the provided defaultKey buffer (assumed to be an array of at least 16 chars).
+ @param md_model Internal metadata model
+ @param tagID tag ID
+ @param defaultKey Assumed to be an array of 16 chars. If not NULL, build a key for unknown tags
+ @return Returns the tag field name if successful, returns an 'unknown tag' string contained in defaultKey otherwise
+ */
+ const char* getTagFieldName(MDMODEL md_model, WORD tagID, char *defaultKey);
+
+ /**
+ Given a tag ID, returns its description.
+ When the tag has no description, a NULL value is returned.
+ @param md_model Internal metadata model
+ @param tagID tag ID
+ @return Returns the tag description if successful, returns NULL otherwise
+ */
+ const char* getTagDescription(MDMODEL md_model, WORD tagID);
+
+ /**
+ Given a tag field name, returns its tag ID.
+ When the tag doesn't exists, a value '-1' is returned.
+ @param md_model Internal metadata model
+ @param key tag field name
+ @return Returns the tag ID if successful, returns -1 otherwise
+ */
+ int getTagID(MDMODEL md_model, const char *key);
+
+ /**
+ Perform a conversion between internal metadata models and FreeImage public metadata models
+ @param md_model Internal metadata model
+ */
+ FREE_IMAGE_MDMODEL getFreeImageModel(MDMODEL model);
+
+};
+
+// --------------------------------------------------------------------------
+// Constant strings
+// --------------------------------------------------------------------------
+
+/// Name of the XMP field
+static const char *g_TagLib_XMPFieldName = "XMLPacket";
+
+/// Name of the Exif raw field
+static const char *g_TagLib_ExifRawFieldName = "ExifRaw";
+
+// --------------------------------------------------------------------------
+// Metadata routines
+// --------------------------------------------------------------------------
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+// JPEG Exif profile
+BOOL jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen);
+
+// JPEG / TIFF IPTC profile
+BOOL read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen);
+BOOL write_iptc_profile(FIBITMAP *dib, BYTE **profile, unsigned *profile_size);
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif // FREEIMAGETAG_H
+
+
diff --git a/plugins/FreeImage/Source/Metadata/IPTC.cpp b/plugins/FreeImage/Source/Metadata/IPTC.cpp
index 8bfb1b18c7..1aba46c094 100644
--- a/plugins/FreeImage/Source/Metadata/IPTC.cpp
+++ b/plugins/FreeImage/Source/Metadata/IPTC.cpp
@@ -1,325 +1,325 @@
-// ==========================================================
-// Metadata functions implementation
-//
-// Design and implementation by
-// - Hervé Drolon (drolon@infonie.fr)
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#ifdef _MSC_VER
-#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
-#endif
-
-#include "FreeImage.h"
-#include "Utilities.h"
-#include "FreeImageTag.h"
-
-// ----------------------------------------------------------
-// IPTC JPEG / TIFF markers routines
-// ----------------------------------------------------------
-
-static const char* IPTC_DELIMITER = ";"; // keywords/supplemental category delimiter
-/**
- Read and decode IPTC binary data
-*/
-BOOL
-read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
- char defaultKey[16];
- size_t length = datalen;
- BYTE *profile = (BYTE*)dataptr;
-
- std::string Keywords;
- std::string SupplementalCategory;
-
- WORD tag_id;
-
- if(!dataptr || (datalen == 0)) {
- return FALSE;
- }
-
- // create a tag
-
- FITAG *tag = FreeImage_CreateTag();
-
- TagLib& tag_lib = TagLib::instance();
-
- // find start of the BIM portion of the binary data
- size_t offset = 0;
- while(offset < length - 1) {
- if((profile[offset] == 0x1C) && (profile[offset+1] == 0x02))
- break;
- offset++;
- }
-
- // for each tag
- while (offset < length) {
-
- // identifies start of a tag
- if (profile[offset] != 0x1c) {
- break;
- }
- // we need at least five bytes left to read a tag
- if ((offset + 5) >= length) {
- break;
- }
-
- offset++;
-
- int directoryType = profile[offset++];
- int tagType = profile[offset++];;
- int tagByteCount = ((profile[offset] & 0xFF) << 8) | (profile[offset + 1] & 0xFF);
- offset += 2;
-
- if ((offset + tagByteCount) > length) {
- // data for tag extends beyond end of iptc segment
- break;
- }
-
- // process the tag
-
- tag_id = (WORD)(tagType | (directoryType << 8));
-
- FreeImage_SetTagID(tag, tag_id);
- FreeImage_SetTagLength(tag, tagByteCount);
-
- // allocate a buffer to store the tag value
- BYTE *iptc_value = (BYTE*)malloc((tagByteCount + 1) * sizeof(BYTE));
- memset(iptc_value, 0, (tagByteCount + 1) * sizeof(BYTE));
-
- // get the tag value
-
- switch (tag_id) {
- case TAG_RECORD_VERSION:
- {
- // short
- FreeImage_SetTagType(tag, FIDT_SSHORT);
- FreeImage_SetTagCount(tag, 1);
- short *pvalue = (short*)&iptc_value[0];
- *pvalue = (short)((profile[offset] << 8) | profile[offset + 1]);
- FreeImage_SetTagValue(tag, pvalue);
- break;
- }
-
- case TAG_RELEASE_DATE:
- case TAG_DATE_CREATED:
- // Date object
- case TAG_RELEASE_TIME:
- case TAG_TIME_CREATED:
- // time
- default:
- {
- // string
- FreeImage_SetTagType(tag, FIDT_ASCII);
- FreeImage_SetTagCount(tag, tagByteCount);
- for(int i = 0; i < tagByteCount; i++) {
- iptc_value[i] = profile[offset + i];
- }
- iptc_value[tagByteCount] = '\0';
- FreeImage_SetTagValue(tag, (char*)&iptc_value[0]);
- break;
- }
- }
-
- if(tag_id == TAG_SUPPLEMENTAL_CATEGORIES) {
- // concatenate the categories
- if(SupplementalCategory.length() == 0) {
- SupplementalCategory.append((char*)iptc_value);
- } else {
- SupplementalCategory.append(IPTC_DELIMITER);
- SupplementalCategory.append((char*)iptc_value);
- }
- }
- else if(tag_id == TAG_KEYWORDS) {
- // concatenate the keywords
- if(Keywords.length() == 0) {
- Keywords.append((char*)iptc_value);
- } else {
- Keywords.append(IPTC_DELIMITER);
- Keywords.append((char*)iptc_value);
- }
- }
- else {
- // get the tag key and description
- const char *key = tag_lib.getTagFieldName(TagLib::IPTC, tag_id, defaultKey);
- FreeImage_SetTagKey(tag, key);
- const char *description = tag_lib.getTagDescription(TagLib::IPTC, tag_id);
- FreeImage_SetTagDescription(tag, description);
-
- // store the tag
- if(key) {
- FreeImage_SetMetadata(FIMD_IPTC, dib, key, tag);
- }
- }
-
- free(iptc_value);
-
- // next tag
- offset += tagByteCount;
-
- }
-
- // store the 'keywords' tag
- if(Keywords.length()) {
- FreeImage_SetTagType(tag, FIDT_ASCII);
- FreeImage_SetTagID(tag, TAG_KEYWORDS);
- FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::IPTC, TAG_KEYWORDS, defaultKey));
- FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::IPTC, TAG_KEYWORDS));
- FreeImage_SetTagLength(tag, (DWORD)Keywords.length());
- FreeImage_SetTagCount(tag, (DWORD)Keywords.length());
- FreeImage_SetTagValue(tag, (char*)Keywords.c_str());
- FreeImage_SetMetadata(FIMD_IPTC, dib, FreeImage_GetTagKey(tag), tag);
- }
-
- // store the 'supplemental category' tag
- if(SupplementalCategory.length()) {
- FreeImage_SetTagType(tag, FIDT_ASCII);
- FreeImage_SetTagID(tag, TAG_SUPPLEMENTAL_CATEGORIES);
- FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::IPTC, TAG_SUPPLEMENTAL_CATEGORIES, defaultKey));
- FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::IPTC, TAG_SUPPLEMENTAL_CATEGORIES));
- FreeImage_SetTagLength(tag, (DWORD)SupplementalCategory.length());
- FreeImage_SetTagCount(tag, (DWORD)SupplementalCategory.length());
- FreeImage_SetTagValue(tag, (char*)SupplementalCategory.c_str());
- FreeImage_SetMetadata(FIMD_IPTC, dib, FreeImage_GetTagKey(tag), tag);
- }
-
- // delete the tag
-
- FreeImage_DeleteTag(tag);
-
- return TRUE;
-}
-
-// --------------------------------------------------------------------------
-
-static BYTE*
-append_iptc_tag(BYTE *profile, unsigned *profile_size, WORD id, DWORD length, const void *value) {
- BYTE *buffer = NULL;
-
- // calculate the new buffer size
- size_t buffer_size = (5 + *profile_size + length) * sizeof(BYTE);
- buffer = (BYTE*)malloc(buffer_size);
- if(!buffer)
- return NULL;
-
- // add the header
- buffer[0] = 0x1C;
- buffer[1] = 0x02;
- // add the tag type
- buffer[2] = (BYTE)(id & 0x00FF);
- // add the tag length
- buffer[3] = (BYTE)(length >> 8);
- buffer[4] = (BYTE)(length & 0xFF);
- // add the tag value
- memcpy(buffer + 5, (BYTE*)value, length);
- // append the previous profile
- if(NULL == profile) {
- *profile_size = (5 + length);
- }
- else {
- memcpy(buffer + 5 + length, profile, *profile_size);
- *profile_size += (5 + length);
- free(profile);
- }
-
- return buffer;
-}
-
-/**
-Encode IPTC metadata into a binary buffer.
-The buffer is allocated by the function and must be freed by the caller.
-*/
-BOOL
-write_iptc_profile(FIBITMAP *dib, BYTE **profile, unsigned *profile_size) {
- FITAG *tag = NULL;
- FIMETADATA *mdhandle = NULL;
-
- BYTE *buffer = NULL;
- unsigned buffer_size = 0;
-
- // parse all IPTC tags and rebuild a IPTC profile
- mdhandle = FreeImage_FindFirstMetadata(FIMD_IPTC, dib, &tag);
-
- if(mdhandle) {
- do {
- WORD tag_id = FreeImage_GetTagID(tag);
-
- // append the tag to the profile
-
- switch(tag_id) {
- case TAG_RECORD_VERSION:
- // ignore (already handled)
- break;
-
- case TAG_SUPPLEMENTAL_CATEGORIES:
- case TAG_KEYWORDS:
- if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
- std::string value = (const char*)FreeImage_GetTagValue(tag);
-
- // split the tag value
- std::vector<std::string> output;
- std::string delimiter = IPTC_DELIMITER;
-
- size_t offset = 0;
- size_t delimiterIndex = 0;
-
- delimiterIndex = value.find(delimiter, offset);
- while (delimiterIndex != std::string::npos) {
- output.push_back(value.substr(offset, delimiterIndex - offset));
- offset += delimiterIndex - offset + delimiter.length();
- delimiterIndex = value.find(delimiter, offset);
- }
- output.push_back(value.substr(offset));
-
- // add as many tags as there are comma separated strings
- for(int i = 0; i < (int)output.size(); i++) {
- std::string& tag_value = output[i];
- buffer = append_iptc_tag(buffer, &buffer_size, tag_id, (DWORD)tag_value.length(), tag_value.c_str());
- }
-
- }
- break;
-
- case TAG_URGENCY:
- if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
- DWORD length = 1; // keep the first octet only
- buffer = append_iptc_tag(buffer, &buffer_size, tag_id, length, FreeImage_GetTagValue(tag));
- }
- break;
-
- default:
- if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
- DWORD length = FreeImage_GetTagLength(tag);
- buffer = append_iptc_tag(buffer, &buffer_size, tag_id, length, FreeImage_GetTagValue(tag));
- }
- break;
- }
-
- } while(FreeImage_FindNextMetadata(mdhandle, &tag));
-
- FreeImage_FindCloseMetadata(mdhandle);
-
- // add the DirectoryVersion tag
- const short version = 0x0200;
- buffer = append_iptc_tag(buffer, &buffer_size, TAG_RECORD_VERSION, sizeof(version), &version);
-
- *profile = buffer;
- *profile_size = buffer_size;
-
- return TRUE;
- }
-
- return FALSE;
-}
+// ==========================================================
+// Metadata functions implementation
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageTag.h"
+
+// ----------------------------------------------------------
+// IPTC JPEG / TIFF markers routines
+// ----------------------------------------------------------
+
+static const char* IPTC_DELIMITER = ";"; // keywords/supplemental category delimiter
+/**
+ Read and decode IPTC binary data
+*/
+BOOL
+read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
+ char defaultKey[16];
+ size_t length = datalen;
+ BYTE *profile = (BYTE*)dataptr;
+
+ std::string Keywords;
+ std::string SupplementalCategory;
+
+ WORD tag_id;
+
+ if(!dataptr || (datalen == 0)) {
+ return FALSE;
+ }
+
+ // create a tag
+
+ FITAG *tag = FreeImage_CreateTag();
+
+ TagLib& tag_lib = TagLib::instance();
+
+ // find start of the BIM portion of the binary data
+ size_t offset = 0;
+ while(offset < length - 1) {
+ if((profile[offset] == 0x1C) && (profile[offset+1] == 0x02))
+ break;
+ offset++;
+ }
+
+ // for each tag
+ while (offset < length) {
+
+ // identifies start of a tag
+ if (profile[offset] != 0x1c) {
+ break;
+ }
+ // we need at least five bytes left to read a tag
+ if ((offset + 5) >= length) {
+ break;
+ }
+
+ offset++;
+
+ int directoryType = profile[offset++];
+ int tagType = profile[offset++];;
+ int tagByteCount = ((profile[offset] & 0xFF) << 8) | (profile[offset + 1] & 0xFF);
+ offset += 2;
+
+ if ((offset + tagByteCount) > length) {
+ // data for tag extends beyond end of iptc segment
+ break;
+ }
+
+ // process the tag
+
+ tag_id = (WORD)(tagType | (directoryType << 8));
+
+ FreeImage_SetTagID(tag, tag_id);
+ FreeImage_SetTagLength(tag, tagByteCount);
+
+ // allocate a buffer to store the tag value
+ BYTE *iptc_value = (BYTE*)malloc((tagByteCount + 1) * sizeof(BYTE));
+ memset(iptc_value, 0, (tagByteCount + 1) * sizeof(BYTE));
+
+ // get the tag value
+
+ switch (tag_id) {
+ case TAG_RECORD_VERSION:
+ {
+ // short
+ FreeImage_SetTagType(tag, FIDT_SSHORT);
+ FreeImage_SetTagCount(tag, 1);
+ short *pvalue = (short*)&iptc_value[0];
+ *pvalue = (short)((profile[offset] << 8) | profile[offset + 1]);
+ FreeImage_SetTagValue(tag, pvalue);
+ break;
+ }
+
+ case TAG_RELEASE_DATE:
+ case TAG_DATE_CREATED:
+ // Date object
+ case TAG_RELEASE_TIME:
+ case TAG_TIME_CREATED:
+ // time
+ default:
+ {
+ // string
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagCount(tag, tagByteCount);
+ for(int i = 0; i < tagByteCount; i++) {
+ iptc_value[i] = profile[offset + i];
+ }
+ iptc_value[tagByteCount] = '\0';
+ FreeImage_SetTagValue(tag, (char*)&iptc_value[0]);
+ break;
+ }
+ }
+
+ if(tag_id == TAG_SUPPLEMENTAL_CATEGORIES) {
+ // concatenate the categories
+ if(SupplementalCategory.length() == 0) {
+ SupplementalCategory.append((char*)iptc_value);
+ } else {
+ SupplementalCategory.append(IPTC_DELIMITER);
+ SupplementalCategory.append((char*)iptc_value);
+ }
+ }
+ else if(tag_id == TAG_KEYWORDS) {
+ // concatenate the keywords
+ if(Keywords.length() == 0) {
+ Keywords.append((char*)iptc_value);
+ } else {
+ Keywords.append(IPTC_DELIMITER);
+ Keywords.append((char*)iptc_value);
+ }
+ }
+ else {
+ // get the tag key and description
+ const char *key = tag_lib.getTagFieldName(TagLib::IPTC, tag_id, defaultKey);
+ FreeImage_SetTagKey(tag, key);
+ const char *description = tag_lib.getTagDescription(TagLib::IPTC, tag_id);
+ FreeImage_SetTagDescription(tag, description);
+
+ // store the tag
+ if(key) {
+ FreeImage_SetMetadata(FIMD_IPTC, dib, key, tag);
+ }
+ }
+
+ free(iptc_value);
+
+ // next tag
+ offset += tagByteCount;
+
+ }
+
+ // store the 'keywords' tag
+ if(Keywords.length()) {
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagID(tag, TAG_KEYWORDS);
+ FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::IPTC, TAG_KEYWORDS, defaultKey));
+ FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::IPTC, TAG_KEYWORDS));
+ FreeImage_SetTagLength(tag, (DWORD)Keywords.length());
+ FreeImage_SetTagCount(tag, (DWORD)Keywords.length());
+ FreeImage_SetTagValue(tag, (char*)Keywords.c_str());
+ FreeImage_SetMetadata(FIMD_IPTC, dib, FreeImage_GetTagKey(tag), tag);
+ }
+
+ // store the 'supplemental category' tag
+ if(SupplementalCategory.length()) {
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagID(tag, TAG_SUPPLEMENTAL_CATEGORIES);
+ FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::IPTC, TAG_SUPPLEMENTAL_CATEGORIES, defaultKey));
+ FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::IPTC, TAG_SUPPLEMENTAL_CATEGORIES));
+ FreeImage_SetTagLength(tag, (DWORD)SupplementalCategory.length());
+ FreeImage_SetTagCount(tag, (DWORD)SupplementalCategory.length());
+ FreeImage_SetTagValue(tag, (char*)SupplementalCategory.c_str());
+ FreeImage_SetMetadata(FIMD_IPTC, dib, FreeImage_GetTagKey(tag), tag);
+ }
+
+ // delete the tag
+
+ FreeImage_DeleteTag(tag);
+
+ return TRUE;
+}
+
+// --------------------------------------------------------------------------
+
+static BYTE*
+append_iptc_tag(BYTE *profile, unsigned *profile_size, WORD id, DWORD length, const void *value) {
+ BYTE *buffer = NULL;
+
+ // calculate the new buffer size
+ size_t buffer_size = (5 + *profile_size + length) * sizeof(BYTE);
+ buffer = (BYTE*)malloc(buffer_size);
+ if(!buffer)
+ return NULL;
+
+ // add the header
+ buffer[0] = 0x1C;
+ buffer[1] = 0x02;
+ // add the tag type
+ buffer[2] = (BYTE)(id & 0x00FF);
+ // add the tag length
+ buffer[3] = (BYTE)(length >> 8);
+ buffer[4] = (BYTE)(length & 0xFF);
+ // add the tag value
+ memcpy(buffer + 5, (BYTE*)value, length);
+ // append the previous profile
+ if(NULL == profile) {
+ *profile_size = (5 + length);
+ }
+ else {
+ memcpy(buffer + 5 + length, profile, *profile_size);
+ *profile_size += (5 + length);
+ free(profile);
+ }
+
+ return buffer;
+}
+
+/**
+Encode IPTC metadata into a binary buffer.
+The buffer is allocated by the function and must be freed by the caller.
+*/
+BOOL
+write_iptc_profile(FIBITMAP *dib, BYTE **profile, unsigned *profile_size) {
+ FITAG *tag = NULL;
+ FIMETADATA *mdhandle = NULL;
+
+ BYTE *buffer = NULL;
+ unsigned buffer_size = 0;
+
+ // parse all IPTC tags and rebuild a IPTC profile
+ mdhandle = FreeImage_FindFirstMetadata(FIMD_IPTC, dib, &tag);
+
+ if(mdhandle) {
+ do {
+ WORD tag_id = FreeImage_GetTagID(tag);
+
+ // append the tag to the profile
+
+ switch(tag_id) {
+ case TAG_RECORD_VERSION:
+ // ignore (already handled)
+ break;
+
+ case TAG_SUPPLEMENTAL_CATEGORIES:
+ case TAG_KEYWORDS:
+ if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
+ std::string value = (const char*)FreeImage_GetTagValue(tag);
+
+ // split the tag value
+ std::vector<std::string> output;
+ std::string delimiter = IPTC_DELIMITER;
+
+ size_t offset = 0;
+ size_t delimiterIndex = 0;
+
+ delimiterIndex = value.find(delimiter, offset);
+ while (delimiterIndex != std::string::npos) {
+ output.push_back(value.substr(offset, delimiterIndex - offset));
+ offset += delimiterIndex - offset + delimiter.length();
+ delimiterIndex = value.find(delimiter, offset);
+ }
+ output.push_back(value.substr(offset));
+
+ // add as many tags as there are comma separated strings
+ for(int i = 0; i < (int)output.size(); i++) {
+ std::string& tag_value = output[i];
+ buffer = append_iptc_tag(buffer, &buffer_size, tag_id, (DWORD)tag_value.length(), tag_value.c_str());
+ }
+
+ }
+ break;
+
+ case TAG_URGENCY:
+ if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
+ DWORD length = 1; // keep the first octet only
+ buffer = append_iptc_tag(buffer, &buffer_size, tag_id, length, FreeImage_GetTagValue(tag));
+ }
+ break;
+
+ default:
+ if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
+ DWORD length = FreeImage_GetTagLength(tag);
+ buffer = append_iptc_tag(buffer, &buffer_size, tag_id, length, FreeImage_GetTagValue(tag));
+ }
+ break;
+ }
+
+ } while(FreeImage_FindNextMetadata(mdhandle, &tag));
+
+ FreeImage_FindCloseMetadata(mdhandle);
+
+ // add the DirectoryVersion tag
+ const short version = 0x0200;
+ buffer = append_iptc_tag(buffer, &buffer_size, TAG_RECORD_VERSION, sizeof(version), &version);
+
+ *profile = buffer;
+ *profile_size = buffer_size;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/plugins/FreeImage/Source/Metadata/TagConversion.cpp b/plugins/FreeImage/Source/Metadata/TagConversion.cpp
index 096ab7ec58..041ba9a747 100644
--- a/plugins/FreeImage/Source/Metadata/TagConversion.cpp
+++ b/plugins/FreeImage/Source/Metadata/TagConversion.cpp
@@ -194,6 +194,46 @@ ConvertAnyTag(FITAG *tag) {
}
break;
}
+
+ case FIDT_LONG8: // N x 64-bit unsigned integer
+ {
+ FIUINT64 *pvalue = (FIUINT64 *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%ld", pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, "%ld", pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+
+ case FIDT_IFD8: // N x 64-bit unsigned integer (offset)
+ {
+ FIUINT64 *pvalue = (FIUINT64 *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%X", pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, "%X", pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+
+ case FIDT_SLONG8: // N x 64-bit signed integer
+ {
+ FIINT64 *pvalue = (FIINT64 *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%ld", pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, "%ld", pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+
case FIDT_ASCII: // 8-bit bytes w/ last byte null
case FIDT_UNDEFINED:// 8-bit untyped data
default:
@@ -295,7 +335,7 @@ ConvertExifTag(FITAG *tag) {
case TAG_COMPONENTS_CONFIGURATION:
{
- char *componentStrings[7] = {"", "Y", "Cb", "Cr", "R", "G", "B"};
+ const char *componentStrings[7] = {"", "Y", "Cb", "Cr", "R", "G", "B"};
BYTE *pvalue = (BYTE*)FreeImage_GetTagValue(tag);
for(DWORD i = 0; i < MIN((DWORD)4, FreeImage_GetTagCount(tag)); i++) {
int j = pvalue[i];
@@ -854,6 +894,92 @@ ConvertExifTag(FITAG *tag) {
}
break;
+ case TAG_COMPRESSION:
+ {
+ WORD compression = *((WORD*)FreeImage_GetTagValue(tag));
+ switch(compression) {
+ case TAG_COMPRESSION_NONE:
+ sprintf(format, "dump mode (%d)", compression);
+ break;
+ case TAG_COMPRESSION_CCITTRLE:
+ sprintf(format, "CCITT modified Huffman RLE (%d)", compression);
+ break;
+ case TAG_COMPRESSION_CCITTFAX3:
+ sprintf(format, "CCITT Group 3 fax encoding (%d)", compression);
+ break;
+ /*
+ case TAG_COMPRESSION_CCITT_T4:
+ sprintf(format, "CCITT T.4 (TIFF 6 name) (%d)", compression);
+ break;
+ */
+ case TAG_COMPRESSION_CCITTFAX4:
+ sprintf(format, "CCITT Group 4 fax encoding (%d)", compression);
+ break;
+ /*
+ case TAG_COMPRESSION_CCITT_T6:
+ sprintf(format, "CCITT T.6 (TIFF 6 name) (%d)", compression);
+ break;
+ */
+ case TAG_COMPRESSION_LZW:
+ sprintf(format, "LZW (%d)", compression);
+ break;
+ case TAG_COMPRESSION_OJPEG:
+ sprintf(format, "!6.0 JPEG (%d)", compression);
+ break;
+ case TAG_COMPRESSION_JPEG:
+ sprintf(format, "JPEG (%d)", compression);
+ break;
+ case TAG_COMPRESSION_NEXT:
+ sprintf(format, "NeXT 2-bit RLE (%d)", compression);
+ break;
+ case TAG_COMPRESSION_CCITTRLEW:
+ sprintf(format, "CCITTRLEW (%d)", compression);
+ break;
+ case TAG_COMPRESSION_PACKBITS:
+ sprintf(format, "PackBits Macintosh RLE (%d)", compression);
+ break;
+ case TAG_COMPRESSION_THUNDERSCAN:
+ sprintf(format, "ThunderScan RLE (%d)", compression);
+ break;
+ case TAG_COMPRESSION_PIXARFILM:
+ sprintf(format, "Pixar companded 10bit LZW (%d)", compression);
+ break;
+ case TAG_COMPRESSION_PIXARLOG:
+ sprintf(format, "Pixar companded 11bit ZIP (%d)", compression);
+ break;
+ case TAG_COMPRESSION_DEFLATE:
+ sprintf(format, "Deflate compression (%d)", compression);
+ break;
+ case TAG_COMPRESSION_ADOBE_DEFLATE:
+ sprintf(format, "Adobe Deflate compression (%d)", compression);
+ break;
+ case TAG_COMPRESSION_DCS:
+ sprintf(format, "Kodak DCS encoding (%d)", compression);
+ break;
+ case TAG_COMPRESSION_JBIG:
+ sprintf(format, "ISO JBIG (%d)", compression);
+ break;
+ case TAG_COMPRESSION_SGILOG:
+ sprintf(format, "SGI Log Luminance RLE (%d)", compression);
+ break;
+ case TAG_COMPRESSION_SGILOG24:
+ sprintf(format, "SGI Log 24-bit packed (%d)", compression);
+ break;
+ case TAG_COMPRESSION_JP2000:
+ sprintf(format, "Leadtools JPEG2000 (%d)", compression);
+ break;
+ case TAG_COMPRESSION_LZMA:
+ sprintf(format, "LZMA2 (%d)", compression);
+ break;
+ default:
+ sprintf(format, "Unknown type (%d)", compression);
+ break;
+ }
+
+ buffer += format;
+ return buffer.c_str();
+ }
+ break;
}
return ConvertAnyTag(tag);
diff --git a/plugins/FreeImage/Source/Metadata/TagLib.cpp b/plugins/FreeImage/Source/Metadata/TagLib.cpp
index 9e525e305c..123d860041 100644
--- a/plugins/FreeImage/Source/Metadata/TagLib.cpp
+++ b/plugins/FreeImage/Source/Metadata/TagLib.cpp
@@ -1,1376 +1,1617 @@
-// ==========================================================
-// Tag library
-//
-// Design and implementation by
-// - Hervé Drolon <drolon@infonie.fr>
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-// ==========================================================
-// Implementation notes :
-// ----------------------
-// The tag info tables declared in this file should probably
-// be loaded from an XML file.
-// This would allow internationalization features and also
-// more extensibility.
-// Maybe in a future release ?
-// ==========================================================
-
-#ifdef _MSC_VER
-#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
-#endif
-
-#include "FreeImage.h"
-#include "Utilities.h"
-#include "FreeImageTag.h"
-
-/**
- HOW-TO : add a new TagIngo table
- --------------------------------------------------------------------------
- 1) add a table identifier in the TagLib class definition (see enum MDMODEL)
- 2) declare the tag table as static and use a 0/NULL value as last entry
- 3) initialize the table in TagLib::TagLib
- 4) provide a conversion in TagLib::getFreeImageModel
-*/
-
-// --------------------------------------------------------------------------
-// EXIF standard tags definition
-// --------------------------------------------------------------------------
-
-static TagInfo
- exif_exif_tag_table[] =
- {
- { 0x0100, (char *) "ImageWidth", (char *) "Image width"},
- { 0x0101, (char *) "ImageLength", (char *) "Image height"},
- { 0x0102, (char *) "BitsPerSample", (char *) "Number of bits per component"},
- { 0x0103, (char *) "Compression", (char *) "Compression scheme"},
- { 0x0106, (char *) "PhotometricInterpretation", (char *) "Pixel composition"},
- { 0x010A, (char *) "FillOrder", (char*) NULL},
- { 0x010D, (char *) "DocumentName", (char *) NULL},
- { 0x010E, (char *) "ImageDescription", (char *) "Image title"},
- { 0x010F, (char *) "Make", (char *) "Image input equipment manufacturer"},
- { 0x0110, (char *) "Model", (char *) "Image input equipment model"},
- { 0x0111, (char *) "StripOffsets", (char *) "Image data location"},
- { 0x0112, (char *) "Orientation", (char *) "Orientation of image"},
- { 0x0115, (char *) "SamplesPerPixel", (char *) "Number of components"},
- { 0x0116, (char *) "RowsPerStrip", (char *) "Number of rows per strip"},
- { 0x0117, (char *) "StripByteCounts", (char *) "Bytes per compressed strip"},
- { 0x011A, (char *) "XResolution", (char *) "Image resolution in width direction"},
- { 0x011B, (char *) "YResolution", (char *) "Image resolution in height direction"},
- { 0x011C, (char *) "PlanarConfiguration", (char *) "Image data arrangement"},
- { 0x011D, (char *) "PageName", (char *) "Name of the page"},
- { 0x011E, (char *) "XPosition", (char *) "X position of the image"},
- { 0x011F, (char *) "YPosition", (char *) "Y position of the image"},
- { 0x0128, (char *) "ResolutionUnit", (char *) "Unit of X and Y resolution"},
- { 0x0129, (char *) "PageNumber", (char *) "Page number"},
- { 0x012D, (char *) "TransferFunction", (char *) "Transfer function"},
- { 0x0131, (char *) "Software", (char *) "Software used"},
- { 0x0132, (char *) "DateTime", (char *) "File change date and time"},
- { 0x013B, (char *) "Artist", (char *) "Person who created the image"},
- { 0x013C, (char *) "HostComputer", (char *) "Host computer used to generate the image"},
- { 0x013E, (char *) "WhitePoint", (char *) "White point chromaticity"},
- { 0x013F, (char *) "PrimaryChromaticities", (char *) "Chromaticities of primaries"},
- { 0x0156, (char *) "TransferRange", (char *) NULL},
- { 0x0200, (char *) "JPEGProc", (char *) NULL},
- { 0x0201, (char *) "JPEGInterchangeFormat", (char *) "Offset to JPEG SOI"},
- { 0x0202, (char *) "JPEGInterchangeFormatLength", (char *) "Bytes of JPEG data"},
- { 0x0211, (char *) "YCbCrCoefficients", (char *) "Color space transformation matrix coefficients"},
- { 0x0212, (char *) "YCbCrSubSampling", (char *) "Subsampling ratio of Y to C"},
- { 0x0213, (char *) "YCbCrPositioning", (char *) "Y and C positioning"},
- { 0x0214, (char *) "ReferenceBlackWhite", (char *) "Pair of black and white reference values"},
- { 0x828D, (char *) "CFARepeatPatternDim", (char *) NULL},
- { 0x828E, (char *) "CFAPattern", (char *) NULL},
- { 0x828F, (char *) "BatteryLevel", (char *) NULL},
- { 0x8298, (char *) "Copyright", (char *) "Copyright holder"},
- { 0x829A, (char *) "ExposureTime", (char *) "Exposure time"},
- { 0x829D, (char *) "FNumber", (char *) "F number"},
- { 0x83BB, (char *) "IPTC/NAA", (char *) NULL},
- { 0x8773, (char *) "InterColorProfile", (char *) NULL},
- { 0x8822, (char *) "ExposureProgram", (char *) "Exposure program"},
- { 0x8824, (char *) "SpectralSensitivity", (char *) "Spectral sensitivity"},
- { 0x8825, (char *) "GPSInfo", (char *) NULL},
- { 0x8827, (char *) "ISOSpeedRatings", (char *) "ISO speed rating"},
- { 0x8828, (char *) "OECF", (char *) "Optoelectric conversion factor"},
- { 0x9000, (char *) "ExifVersion", (char *) "Exif version"},
- { 0x9003, (char *) "DateTimeOriginal", (char *) "Date and time of original data generation"},
- { 0x9004, (char *) "DateTimeDigitized", (char *) "Date and time of digital data generation"},
- { 0x9101, (char *) "ComponentsConfiguration", (char *) "Meaning of each component"},
- { 0x9102, (char *) "CompressedBitsPerPixel", (char *) "Image compression mode"},
- { 0x9201, (char *) "ShutterSpeedValue", (char *) "Shutter speed"},
- { 0x9202, (char *) "ApertureValue", (char *) "Aperture"},
- { 0x9203, (char *) "BrightnessValue", (char *) "Brightness"},
- { 0x9204, (char *) "ExposureBiasValue", (char *) "Exposure bias"},
- { 0x9205, (char *) "MaxApertureValue", (char *) "Maximum lens aperture"},
- { 0x9206, (char *) "SubjectDistance", (char *) "Subject distance"},
- { 0x9207, (char *) "MeteringMode", (char *) "Metering mode"},
- { 0x9208, (char *) "LightSource", (char *) "Light source"},
- { 0x9209, (char *) "Flash", (char *) "Flash"},
- { 0x920A, (char *) "FocalLength", (char *) "Lens focal length"},
- { 0x9214, (char *) "SubjectArea", (char *) "Subject area"},
- { 0x927C, (char *) "MakerNote", (char *) "Manufacturer notes"},
- { 0x9286, (char *) "UserComment", (char *) "User comments"},
- { 0x9290, (char *) "SubSecTime", (char *) "DateTime subseconds"},
- { 0x9291, (char *) "SubSecTimeOriginal", (char *) "DateTimeOriginal subseconds"},
- { 0x9292, (char *) "SubSecTimeDigitized", (char *) "DateTimeDigitized subseconds"},
- { 0xA000, (char *) "FlashPixVersion", (char *) "Supported Flashpix version"},
- { 0xA001, (char *) "ColorSpace", (char *) "Color space information"},
- { 0xA002, (char *) "PixelXDimension", (char *) "Valid image width"},
- { 0xA003, (char *) "PixelYDimension", (char *) "Valid image height"},
- { 0xA004, (char *) "RelatedSoundFile", (char *) "Related audio file"},
- { 0xA005, (char *) "InteroperabilityOffset", (char *) NULL},
- { 0xA20B, (char *) "FlashEnergy", (char *) "Flash energy"},
- { 0xA20C, (char *) "SpatialFrequencyResponse", (char *) "Spatial frequency response"},
- { 0xA20E, (char *) "FocalPlaneXResolution", (char *) "Focal plane X resolution"},
- { 0xA20F, (char *) "FocalPlaneYResolution", (char *) "Focal plane Y resolution"},
- { 0xA210, (char *) "FocalPlaneResolutionUnit", (char *) "Focal plane resolution unit"},
- { 0xA214, (char *) "SubjectLocation", (char *) "Subject location"},
- { 0xA215, (char *) "ExposureIndex", (char *) "Exposure index"},
- { 0xA217, (char *) "SensingMethod", (char *) "Sensing method"},
- { 0xA300, (char *) "FileSrc", (char *) "File source"},
- { 0xA301, (char *) "SceneType", (char *) "Scene type"},
- { 0xA302, (char *) "CFAPattern", (char *) "CFA pattern"},
- { 0xA401, (char *) "CustomRendered", (char *) "Custom image processing"},
- { 0xA402, (char *) "ExposureMode", (char *) "Exposure mode"},
- { 0xA403, (char *) "WhiteBalance", (char *) "White balance"},
- { 0xA404, (char *) "DigitalZoomRatio", (char *) "Digital zoom ratio"},
- { 0xA405, (char *) "FocalLengthIn35mmFilm", (char *) "Focal length in 35 mm film"},
- { 0xA406, (char *) "SceneCaptureType", (char *) "Scene capture type"},
- { 0xA407, (char *) "GainControl", (char *) "Gain control"},
- { 0xA408, (char *) "Contrast", (char *) "Contrast"},
- { 0xA409, (char *) "Saturation", (char *) "Saturation"},
- { 0xA40A, (char *) "Sharpness", (char *) "Sharpness"},
- { 0xA40B, (char *) "DeviceSettingDescription", (char *) "Device settings description"},
- { 0xA40C, (char *) "SubjectDistanceRange", (char *) "Subject distance range"},
- { 0xA420, (char *) "ImageUniqueID", (char *) "Unique image ID"},
- // These tags are not part of the Exiv v2.3 specifications but are often loaded by applications as Exif data
- { 0x4746, (char *) "Rating", (char *) "Rating tag used by Windows"},
- { 0x4749, (char *) "RatingPercent", (char *) "Rating tag used by Windows, value in percent"},
- { 0x9C9B, (char *) "XPTitle", (char *) "Title tag used by Windows, encoded in UCS2"},
- { 0x9C9C, (char *) "XPComment", (char *) "Comment tag used by Windows, encoded in UCS2"},
- { 0x9C9D, (char *) "XPAuthor", (char *) "Author tag used by Windows, encoded in UCS2"},
- { 0x9C9E, (char *) "XPKeywords", (char *) "Keywords tag used by Windows, encoded in UCS2"},
- { 0x9C9F, (char *) "XPSubject", (char *) "Subject tag used by Windows, encoded in UCS2"},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-// --------------------------------------------------------------------------
-// EXIF GPS tags definition
-// --------------------------------------------------------------------------
-
-static TagInfo
- exif_gps_tag_table[] =
- {
- { 0x0000, (char *) "GPSVersionID", (char *) "GPS tag version"},
- { 0x0001, (char *) "GPSLatitudeRef", (char *) "North or South Latitude"},
- { 0x0002, (char *) "GPSLatitude", (char *) "Latitude"},
- { 0x0003, (char *) "GPSLongitudeRef", (char *) "East or West Longitude"},
- { 0x0004, (char *) "GPSLongitude", (char *) "Longitude"},
- { 0x0005, (char *) "GPSAltitudeRef", (char *) "Altitude reference"},
- { 0x0006, (char *) "GPSAltitude", (char *) "Altitude"},
- { 0x0007, (char *) "GPSTimeStamp", (char *) "GPS time (atomic clock)"},
- { 0x0008, (char *) "GPSSatellites", (char *) "GPS satellites used for measurement"},
- { 0x0009, (char *) "GPSStatus", (char *) "GPS receiver status"},
- { 0x000A, (char *) "GPSMeasureMode", (char *) "GPS measurement mode"},
- { 0x000B, (char *) "GPSDOP", (char *) "Measurement precision"},
- { 0x000C, (char *) "GPSSpeedRef", (char *) "Speed unit"},
- { 0x000D, (char *) "GPSSpeed", (char *) "Speed of GPS receiver"},
- { 0x000E, (char *) "GPSTrackRef", (char *) "Reference for direction of movement"},
- { 0x000F, (char *) "GPSTrack", (char *) "Direction of movement"},
- { 0x0010, (char *) "GPSImgDirectionRef", (char *) "Reference for direction of image"},
- { 0x0011, (char *) "GPSImgDirection", (char *) "Direction of image"},
- { 0x0012, (char *) "GPSMapDatum", (char *) "Geodetic survey data used"},
- { 0x0013, (char *) "GPSDestLatitudeRef", (char *) "Reference for latitude of destination"},
- { 0x0014, (char *) "GPSDestLatitude", (char *) "Latitude of destination"},
- { 0x0015, (char *) "GPSDestLongitudeRef", (char *) "Reference for longitude of destination"},
- { 0x0016, (char *) "GPSDestLongitude", (char *) "Longitude of destination"},
- { 0x0017, (char *) "GPSDestBearingRef", (char *) "Reference for bearing of destination"},
- { 0x0018, (char *) "GPSDestBearing", (char *) "Bearing of destination"},
- { 0x0019, (char *) "GPSDestDistanceRef", (char *) "Reference for distance to destination"},
- { 0x001A, (char *) "GPSDestDistance", (char *) "Distance to destination"},
- { 0x001B, (char *) "GPSProcessingMethod", (char *) "Name of GPS processing method"},
- { 0x001C, (char *) "GPSAreaInformation", (char *) "Name of GPS area"},
- { 0x001D, (char *) "GPSDateStamp", (char *) "GPS date"},
- { 0x001E, (char *) "GPSDifferential", (char *) "GPS differential correction"},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-// --------------------------------------------------------------------------
-// EXIF interoperability tags definition
-// --------------------------------------------------------------------------
-
-static TagInfo
- exif_interop_tag_table[] =
- {
- { 0x0001, (char *) "InteroperabilityIndex", (char *) "Interoperability Identification"},
- { 0x0002, (char *) "InteroperabilityVersion", (char *) "Interoperability version"},
- { 0x1000, (char *) "RelatedImageFileFormat", (char *) "File format of image file"},
- { 0x1001, (char *) "RelatedImageWidth", (char *) "Image width"},
- { 0x1002, (char *) "RelatedImageLength", (char *) "Image height"},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-// --------------------------------------------------------------------------
-// EXIF maker note tags definition
-// --------------------------------------------------------------------------
-
-/**
-Canon maker note
-*/
-static TagInfo
- exif_canon_tag_table[] =
- {
- { 0x0001, (char *) "CanonCameraSettings", (char *) "Canon CameraSettings Tags"},
- { 0x0002, (char *) "CanonFocalLength", (char *) "Canon FocalLength Tags"},
- { 0x0003, (char *) "CanonFlashInfo?", (char *) NULL},
- { 0x0004, (char *) "CanonShotInfo", (char *) "Canon ShotInfo Tags"},
- { 0x0005, (char *) "CanonPanorama", (char *) "Canon Panorama Tags"},
- { 0x0006, (char *) "CanonImageType", (char *) NULL},
- { 0x0007, (char *) "CanonFirmwareVersion", (char *) NULL},
- { 0x0008, (char *) "FileNumber", (char *) NULL},
- { 0x0009, (char *) "OwnerName", (char *) NULL},
- { 0x000A, (char *) "UnknownD30", (char *) "Canon UnknownD30 Tags"},
- { 0x000C, (char *) "SerialNumber", (char *) NULL},
- { 0x000D, (char *) "CanonCameraInfo", (char *) "Canon CameraInfo Tags"},
- { 0x000E, (char *) "CanonFileLength", (char *) NULL},
- { 0x000F, (char *) "CanonCustomFunctions", (char *) "Custom Functions"},
- { 0x0010, (char *) "CanonModelID", (char *) NULL},
- { 0x0012, (char *) "CanonAFInfo", (char *) "Canon AFInfo Tags"},
- { 0x0013, (char *) "ThumbnailImageValidArea", (char *) NULL},
- { 0x0015, (char *) "SerialNumberFormat", (char *) NULL},
- { 0x001A, (char *) "SuperMacro", (char *) NULL},
- { 0x001C, (char *) "DateStampMode", (char *) NULL},
- { 0x001D, (char *) "MyColors", (char *) NULL},
- { 0x001E, (char *) "FirmwareRevision", (char *) NULL},
- { 0x0023, (char *) "Categories", (char *) NULL},
- { 0x0024, (char *) "FaceDetect1", (char *) NULL},
- { 0x0025, (char *) "FaceDetect2", (char *) NULL},
- { 0x0026, (char *) "CanonAFInfo2", (char *) "Canon AFInfo2 Tags"},
- { 0x0028, (char *) "ImageUniqueID", (char *) NULL},
- { 0x0081, (char *) "RawDataOffset", (char *) NULL},
- { 0x0083, (char *) "OriginalDecisionDataOffset", (char *) NULL},
- { 0x0090, (char *) "CustomFunctions1D", (char *) "CanonCustom Functions1D Tags"},
- { 0x0091, (char *) "PersonalFunctions", (char *) "CanonCustom PersonalFuncs Tags"},
- { 0x0092, (char *) "PersonalFunctionValues", (char *) "CanonCustom PersonalFuncValues Tags"},
- { 0x0093, (char *) "CanonFileInfo", (char *) "Canon FileInfo Tags"},
- { 0x0094, (char *) "AFPointsInFocus1D", (char *) NULL},
- { 0x0095, (char *) "LensModel", (char *) NULL},
- { 0x0096, (char *) "SerialInfo", (char *) NULL},
- { 0x0097, (char *) "DustRemovalData", (char *) NULL},
- { 0x0099, (char *) "CustomFunctions2", (char *) NULL},
- { 0x00A0, (char *) "ProcessingInfo", (char *) NULL},
- { 0x00A1, (char *) "ToneCurveTable", (char *) NULL},
- { 0x00A2, (char *) "SharpnessTable", (char *) NULL},
- { 0x00A3, (char *) "SharpnessFreqTable", (char *) NULL},
- { 0x00A4, (char *) "WhiteBalanceTable", (char *) NULL},
- { 0x00A9, (char *) "ColorBalance", (char *) NULL},
- { 0x00AA, (char *) "MeasuredColor", (char *) NULL},
- { 0x00AE, (char *) "ColorTemperature", (char *) NULL},
- { 0x00B0, (char *) "CanonFlags", (char *) NULL},
- { 0x00B1, (char *) "ModifiedInfo", (char *) NULL},
- { 0x00B2, (char *) "ToneCurveMatching", (char *) NULL},
- { 0x00B3, (char *) "WhiteBalanceMatching", (char *) NULL},
- { 0x00B4, (char *) "ColorSpace", (char *) NULL},
- { 0x00B6, (char *) "PreviewImageInfo", (char *) NULL},
- { 0x00D0, (char *) "VRDOffset", (char *) "Offset of VRD 'recipe data' if it exists"},
- { 0x00E0, (char *) "SensorInfo", (char *) NULL},
- { 0x4001, (char *) "ColorData", (char *) NULL},
- { 0x4002, (char *) "UnknownBlock1?", (char *) NULL},
- { 0x4003, (char *) "ColorInfo", (char *) NULL},
- { 0x4005, (char *) "UnknownBlock2?", (char *) NULL},
- { 0x4008, (char *) "BlackLevel?", (char *) NULL},
- { 0x4013, (char *) "AFMicroAdj", (char *) NULL},
- { 0x4015, (char *) "VignettingCorr", (char *) NULL},
- { 0x4016, (char *) "VignettingCorr2", (char *) NULL},
- { 0x4018, (char *) "LightingOpt", (char *) NULL},
-
- // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment
-
- // Fields under tag 0x0001 (we add 0xC100 to make unique tag id)
- { 0xC100 + 1, (char *) "CameraSettings:MacroMode", (char *) NULL},
- { 0xC100 + 2, (char *) "CameraSettings:SelfTimer", (char *) NULL},
- { 0xC100 + 3, (char *) "CameraSettings:Quality", (char *) NULL},
- { 0xC100 + 4, (char *) "CameraSettings:CanonFlashMode", (char *) NULL},
- { 0xC100 + 5, (char *) "CameraSettings:ContinuousDrive", (char *) NULL},
- { 0xC100 + 7, (char *) "CameraSettings:FocusMode", (char *) NULL},
- { 0xC100 + 9, (char *) "CameraSettings:RecordMode", (char *) NULL},
- { 0xC100 + 10, (char *) "CameraSettings:CanonImageSize", (char *) NULL},
- { 0xC100 + 11, (char *) "CameraSettings:EasyMode", (char *) NULL},
- { 0xC100 + 12, (char *) "CameraSettings:DigitalZoom", (char *) NULL},
- { 0xC100 + 13, (char *) "CameraSettings:Contrast", (char *) NULL},
- { 0xC100 + 14, (char *) "CameraSettings:Saturation", (char *) NULL},
- { 0xC100 + 15, (char *) "CameraSettings:Sharpness", (char *) NULL},
- { 0xC100 + 16, (char *) "CameraSettings:CameraISO", (char *) NULL},
- { 0xC100 + 17, (char *) "CameraSettings:MeteringMode", (char *) NULL},
- { 0xC100 + 18, (char *) "CameraSettings:FocusRange", (char *) NULL},
- { 0xC100 + 19, (char *) "CameraSettings:AFPoint", (char *) NULL},
- { 0xC100 + 20, (char *) "CameraSettings:CanonExposureMode", (char *) NULL},
- { 0xC100 + 22, (char *) "CameraSettings:LensType", (char *) NULL},
- { 0xC100 + 23, (char *) "CameraSettings:LongFocal", (char *) NULL},
- { 0xC100 + 24, (char *) "CameraSettings:ShortFocal", (char *) NULL},
- { 0xC100 + 25, (char *) "CameraSettings:FocalUnits", (char *) "Focal Units per mm"},
- { 0xC100 + 26, (char *) "CameraSettings:MaxAperture", (char *) NULL},
- { 0xC100 + 27, (char *) "CameraSettings:MinAperture", (char *) NULL},
- { 0xC100 + 28, (char *) "CameraSettings:FlashActivity", (char *) NULL},
- { 0xC100 + 29, (char *) "CameraSettings:FlashBits", (char *) NULL},
- { 0xC100 + 32, (char *) "CameraSettings:FocusContinuous", (char *) NULL},
- { 0xC100 + 33, (char *) "CameraSettings:AESetting", (char *) NULL},
- { 0xC100 + 34, (char *) "CameraSettings:ImageStabilization", (char *) NULL},
- { 0xC100 + 35, (char *) "CameraSettings:DisplayAperture", (char *) NULL},
- { 0xC100 + 36, (char *) "CameraSettings:ZoomSourceWidth", (char *) NULL},
- { 0xC100 + 37, (char *) "CameraSettings:ZoomTargetWidth", (char *) NULL},
- { 0xC100 + 39, (char *) "CameraSettings:SpotMeteringMode", (char *) NULL},
- { 0xC100 + 40, (char *) "CameraSettings:PhotoEffect", (char *) NULL},
- { 0xC100 + 41, (char *) "CameraSettings:ManualFlashOutput", (char *) NULL},
- { 0xC100 + 42, (char *) "CameraSettings:ColorTone", (char *) NULL},
- { 0xC100 + 46, (char *) "CameraSettings:SRAWQuality", (char *) NULL},
-
- // Fields under tag 0x0002 (we add 0xC200 to make unique tag id)
- { 0xC200 + 0, (char *) "FocalLength:FocalType", (char *) NULL},
- { 0xC200 + 1, (char *) "FocalLength:FocalLength", (char *) NULL},
- { 0xC200 + 2, (char *) "FocalLength:FocalPlaneXSize", (char *) NULL},
- { 0xC200 + 3, (char *) "FocalLength:FocalPlaneYSize", (char *) NULL},
-
- // Fields under tag 0x0004 (we add 0xC400 to make unique tag id)
- { 0xC400 + 1, (char *) "ShotInfo:AutoISO", (char *) NULL},
- { 0xC400 + 2, (char *) "ShotInfo:BaseISO", (char *) NULL},
- { 0xC400 + 3, (char *) "ShotInfo:MeasuredEV", (char *) NULL},
- { 0xC400 + 4, (char *) "ShotInfo:TargetAperture", (char *) NULL},
- { 0xC400 + 5, (char *) "ShotInfo:TargetExposureTime", (char *) NULL},
- { 0xC400 + 6, (char *) "ShotInfo:ExposureCompensation", (char *) NULL},
- { 0xC400 + 7, (char *) "ShotInfo:WhiteBalance", (char *) NULL},
- { 0xC400 + 8, (char *) "ShotInfo:SlowShutter", (char *) NULL},
- { 0xC400 + 9, (char *) "ShotInfo:SequenceNumber", (char *) NULL},
- { 0xC400 + 10, (char *) "ShotInfo:OpticalZoomCode", (char *) NULL},
- { 0xC400 + 12, (char *) "ShotInfo:CameraTemperature", (char *) NULL},
- { 0xC400 + 13, (char *) "ShotInfo:FlashGuideNumber", (char *) NULL},
- { 0xC400 + 14, (char *) "ShotInfo:AFPointsInFocus", (char *) NULL},
- { 0xC400 + 15, (char *) "ShotInfo:FlashExposureComp", (char *) NULL},
- { 0xC400 + 16, (char *) "ShotInfo:AutoExposureBracketing", (char *) NULL},
- { 0xC400 + 17, (char *) "ShotInfo:AEBBracketValue", (char *) NULL},
- { 0xC400 + 18, (char *) "ShotInfo:ControlMode", (char *) NULL},
- { 0xC400 + 19, (char *) "ShotInfo:FocusDistanceUpper", (char *) NULL},
- { 0xC400 + 20, (char *) "ShotInfo:FocusDistanceLower", (char *) NULL},
- { 0xC400 + 21, (char *) "ShotInfo:FNumber", (char *) NULL},
- { 0xC400 + 22, (char *) "ShotInfo:ExposureTime", (char *) NULL},
- { 0xC400 + 23, (char *) "ShotInfo:MeasuredEV2", (char *) NULL},
- { 0xC400 + 24, (char *) "ShotInfo:BulbDuration", (char *) NULL},
- { 0xC400 + 26, (char *) "ShotInfo:CameraType", (char *) NULL},
- { 0xC400 + 27, (char *) "ShotInfo:AutoRotate", (char *) NULL},
- { 0xC400 + 28, (char *) "ShotInfo:NDFilter", (char *) NULL},
- { 0xC400 + 29, (char *) "ShotInfo:SelfTimer2", (char *) NULL},
- { 0xC400 + 33, (char *) "ShotInfo:FlashOutput", (char *) NULL},
-
- // Fields under tag 0x0012 (we add 0x1200 to make unique tag id)
- { 0x1200 + 0, (char *) "AFInfo:NumAFPoints", (char *) NULL},
- { 0x1200 + 1, (char *) "AFInfo:ValidAFPoints", (char *) NULL},
- { 0x1200 + 2, (char *) "AFInfo:CanonImageWidth", (char *) NULL},
- { 0x1200 + 3, (char *) "AFInfo:CanonImageHeight", (char *) NULL},
- { 0x1200 + 4, (char *) "AFInfo:AFImageWidth", (char *) NULL},
- { 0x1200 + 5, (char *) "AFInfo:AFImageHeight", (char *) NULL},
- { 0x1200 + 6, (char *) "AFInfo:AFAreaWidth", (char *) NULL},
- { 0x1200 + 7, (char *) "AFInfo:AFAreaHeight", (char *) NULL},
- { 0x1200 + 8, (char *) "AFInfo:AFAreaXPositions", (char *) NULL},
- { 0x1200 + 9, (char *) "AFInfo:AFAreaYPositions", (char *) NULL},
- { 0x1200 + 10, (char *) "AFInfo:AFPointsInFocus", (char *) NULL},
- { 0x1200 + 11, (char *) "AFInfo:PrimaryAFPoint?", (char *) NULL},
- { 0x1200 + 12, (char *) "AFInfo:PrimaryAFPoint", (char *) NULL},
-
- // Fields under tag 0x00A0 (we add 0xCA00 to make unique tag id)
- { 0xCA00 + 1, (char *) "ProcessingInfo:ToneCurve", (char *) NULL},
- { 0xCA00 + 2, (char *) "ProcessingInfo:Sharpness", (char *) NULL},
- { 0xCA00 + 3, (char *) "ProcessingInfo:SharpnessFrequency", (char *) NULL},
- { 0xCA00 + 4, (char *) "ProcessingInfo:SensorRedLevel", (char *) NULL},
- { 0xCA00 + 5, (char *) "ProcessingInfo:SensorBlueLevel", (char *) NULL},
- { 0xCA00 + 6, (char *) "ProcessingInfo:WhiteBalanceRed", (char *) NULL},
- { 0xCA00 + 7, (char *) "ProcessingInfo:WhiteBalanceBlue", (char *) NULL},
- { 0xCA00 + 8, (char *) "ProcessingInfo:WhiteBalance", (char *) NULL},
- { 0xCA00 + 9, (char *) "ProcessingInfo:ColorTemperature", (char *) NULL},
- { 0xCA00 + 10, (char *) "ProcessingInfo:PictureStyle", (char *) NULL},
- { 0xCA00 + 11, (char *) "ProcessingInfo:DigitalGain", (char *) NULL},
- { 0xCA00 + 12, (char *) "ProcessingInfo:WBShiftAB", (char *) NULL},
- { 0xCA00 + 13, (char *) "ProcessingInfo:WBShiftGM", (char *) NULL},
-
- // Fields under tag 0x00E0 (we add 0xCE00 to make unique tag id)
- { 0xCE00 + 1, (char *) "SensorInfo:SensorWidth", (char *) NULL},
- { 0xCE00 + 2, (char *) "SensorInfo:SensorHeight", (char *) NULL},
- { 0xCE00 + 5, (char *) "SensorInfo:SensorLeftBorder", (char *) NULL},
- { 0xCE00 + 6, (char *) "SensorInfo:SensorTopBorder", (char *) NULL},
- { 0xCE00 + 7, (char *) "SensorInfo:SensorRightBorder", (char *) NULL},
- { 0xCE00 + 8, (char *) "SensorInfo:SensorBottomBorder", (char *) NULL},
- { 0xCE00 + 9, (char *) "SensorInfo:BlackMaskLeftBorder", (char *) NULL},
- { 0xCE00 + 10, (char *) "SensorInfo:BlackMaskTopBorder", (char *) NULL},
- { 0xCE00 + 11, (char *) "SensorInfo:BlackMaskRightBorder", (char *) NULL},
- { 0xCE00 + 12, (char *) "SensorInfo:BlackMaskBottomBorder", (char *) NULL},
-
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-Casio type 1 maker note
-*/
-static TagInfo
- exif_casio_type1_tag_table[] =
- {
- { 0x0001, (char *) "RecordingMode", (char *) NULL},
- { 0x0002, (char *) "Quality", (char *) NULL},
- { 0x0003, (char *) "FocusMode", (char *) NULL},
- { 0x0004, (char *) "FlashMode", (char *) NULL},
- { 0x0005, (char *) "FlashIntensity", (char *) NULL},
- { 0x0006, (char *) "ObjectDistance", (char *) NULL},
- { 0x0007, (char *) "WhiteBalance", (char *) NULL},
- { 0x000A, (char *) "DigitalZoom", (char *) NULL},
- { 0x000B, (char *) "Sharpness", (char *) NULL},
- { 0x000C, (char *) "Contrast", (char *) NULL},
- { 0x000D, (char *) "Saturation", (char *) NULL},
- { 0x0014, (char *) "ISO", (char *) NULL},
- { 0x0015, (char *) "FirmwareDate", (char *) NULL},
- { 0x0016, (char *) "Enhancement", (char *) NULL},
- { 0x0017, (char *) "ColorFilter", (char *) NULL},
- { 0x0018, (char *) "AFPoint", (char *) NULL},
- { 0x0019, (char *) "FlashIntensity", (char *) NULL},
- { 0x0E00, (char *) "PrintIM", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-Casio type 2 maker note
-*/
-static TagInfo
- exif_casio_type2_tag_table[] =
- {
- { 0x0002, (char *) "PreviewImageSize", (char *) NULL},
- { 0x0003, (char *) "PreviewImageLength", (char *) NULL},
- { 0x0004, (char *) "PreviewImageStart", (char *) NULL},
- { 0x0008, (char *) "QualityMode", (char *) NULL},
- { 0x0009, (char *) "CasioImageSize", (char *) NULL},
- { 0x000D, (char *) "FocusMode", (char *) NULL},
- { 0x0014, (char *) "ISO", (char *) NULL},
- { 0x0019, (char *) "WhiteBalance", (char *) NULL},
- { 0x001D, (char *) "FocalLength", (char *) NULL},
- { 0x001F, (char *) "Saturation", (char *) NULL},
- { 0x0020, (char *) "Contrast", (char *) NULL},
- { 0x0021, (char *) "Sharpness", (char *) NULL},
- { 0x0E00, (char *) "PrintIM", (char *) NULL},
- { 0x2000, (char *) "PreviewImage", (char *) NULL},
- { 0x2001, (char *) "FirmwareDate", (char *) NULL},
- { 0x2011, (char *) "WhiteBalanceBias", (char *) NULL},
- { 0x2012, (char *) "WhiteBalance", (char *) NULL},
- { 0x2021, (char *) "AFPointPosition", (char *) NULL},
- { 0x2022, (char *) "ObjectDistance", (char *) NULL},
- { 0x2034, (char *) "FlashDistance", (char *) NULL},
- { 0x2076, (char *) "SpecialEffectMode", (char *) NULL},
- { 0x3000, (char *) "RecordMode", (char *) NULL},
- { 0x3001, (char *) "ReleaseMode", (char *) NULL},
- { 0x3002, (char *) "Quality", (char *) NULL},
- { 0x3003, (char *) "FocusMode", (char *) NULL},
- { 0x3006, (char *) "HometownCity", (char *) NULL},
- { 0x3007, (char *) "BestShotMode", (char *) NULL},
- { 0x3008, (char *) "AutoISO", (char *) NULL},
- { 0x3009, (char *) "AFMode", (char *) NULL},
- { 0x3011, (char *) "Sharpness", (char *) NULL},
- { 0x3012, (char *) "Contrast", (char *) NULL},
- { 0x3013, (char *) "Saturation", (char *) NULL},
- { 0x3014, (char *) "ISO", (char *) NULL},
- { 0x3015, (char *) "ColorMode", (char *) NULL},
- { 0x3016, (char *) "Enhancement", (char *) NULL},
- { 0x3017, (char *) "ColorFilter", (char *) NULL},
- { 0x301C, (char *) "SequenceNumber", (char *) NULL},
- { 0x301D, (char *) "BracketSequence", (char *) NULL},
- { 0x3020, (char *) "ImageStabilization", (char *) NULL},
- { 0x302A, (char *) "LightingMode", (char *) NULL},
- { 0x302B, (char *) "PortraitRefiner", (char *) NULL},
- { 0x3030, (char *) "SpecialEffectLevel", (char *) NULL},
- { 0x3031, (char *) "SpecialEffectSetting", (char *) NULL},
- { 0x3103, (char *) "DriveMode", (char *) NULL},
- { 0x4001, (char *) "CaptureFrameRate", (char *) NULL},
- { 0x4003, (char *) "VideoQuality", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-FujiFilm maker note
-*/
-static TagInfo
- exif_fujifilm_tag_table[] =
- {
- { 0x0000, (char *) "Version", (char *) NULL},
- { 0x0010, (char *) "InternalSerialNumber", (char *) NULL},
- { 0x1000, (char *) "Quality", (char *) NULL},
- { 0x1001, (char *) "Sharpness", (char *) NULL},
- { 0x1002, (char *) "WhiteBalance", (char *) NULL},
- { 0x1003, (char *) "Saturation", (char *) NULL},
- { 0x1004, (char *) "Contrast", (char *) NULL},
- { 0x1005, (char *) "ColorTemperature", (char *) NULL},
- { 0x100A, (char *) "WhiteBalanceFineTune", (char *) NULL},
- { 0x100B, (char *) "NoiseReduction", (char *) NULL},
- { 0x1010, (char *) "FujiFlashMode", (char *) NULL},
- { 0x1011, (char *) "FlashExposureComp", (char *) NULL},
- { 0x1020, (char *) "Macro", (char *) NULL},
- { 0x1021, (char *) "FocusMode", (char *) NULL},
- { 0x1023, (char *) "FocusPixel", (char *) NULL},
- { 0x1030, (char *) "SlowSync", (char *) NULL},
- { 0x1031, (char *) "PictureMode", (char *) NULL},
- { 0x1033, (char *) "EXRAuto", (char *) NULL},
- { 0x1034, (char *) "EXRMode", (char *) NULL},
- { 0x1100, (char *) "AutoBracketting", (char *) NULL},
- { 0x1101, (char *) "SequenceNumber", (char *) NULL},
- { 0x1210, (char *) "ColorMode", (char *) NULL},
- { 0x1300, (char *) "BlurWarning", (char *) NULL},
- { 0x1301, (char *) "FocusWarning", (char *) NULL},
- { 0x1302, (char *) "ExposureWarning", (char *) NULL},
- { 0x1400, (char *) "DynamicRange", (char *) NULL},
- { 0x1401, (char *) "FilmMode", (char *) NULL},
- { 0x1402, (char *) "DynamicRangeSetting", (char *) NULL},
- { 0x1403, (char *) "DevelopmentDynamicRange", (char *) NULL},
- { 0x1404, (char *) "MinFocalLength", (char *) NULL},
- { 0x1405, (char *) "MaxFocalLength", (char *) NULL},
- { 0x1406, (char *) "MaxApertureAtMinFocal", (char *) NULL},
- { 0x1407, (char *) "MaxApertureAtMaxFocal", (char *) NULL},
- { 0x4100, (char *) "FacesDetected", (char *) NULL},
- { 0x4103, (char *) "FacePositions", (char *) NULL},
- { 0x8000, (char *) "FileSource", (char *) NULL},
- { 0x8002, (char *) "OrderNumber", (char *) NULL},
- { 0x8003, (char *) "FrameNumber", (char *) NULL},
- { 0xB211, (char *) "Parallax", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-Kyocera maker note
-*/
-static TagInfo
- exif_kyocera_tag_table[] =
- {
- { 0x0001, (char *) "ThumbnailImage", (char *) NULL},
- { 0x0E00, (char *) "PrintIM", (char *) "Print Image Matching Info"},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-Olympus Type 1 / Epson / Agfa maker note
-*/
-static TagInfo
- exif_olympus_type1_tag_table[] =
- {
- { 0x0000, (char *) "MakerNoteVersion", (char *) NULL},
- { 0x0001, (char *) "MinoltaCameraSettingsOld", (char *) NULL},
- { 0x0003, (char *) "MinoltaCameraSettings", (char *) NULL},
- { 0x0040, (char *) "CompressedImageSize", (char *) NULL},
- { 0x0081, (char *) "PreviewImageData", (char *) NULL},
- { 0x0088, (char *) "PreviewImageStart", (char *) NULL},
- { 0x0089, (char *) "PreviewImageLength", (char *) NULL},
- { 0x0100, (char *) "ThumbnailImage", (char *) NULL},
- { 0x0104, (char *) "BodyFirmwareVersion", (char *) NULL},
- { 0x0200, (char *) "SpecialMode", (char *) NULL},
- { 0x0201, (char *) "Quality", (char *) NULL},
- { 0x0202, (char *) "Macro", (char *) NULL},
- { 0x0203, (char *) "BWMode", (char *) NULL},
- { 0x0204, (char *) "DigitalZoom", (char *) NULL},
- { 0x0205, (char *) "FocalPlaneDiagonal", (char *) NULL},
- { 0x0206, (char *) "LensDistortionParams", (char *) NULL},
- { 0x0207, (char *) "CameraType", (char *) NULL},
- { 0x0208, (char *) "TextInfo", (char *) "Olympus TextInfo Tags"},
- { 0x0209, (char *) "CameraID", (char *) NULL},
- { 0x020B, (char *) "EpsonImageWidth", (char *) NULL},
- { 0x020C, (char *) "EpsonImageHeight", (char *) NULL},
- { 0x020D, (char *) "EpsonSoftware", (char *) NULL},
- { 0x0280, (char *) "PreviewImage", (char *) NULL},
- { 0x0300, (char *) "PreCaptureFrames", (char *) NULL},
- { 0x0301, (char *) "WhiteBoard", (char *) NULL},
- { 0x0302, (char *) "OneTouchWB", (char *) NULL},
- { 0x0303, (char *) "WhiteBalanceBracket", (char *) NULL},
- { 0x0304, (char *) "WhiteBalanceBias", (char *) NULL},
- { 0x0403, (char *) "SceneMode", (char *) NULL},
- { 0x0404, (char *) "SerialNumber", (char *) NULL},
- { 0x0405, (char *) "Firmware", (char *) NULL},
- { 0x0E00, (char *) "PrintIM", (char *) "PrintIM Tags"},
- { 0x0F00, (char *) "DataDump", (char *) NULL},
- { 0x0F01, (char *) "DataDump2", (char *) NULL},
- { 0x1000, (char *) "ShutterSpeedValue", (char *) NULL},
- { 0x1001, (char *) "ISOValue", (char *) NULL},
- { 0x1002, (char *) "ApertureValue", (char *) NULL},
- { 0x1003, (char *) "BrightnessValue", (char *) NULL},
- { 0x1004, (char *) "FlashMode", (char *) NULL},
- { 0x1005, (char *) "FlashDevice", (char *) NULL},
- { 0x1006, (char *) "ExposureCompensation", (char *) NULL},
- { 0x1007, (char *) "SensorTemperature", (char *) NULL},
- { 0x1008, (char *) "LensTemperature", (char *) NULL},
- { 0x1009, (char *) "LightCondition", (char *) NULL},
- { 0x100A, (char *) "FocusRange", (char *) NULL},
- { 0x100B, (char *) "FocusMode", (char *) NULL},
- { 0x100C, (char *) "ManualFocusDistance", (char *) NULL},
- { 0x100D, (char *) "ZoomStepCount", (char *) NULL},
- { 0x100E, (char *) "FocusStepCount", (char *) NULL},
- { 0x100F, (char *) "Sharpness", (char *) NULL},
- { 0x1010, (char *) "FlashChargeLevel", (char *) NULL},
- { 0x1011, (char *) "ColorMatrix", (char *) NULL},
- { 0x1012, (char *) "BlackLevel", (char *) NULL},
- { 0x1015, (char *) "WBMode", (char *) NULL},
- { 0x1017, (char *) "RedBalance", (char *) NULL},
- { 0x1018, (char *) "BlueBalance", (char *) NULL},
- { 0x1019, (char *) "ColorMatrixNumber", (char *) NULL},
- { 0x101A, (char *) "SerialNumber", (char *) NULL},
- { 0x1023, (char *) "FlashExposureComp", (char *) NULL},
- { 0x1024, (char *) "InternalFlashTable", (char *) NULL},
- { 0x1025, (char *) "ExternalFlashGValue", (char *) NULL},
- { 0x1026, (char *) "ExternalFlashBounce", (char *) NULL},
- { 0x1027, (char *) "ExternalFlashZoom", (char *) NULL},
- { 0x1028, (char *) "ExternalFlashMode", (char *) NULL},
- { 0x1029, (char *) "Contrast", (char *) NULL},
- { 0x102A, (char *) "SharpnessFactor", (char *) NULL},
- { 0x102B, (char *) "ColorControl", (char *) NULL},
- { 0x102C, (char *) "ValidBits", (char *) NULL},
- { 0x102D, (char *) "CoringFilter", (char *) NULL},
- { 0x102E, (char *) "OlympusImageWidth", (char *) NULL},
- { 0x102F, (char *) "OlympusImageHeight", (char *) NULL},
- { 0x1030, (char *) "SceneDetect", (char *) NULL},
- { 0x1031, (char *) "SceneArea?", (char *) NULL},
- { 0x1033, (char *) "SceneDetectData?", (char *) NULL},
- { 0x1034, (char *) "CompressionRatio", (char *) NULL},
- { 0x1035, (char *) "PreviewImageValid", (char *) NULL},
- { 0x1036, (char *) "PreviewImageStart", (char *) NULL},
- { 0x1037, (char *) "PreviewImageLength", (char *) NULL},
- { 0x1038, (char *) "AFResult", (char *) NULL},
- { 0x1039, (char *) "CCDScanMode", (char *) NULL},
- { 0x103A, (char *) "NoiseReduction", (char *) NULL},
- { 0x103B, (char *) "InfinityLensStep", (char *) NULL},
- { 0x103C, (char *) "NearLensStep", (char *) NULL},
- { 0x103D, (char *) "LightValueCenter", (char *) NULL},
- { 0x103E, (char *) "LightValuePeriphery", (char *) NULL},
- { 0x2010, (char *) "Equipment", (char *) "Olympus Equipment Tags"},
- { 0x2020, (char *) "CameraSettings", (char *) "Olympus CameraSettings Tags"},
- { 0x2030, (char *) "RawDevelopment", (char *) "Olympus RawDevelopment Tags"},
- { 0x2040, (char *) "ImageProcessing", (char *) "Olympus ImageProcessing Tags"},
- { 0x2050, (char *) "FocusInfo", (char *) "Olympus FocusInfo Tags"},
- { 0x2100, (char *) "Olympus2100", (char *) "Olympus FE Tags"},
- { 0x2200, (char *) "Olympus2200", (char *) "Olympus FE Tags"},
- { 0x2300, (char *) "Olympus2300", (char *) "Olympus FE Tags"},
- { 0x2400, (char *) "Olympus2400", (char *) "Olympus FE Tags"},
- { 0x2500, (char *) "Olympus2500", (char *) "Olympus FE Tags"},
- { 0x2600, (char *) "Olympus2600", (char *) "Olympus FE Tags"},
- { 0x2700, (char *) "Olympus2700", (char *) "Olympus FE Tags"},
- { 0x2800, (char *) "Olympus2800", (char *) "Olympus FE Tags"},
- { 0x2900, (char *) "Olympus2900", (char *) "Olympus FE Tags"},
- { 0x3000, (char *) "RawInfo", (char *) "Olympus RawInfo Tags"},
- { 0x4000, (char *) "MainInfo", (char *) "Olympus MainInfo Tags"},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-Minolta maker note
-*/
-static TagInfo
- exif_minolta_tag_table[] =
- {
- { 0x0000, (char *) "MakerNoteVersion", (char *) NULL},
- { 0x0001, (char *) "MinoltaCameraSettingsOld", (char *) NULL},
- { 0x0003, (char *) "MinoltaCameraSettings", (char *) NULL},
- { 0x0004, (char *) "MinoltaCameraSettings7D", (char *) NULL},
- { 0x0018, (char *) "ImageStabilization", (char *) NULL},
- { 0x0040, (char *) "CompressedImageSize", (char *) NULL},
- { 0x0081, (char *) "PreviewImage", (char *) NULL},
- { 0x0088, (char *) "PreviewImageStart", (char *) NULL},
- { 0x0089, (char *) "PreviewImageLength", (char *) NULL},
- { 0x0100, (char *) "SceneMode", (char *) NULL},
- { 0x0101, (char *) "ColorMode", (char *) NULL},
- { 0x0102, (char *) "MinoltaQuality", (char *) NULL},
- { 0x0103, (char *) "MinoltaImageSize", (char *) NULL},
- { 0x0104, (char *) "FlashExposureComp", (char *) NULL},
- { 0x0105, (char *) "Teleconverter", (char *) NULL},
- { 0x0107, (char *) "ImageStabilization", (char *) NULL},
- { 0x0109, (char *) "RawAndJpgRecording", (char *) NULL},
- { 0x010A, (char *) "ZoneMatching", (char *) NULL},
- { 0x010B, (char *) "ColorTemperature", (char *) NULL},
- { 0x010C, (char *) "LensType", (char *) NULL},
- { 0x0111, (char *) "ColorCompensationFilter", (char *) NULL},
- { 0x0112, (char *) "WhiteBalanceFineTune", (char *) NULL},
- { 0x0113, (char *) "ImageStabilization", (char *) NULL},
- { 0x0114, (char *) "MinoltaCameraSettings5D", (char *) NULL},
- { 0x0115, (char *) "WhiteBalance", (char *) NULL},
- { 0x0E00, (char *) "PrintIM", (char *) NULL},
- { 0x0F00, (char *) "MinoltaCameraSettings2", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-There are 3 formats of Nikon's MakerNote. MakerNote of E700/E800/E900/E900S/E910/E950
-starts from ASCII string "Nikon". Data format is the same as IFD, but it starts from
-offset 0x08. This is the same as Olympus except start string.
-*/
-
-/**
-TYPE 1 is for E-Series cameras prior to (not including) E990
-*/
-static TagInfo
- exif_nikon_type1_tag_table[] =
- {
- { 0x0002, (char *) "FamilyID", (char *) NULL},
- { 0x0003, (char *) "Quality", (char *) NULL},
- { 0x0004, (char *) "ColorMode", (char *) NULL},
- { 0x0005, (char *) "ImageAdjustment", (char *) NULL},
- { 0x0006, (char *) "CCDSensitivity", (char *) NULL},
- { 0x0007, (char *) "WhiteBalance", (char *) NULL},
- { 0x0008, (char *) "Focus", (char *) NULL},
- { 0x000A, (char *) "DigitalZoom", (char *) NULL},
- { 0x000B, (char *) "FisheyeConverter", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-Nikon type 2 maker note
-*/
-static TagInfo
- exif_nikon_type2_tag_table[] =
- {
- { 0x0001, (char *) "MakerNoteVersion", (char *) NULL},
- { 0x0002, (char *) "ISO", (char *) NULL},
- { 0x0003, (char *) "ColorMode", (char *) NULL},
- { 0x0004, (char *) "Quality", (char *) NULL},
- { 0x0005, (char *) "WhiteBalance", (char *) NULL},
- { 0x0006, (char *) "Sharpness", (char *) NULL},
- { 0x0007, (char *) "FocusMode", (char *) NULL},
- { 0x0008, (char *) "FlashSetting", (char *) NULL},
- { 0x0009, (char *) "FlashType", (char *) NULL},
- { 0x000B, (char *) "WhiteBalanceFineTune", (char *) NULL},
- { 0x000F, (char *) "ISOSelection", (char *) NULL},
- { 0x0010, (char *) "DataDump", (char *) NULL},
- { 0x0080, (char *) "ImageAdjustment", (char *) NULL},
- { 0x0082, (char *) "AuxiliaryLens", (char *) NULL},
- { 0x0085, (char *) "ManualFocusDistance", (char *) NULL},
- { 0x0086, (char *) "DigitalZoom", (char *) NULL},
- { 0x0088, (char *) "AFInfo", (char *) NULL},
- { 0x0089, (char *) "ShootingMode", (char *) NULL},
- { 0x008D, (char *) "ColorMode", (char *) NULL},
- { 0x008F, (char *) "SceneMode", (char *) NULL},
- { 0x0092, (char *) "HueAdjustment", (char *) NULL},
- { 0x0094, (char *) "Saturation", (char *) NULL},
- { 0x0095, (char *) "NoiseReduction", (char *) NULL},
- { 0x0E00, (char *) "PrintIM", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-The type-3 directory is for D-Series cameras such as the D1 and D100.
-see http://www.timelesswanderings.net/equipment/D100/NEF.html
-*/
-static TagInfo
- exif_nikon_type3_tag_table[] =
- {
- { 0x0001, (char *) "MakerNoteVersion", (char *) NULL},
- { 0x0002, (char *) "ISO", (char *) NULL},
- { 0x0003, (char *) "ColorMode", (char *) NULL},
- { 0x0004, (char *) "Quality", (char *) NULL},
- { 0x0005, (char *) "WhiteBalance", (char *) NULL},
- { 0x0006, (char *) "Sharpness", (char *) NULL},
- { 0x0007, (char *) "FocusMode", (char *) NULL},
- { 0x0008, (char *) "FlashSetting", (char *) NULL},
- { 0x0009, (char *) "FlashType", (char *) NULL},
- { 0x000B, (char *) "WhiteBalanceFineTune", (char *) NULL},
- { 0x000C, (char *) "WB_RBLevels", (char *) NULL},
- { 0x000D, (char *) "ProgramShift", (char *) NULL},
- { 0x000E, (char *) "ExposureDifference", (char *) NULL},
- { 0x000F, (char *) "ISOSelection", (char *) NULL},
- { 0x0010, (char *) "DataDump", (char *) NULL},
- { 0x0011, (char *) "PreviewIFD", (char *) NULL},
- { 0x0012, (char *) "FlashExposureComp", (char *) NULL},
- { 0x0013, (char *) "ISOSetting", (char *) NULL},
- { 0x0014, (char *) "ColorBalanceA", (char *) NULL},
- { 0x0016, (char *) "ImageBoundary", (char *) NULL},
- { 0x0017, (char *) "FlashExposureComp", (char *) NULL},
- { 0x0018, (char *) "FlashExposureBracketValue", (char *) NULL},
- { 0x0019, (char *) "ExposureBracketValue", (char *) NULL},
- { 0x001A, (char *) "ImageProcessing", (char *) NULL},
- { 0x001B, (char *) "CropHiSpeed", (char *) NULL},
- { 0x001C, (char *) "ExposureTuning", (char *) NULL},
- { 0x001D, (char *) "SerialNumber", (char *) NULL},
- { 0x001E, (char *) "ColorSpace", (char *) NULL},
- { 0x001F, (char *) "VRInfo", (char *) NULL},
- { 0x0020, (char *) "ImageAuthentication", (char *) NULL},
- { 0x0022, (char *) "ActiveD-Lighting", (char *) NULL},
- { 0x0023, (char *) "PictureControl", (char *) NULL},
- { 0x0024, (char *) "WorldTime", (char *) NULL},
- { 0x0025, (char *) "ISOInfo", (char *) NULL},
- { 0x002A, (char *) "VignetteControl", (char *) NULL},
- { 0x002B, (char *) "DistortInfo", (char *) NULL},
- { 0x0080, (char *) "ImageAdjustment", (char *) NULL},
- { 0x0081, (char *) "ToneComp", (char *) NULL},
- { 0x0082, (char *) "AuxiliaryLens", (char *) NULL},
- { 0x0083, (char *) "LensType", (char *) NULL},
- { 0x0084, (char *) "Lens", (char *) NULL},
- { 0x0085, (char *) "ManualFocusDistance", (char *) NULL},
- { 0x0086, (char *) "DigitalZoom", (char *) NULL},
- { 0x0087, (char *) "FlashMode", (char *) NULL},
- { 0x0088, (char *) "AFInfo", (char *) NULL},
- { 0x0089, (char *) "ShootingMode", (char *) NULL},
- { 0x008B, (char *) "LensFStops", (char *) NULL},
- { 0x008C, (char *) "ContrastCurve", (char *) NULL},
- { 0x008D, (char *) "ColorHue", (char *) NULL},
- { 0x008F, (char *) "SceneMode", (char *) NULL},
- { 0x0090, (char *) "LightSource", (char *) NULL},
- { 0x0091, (char *) "ShotInfo", (char *) NULL},
- { 0x0092, (char *) "HueAdjustment", (char *) NULL},
- { 0x0093, (char *) "NEFCompression", (char *) NULL},
- { 0x0094, (char *) "Saturation", (char *) NULL},
- { 0x0095, (char *) "NoiseReduction", (char *) NULL},
- { 0x0096, (char *) "LinearizationTable", (char *) NULL},
- { 0x0097, (char *) "ColorBalance", (char *) NULL},
- { 0x0098, (char *) "LensData", (char *) NULL},
- { 0x0099, (char *) "RawImageCenter", (char *) NULL},
- { 0x009A, (char *) "SensorPixelSize", (char *) NULL},
- { 0x009C, (char *) "SceneAssist", (char *) NULL},
- { 0x009E, (char *) "RetouchHistory", (char *) NULL},
- { 0x00A0, (char *) "SerialNumber", (char *) NULL},
- { 0x00A2, (char *) "ImageDataSize", (char *) NULL},
- { 0x00A5, (char *) "ImageCount", (char *) NULL},
- { 0x00A6, (char *) "DeletedImageCount", (char *) NULL},
- { 0x00A7, (char *) "ShutterCount", (char *) NULL},
- { 0x00A8, (char *) "FlashInfo", (char *) NULL},
- { 0x00A9, (char *) "ImageOptimization", (char *) NULL},
- { 0x00AA, (char *) "Saturation", (char *) NULL},
- { 0x00AB, (char *) "VariProgram", (char *) NULL},
- { 0x00AC, (char *) "ImageStabilization", (char *) NULL},
- { 0x00AD, (char *) "AFResponse", (char *) NULL},
- { 0x00B0, (char *) "MultiExposure", (char *) NULL},
- { 0x00B1, (char *) "HighISONoiseReduction", (char *) NULL},
- { 0x00B3, (char *) "ToningEffect", (char *) NULL},
- { 0x00B6, (char *) "PowerUpTime", (char *) NULL},
- { 0x00B7, (char *) "AFInfo2", (char *) NULL},
- { 0x00B8, (char *) "FileInfo", (char *) NULL},
- { 0x00B9, (char *) "AFTune", (char *) NULL},
- { 0x00BD, (char *) "PictureControl", (char *) NULL},
- { 0x0E00, (char *) "PrintIM", (char *) NULL},
- { 0x0E01, (char *) "NikonCaptureData", (char *) NULL},
- { 0x0E09, (char *) "NikonCaptureVersion", (char *) NULL},
- { 0x0E0E, (char *) "NikonCaptureOffsets", (char *) NULL},
- { 0x0E10, (char *) "NikonScanIFD", (char *) NULL},
- { 0x0E1D, (char *) "NikonICCProfile", (char *) NULL},
- { 0x0E1E, (char *) "NikonCaptureOutput", (char *) NULL},
- { 0x0E22, (char *) "NEFBitDepth", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-Panasonic / Leica maker note
-*/
-static TagInfo
- exif_panasonic_tag_table[] =
- {
- { 0x0001, (char *) "ImageQuality", (char *) NULL},
- { 0x0002, (char *) "FirmwareVersion", (char *) NULL},
- { 0x0003, (char *) "WhiteBalance", (char *) NULL},
- { 0x0007, (char *) "FocusMode", (char *) NULL},
- { 0x000F, (char *) "AFAreaMode", (char *) NULL},
- { 0x001A, (char *) "ImageStabilization", (char *) NULL},
- { 0x001C, (char *) "MacroMode", (char *) NULL},
- { 0x001F, (char *) "ShootingMode", (char *) NULL},
- { 0x0020, (char *) "Audio", (char *) NULL},
- { 0x0021, (char *) "DataDump", (char *) NULL},
- { 0x0022, (char *) "EasyMode", (char *) NULL},
- { 0x0023, (char *) "WhiteBalanceBias", (char *) NULL},
- { 0x0024, (char *) "FlashBias", (char *) NULL},
- { 0x0025, (char *) "InternalSerialNumber", (char *) NULL},
- { 0x0026, (char *) "PanasonicExifVersion", (char *) NULL},
- { 0x0028, (char *) "ColorEffect", (char *) NULL},
- { 0x0029, (char *) "TimeSincePowerOn", (char *) NULL},
- { 0x002A, (char *) "BurstMode", (char *) NULL},
- { 0x002B, (char *) "SequenceNumber", (char *) NULL},
- { 0x002C, (char *) "ContrastMode", (char *) NULL},
- { 0x002D, (char *) "NoiseReduction", (char *) NULL},
- { 0x002E, (char *) "SelfTimer", (char *) NULL},
- { 0x0030, (char *) "Rotation", (char *) NULL},
- { 0x0031, (char *) "AFAssistLamp", (char *) NULL},
- { 0x0032, (char *) "ColorMode", (char *) NULL},
- { 0x0033, (char *) "BabyAge", (char *) NULL},
- { 0x0034, (char *) "OpticalZoomMode", (char *) NULL},
- { 0x0035, (char *) "ConversionLens", (char *) NULL},
- { 0x0036, (char *) "TravelDay", (char *) NULL},
- { 0x0039, (char *) "Contrast", (char *) NULL},
- { 0x003A, (char *) "WorldTimeLocation", (char *) NULL},
- { 0x003B, (char *) "TextStamp", (char *) NULL},
- { 0x003C, (char *) "ProgramISO", (char *) NULL},
- { 0x003D, (char *) "AdvancedSceneMode", (char *) NULL},
- { 0x003F, (char *) "FacesDetected", (char *) NULL},
- { 0x0040, (char *) "Saturation", (char *) NULL},
- { 0x0041, (char *) "Sharpness", (char *) NULL},
- { 0x0042, (char *) "FilmMode", (char *) NULL},
- { 0x0046, (char *) "WBAdjustAB", (char *) NULL},
- { 0x0047, (char *) "WBAdjustGM", (char *) NULL},
- { 0x004B, (char *) "PanasonicImageWidth", (char *) NULL},
- { 0x004C, (char *) "PanasonicImageHeight", (char *) NULL},
- { 0x004D, (char *) "AFPointPosition", (char *) NULL},
- { 0x004E, (char *) "FaceDetInfo", (char *) NULL},
- { 0x0051, (char *) "LensType", (char *) NULL},
- { 0x0052, (char *) "LensSerialNumber", (char *) NULL},
- { 0x0053, (char *) "AccessoryType", (char *) NULL},
- { 0x0059, (char *) "Transform", (char *) NULL},
- { 0x005D, (char *) "IntelligentExposure", (char *) NULL},
- { 0x0061, (char *) "FaceRecInfo", (char *) NULL},
- { 0x0062, (char *) "FlashWarning", (char *) NULL},
- { 0x0063, (char *) "RecognizedFaceFlags?", (char *) NULL},
- { 0x0069, (char *) "Country", (char *) NULL},
- { 0x006B, (char *) "State", (char *) NULL},
- { 0x006D, (char *) "City", (char *) NULL},
- { 0x006F, (char *) "Landmark", (char *) NULL},
- { 0x0070, (char *) "IntelligentResolution", (char *) NULL},
- { 0x0E00, (char *) "PrintIM", (char *) NULL},
- { 0x8000, (char *) "MakerNoteVersion", (char *) NULL},
- { 0x8001, (char *) "SceneMode", (char *) NULL},
- { 0x8004, (char *) "WBRedLevel", (char *) NULL},
- { 0x8005, (char *) "WBGreenLevel", (char *) NULL},
- { 0x8006, (char *) "WBBlueLevel", (char *) NULL},
- { 0x8007, (char *) "FlashFired", (char *) NULL},
- { 0x8012, (char *) "Transform", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-Pentax (Asahi) maker note type 1
-*/
-static TagInfo
- exif_asahi_tag_table[] =
- {
- { 0x0001, (char *) "Capture Mode", (char *) NULL},
- { 0x0002, (char *) "Quality Level", (char *) NULL},
- { 0x0003, (char *) "Focus Mode", (char *) NULL},
- { 0x0004, (char *) "Flash Mode", (char *) NULL},
- { 0x0007, (char *) "White Balance", (char *) NULL},
- { 0x000A, (char *) "Digital Zoom", (char *) NULL},
- { 0x000B, (char *) "Sharpness", (char *) NULL},
- { 0x000C, (char *) "Contrast", (char *) NULL},
- { 0x000D, (char *) "Saturation", (char *) NULL},
- { 0x0014, (char *) "ISO Speed", (char *) NULL},
- { 0x0017, (char *) "Color", (char *) NULL},
- { 0x0E00, (char *) "PrintIM", (char *) NULL},
- { 0x1000, (char *) "Time Zone", (char *) NULL},
- { 0x1001, (char *) "Daylight Savings", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-Pentax maker note type 2
-*/
-static TagInfo
- exif_pentax_tag_table[] =
- {
- { 0x0000, (char *) "PentaxVersion", (char *) NULL},
- { 0x0001, (char *) "PentaxMode", (char *) NULL},
- { 0x0002, (char *) "PreviewImageSize", (char *) NULL},
- { 0x0003, (char *) "PreviewImageLength", (char *) NULL},
- { 0x0004, (char *) "PreviewImageStart", (char *) NULL},
- { 0x0005, (char *) "PentaxModelID", (char *) NULL},
- { 0x0006, (char *) "Date", (char *) NULL},
- { 0x0007, (char *) "Time", (char *) NULL},
- { 0x0008, (char *) "Quality", (char *) NULL},
- { 0x0009, (char *) "PentaxImageSize", (char *) NULL},
- { 0x000B, (char *) "PictureMode", (char *) NULL},
- { 0x000C, (char *) "FlashMode", (char *) NULL},
- { 0x000D, (char *) "FocusMode", (char *) NULL},
- { 0x000E, (char *) "AFPointSelected", (char *) NULL},
- { 0x000F, (char *) "AFPointsInFocus", (char *) NULL},
- { 0x0010, (char *) "FocusPosition", (char *) NULL},
- { 0x0012, (char *) "ExposureTime", (char *) NULL},
- { 0x0013, (char *) "FNumber", (char *) NULL},
- { 0x0014, (char *) "ISO", (char *) NULL},
- { 0x0016, (char *) "ExposureCompensation", (char *) NULL},
- { 0x0017, (char *) "MeteringMode", (char *) NULL},
- { 0x0018, (char *) "AutoBracketing", (char *) NULL},
- { 0x0019, (char *) "WhiteBalance", (char *) NULL},
- { 0x001A, (char *) "WhiteBalanceMode", (char *) NULL},
- { 0x001B, (char *) "BlueBalance", (char *) NULL},
- { 0x001C, (char *) "RedBalance", (char *) NULL},
- { 0x001D, (char *) "FocalLength", (char *) NULL},
- { 0x001E, (char *) "DigitalZoom", (char *) NULL},
- { 0x001F, (char *) "Saturation", (char *) NULL},
- { 0x0020, (char *) "Contrast", (char *) NULL},
- { 0x0021, (char *) "Sharpness", (char *) NULL},
- { 0x0022, (char *) "WorldTimeLocation", (char *) NULL},
- { 0x0023, (char *) "HometownCity", (char *) NULL},
- { 0x0024, (char *) "DestinationCity", (char *) NULL},
- { 0x0025, (char *) "HometownDST", (char *) NULL},
- { 0x0026, (char *) "DestinationDST", (char *) NULL},
- { 0x0027, (char *) "DSPFirmwareVersion", (char *) NULL},
- { 0x0028, (char *) "CPUFirmwareVersion", (char *) NULL},
- { 0x0029, (char *) "FrameNumber", (char *) NULL},
- { 0x002D, (char *) "EffectiveLV", (char *) NULL},
- { 0x0032, (char *) "ImageProcessing", (char *) NULL},
- { 0x0033, (char *) "PictureMode", (char *) NULL},
- { 0x0034, (char *) "DriveMode", (char *) NULL},
- { 0x0035, (char *) "SensorSize", (char *) NULL},
- { 0x0037, (char *) "ColorSpace", (char *) NULL},
- { 0x0039, (char *) "RawImageSize", (char *) NULL},
- { 0x003C, (char *) "AFPointsInFocus", (char *) NULL},
- { 0x003E, (char *) "PreviewImageBorders", (char *) NULL},
- { 0x003F, (char *) "LensType", (char *) NULL},
- { 0x0040, (char *) "SensitivityAdjust", (char *) NULL},
- { 0x0041, (char *) "ImageProcessingCount", (char *) NULL},
- { 0x0047, (char *) "CameraTemperature", (char *) NULL},
- { 0x0048, (char *) "AELock", (char *) NULL},
- { 0x0049, (char *) "NoiseReduction", (char *) NULL},
- { 0x004D, (char *) "FlashExposureComp", (char *) NULL},
- { 0x004F, (char *) "ImageTone", (char *) NULL},
- { 0x0050, (char *) "ColorTemperature", (char *) NULL},
- { 0x005C, (char *) "ShakeReductionInfo", (char *) NULL},
- { 0x005D, (char *) "ShutterCount", (char *) NULL},
- { 0x0069, (char *) "DynamicRangeExpansion", (char *) NULL},
- { 0x0071, (char *) "HighISONoiseReduction", (char *) NULL},
- { 0x0072, (char *) "AFAdjustment", (char *) NULL},
- { 0x0200, (char *) "BlackPoint", (char *) NULL},
- { 0x0201, (char *) "WhitePoint", (char *) NULL},
- { 0x0203, (char *) "ColorMatrixA", (char *) NULL},
- { 0x0204, (char *) "ColorMatrixB", (char *) NULL},
- { 0x0205, (char *) "CameraSettings", (char *) NULL},
- { 0x0206, (char *) "AEInfo", (char *) NULL},
- { 0x0207, (char *) "LensInfo", (char *) NULL},
- { 0x0208, (char *) "FlashInfo", (char *) NULL},
- { 0x0209, (char *) "AEMeteringSegments", (char *) NULL},
- { 0x020A, (char *) "FlashMeteringSegments", (char *) NULL},
- { 0x020B, (char *) "SlaveFlashMeteringSegments", (char *) NULL},
- { 0x020D, (char *) "WB_RGGBLevelsDaylight", (char *) NULL},
- { 0x020E, (char *) "WB_RGGBLevelsShade", (char *) NULL},
- { 0x020F, (char *) "WB_RGGBLevelsCloudy", (char *) NULL},
- { 0x0210, (char *) "WB_RGGBLevelsTungsten", (char *) NULL},
- { 0x0211, (char *) "WB_RGGBLevelsFluorescentD", (char *) NULL},
- { 0x0212, (char *) "WB_RGGBLevelsFluorescentN", (char *) NULL},
- { 0x0213, (char *) "WB_RGGBLevelsFluorescentW", (char *) NULL},
- { 0x0214, (char *) "WB_RGGBLevelsFlash", (char *) NULL},
- { 0x0215, (char *) "CameraInfo", (char *) NULL},
- { 0x0216, (char *) "BatteryInfo", (char *) NULL},
- { 0x021B, (char *) "SaturationInfo", (char *) NULL},
- { 0x021F, (char *) "AFInfo", (char *) NULL},
- { 0x0222, (char *) "ColorInfo", (char *) NULL},
- { 0x0224, (char *) "EVStepInfo", (char *) NULL},
- { 0x03FE, (char *) "DataDump", (char *) NULL},
- { 0x0402, (char *) "ToneCurve", (char *) NULL},
- { 0x0403, (char *) "ToneCurves", (char *) NULL},
- { 0x0E00, (char *) "PrintIM", (char *) NULL},
- { 0x1000, (char *) "HometownCityCode", (char *) NULL},
- { 0x1001, (char *) "DestinationCityCode", (char *) NULL},
- { 0x2000, (char *) "PreviewImageData", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-/**
-Sony maker note
-*/
-static TagInfo
- exif_sony_tag_table[] =
- {
- { 0x0E00, (char *) "PrintIM", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-// --------------------------------------------------------------------------
-// IPTC tags definition
-// --------------------------------------------------------------------------
-
-static TagInfo
- iptc_tag_table[] =
- {
- // IPTC-NAA IIM version 4
- { 0x0200 + 0, (char *) "ApplicationRecordVersion", (char *) "Application Record Version"},
- { 0x0200 + 3, (char *) "ObjectTypeReference", (char *) "Object Type Reference"},
- { 0x0200 + 4, (char *) "ObjectAttributeReference", (char *) "Object Attribute Reference"},
- { 0x0200 + 5, (char *) "ObjectName", (char *) "Title"},
- { 0x0200 + 7, (char *) "EditStatus", (char *) "Edit Status"},
- { 0x0200 + 8, (char *) "EditorialUpdate", (char *) "Editorial Update"},
- { 0x0200 + 10, (char *) "Urgency", (char *) "Urgency"},
- { 0x0200 + 12, (char *) "SubjectReference", (char *) "Subject Reference"},
- { 0x0200 + 15, (char *) "Category", (char *) "Category"},
- { 0x0200 + 20, (char *) "SupplementalCategories", (char *) "Supplemental Categories"},
- { 0x0200 + 22, (char *) "FixtureIdentifier", (char *) "Fixture Identifier"},
- { 0x0200 + 25, (char *) "Keywords", (char *) "Keywords"},
- { 0x0200 + 26, (char *) "ContentLocationCode", (char *) "Content Location Code"},
- { 0x0200 + 27, (char *) "ContentLocationName", (char *) "Content Location Name"},
- { 0x0200 + 30, (char *) "ReleaseDate", (char *) "Release Date"},
- { 0x0200 + 35, (char *) "ReleaseTime", (char *) "Release Time"},
- { 0x0200 + 37, (char *) "ExpirationDate", (char *) "Expiration Date"},
- { 0x0200 + 38, (char *) "ExpirationTime", (char *) "Expiration Time"},
- { 0x0200 + 40, (char *) "SpecialInstructions", (char *) "Instructions"},
- { 0x0200 + 42, (char *) "ActionAdvised", (char *) "Action Advised"},
- { 0x0200 + 45, (char *) "ReferenceService", (char *) "Reference Service"},
- { 0x0200 + 47, (char *) "ReferenceDate", (char *) "Reference Date"},
- { 0x0200 + 50, (char *) "ReferenceNumber", (char *) "Reference Number"},
- { 0x0200 + 55, (char *) "DateCreated", (char *) "Date Created"},
- { 0x0200 + 60, (char *) "TimeCreated", (char *) "Time Created"},
- { 0x0200 + 62, (char *) "DigitalCreationDate", (char *) "Digital Creation Date"},
- { 0x0200 + 63, (char *) "DigitalCreationTime", (char *) "Digital Creation Time"},
- { 0x0200 + 65, (char *) "OriginatingProgram", (char *) "Originating Program"},
- { 0x0200 + 70, (char *) "ProgramVersion", (char *) "Program Version"},
- { 0x0200 + 75, (char *) "ObjectCycle", (char *) "Object Cycle"},
- { 0x0200 + 80, (char *) "By-line", (char *) "Author"},
- { 0x0200 + 85, (char *) "By-lineTitle", (char *) "Author's Position"},
- { 0x0200 + 90, (char *) "City", (char *) "City"},
- { 0x0200 + 92, (char *) "SubLocation", (char *) "Sub-Location"},
- { 0x0200 + 95, (char *) "Province-State", (char *) "State/Province"},
- { 0x0200 + 100, (char *) "Country-PrimaryLocationCode", (char *) "Country Code"},
- { 0x0200 + 101, (char *) "Country-PrimaryLocationName", (char *) "Country Name"},
- { 0x0200 + 103, (char *) "OriginalTransmissionReference", (char *) "Transmission Reference"},
- { 0x0200 + 105, (char *) "Headline", (char *) "Headline"},
- { 0x0200 + 110, (char *) "Credit", (char *) "Credit"},
- { 0x0200 + 115, (char *) "Source", (char *) "Source"},
- { 0x0200 + 116, (char *) "CopyrightNotice", (char *) "Copyright Notice"},
- { 0x0200 + 118, (char *) "Contact", (char *) "Contact"},
- { 0x0200 + 120, (char *) "Caption-Abstract", (char *) "Caption"},
- { 0x0200 + 122, (char *) "Writer-Editor", (char *) "Caption Writer"},
- { 0x0200 + 125, (char *) "RasterizedCaption", (char *) "Rasterized Caption"},
- { 0x0200 + 130, (char *) "ImageType", (char *) "Image Type"},
- { 0x0200 + 131, (char *) "ImageOrientation", (char *) "Image Orientation"},
- { 0x0200 + 135, (char *) "LanguageIdentifier", (char *) "Language Identifier"},
- { 0x0200 + 150, (char *) "AudioType", (char *) "Audio Type"},
- { 0x0200 + 151, (char *) "AudioSamplingRate", (char *) "Audio Sampling Rate"},
- { 0x0200 + 152, (char *) "AudioSamplingResolution", (char *) "Audio Sampling Resolution"},
- { 0x0200 + 153, (char *) "AudioDuration", (char *) "Audio Duration"},
- { 0x0200 + 154, (char *) "AudioOutcue", (char *) "Audio Outcue"},
- // Metadata seen in other softwares (see also http://owl.phy.queensu.ca/~phil/exiftool/TagNames/IPTC.html#ApplicationRecord)
- { 0x0200 + 184, (char *) "JobID", (char *) "Job ID"},
- { 0x0200 + 185, (char *) "MasterDocumentID", (char *) "Master Document ID"},
- { 0x0200 + 186, (char *) "ShortDocumentID", (char *) "Short Document ID"},
- { 0x0200 + 187, (char *) "UniqueDocumentID", (char *) "Unique Document ID"},
- { 0x0200 + 188, (char *) "OwnerID", (char *) "Owner ID"},
- // IPTC-NAA IIM version 4
- { 0x0200 + 200, (char *) "ObjectPreviewFileFormat", (char *) "Object Preview File Format"},
- { 0x0200 + 201, (char *) "ObjectPreviewFileVersion", (char *) "Object Preview File Version"},
- { 0x0200 + 202, (char *) "ObjectPreviewData", (char *) "Audio Outcue"},
- // Metadata seen in other softwares (see also http://owl.phy.queensu.ca/~phil/exiftool/TagNames/IPTC.html#ApplicationRecord)
- { 0x0200 + 221, (char *) "Prefs", (char *) "PhotoMechanic preferences"},
- { 0x0200 + 225, (char *) "ClassifyState", (char *) "Classify State"},
- { 0x0200 + 228, (char *) "SimilarityIndex", (char *) "Similarity Index"},
- { 0x0200 + 230, (char *) "DocumentNotes", (char *) "Document Notes"},
- { 0x0200 + 231, (char *) "DocumentHistory", (char *) "Document History"},
- { 0x0200 + 232, (char *) "ExifCameraInfo", (char *) "Exif Camera Info"},
-
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-// --------------------------------------------------------------------------
-// GeoTIFF tags definition
-// --------------------------------------------------------------------------
-
-static TagInfo
- geotiff_tag_table[] =
- {
- { 0x830E, (char *) "GeoPixelScale", (char *) NULL},
- { 0x8480, (char *) "Intergraph TransformationMatrix", (char *) NULL},
- { 0x8482, (char *) "GeoTiePoints", (char *) NULL},
- { 0x85D7, (char *) "JPL Carto IFD offset", (char *) NULL},
- { 0x85D8, (char *) "GeoTransformationMatrix", (char *) NULL},
- { 0x87AF, (char *) "GeoKeyDirectory", (char *) NULL},
- { 0x87B0, (char *) "GeoDoubleParams", (char *) NULL},
- { 0x87B1, (char *) "GeoASCIIParams", (char *) NULL},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-// --------------------------------------------------------------------------
-// Animation tags definition
-// --------------------------------------------------------------------------
-
-static TagInfo
- animation_tag_table[] =
- {
- { 0x0001, (char *) "LogicalWidth", (char *) "Logical width"},
- { 0x0002, (char *) "LogicalHeight", (char *) "Logical height"},
- { 0x0003, (char *) "GlobalPalette", (char *) "Global Palette"},
- { 0x0004, (char *) "Loop", (char *) "loop"},
- { 0x1001, (char *) "FrameLeft", (char *) "Frame left"},
- { 0x1002, (char *) "FrameTop", (char *) "Frame top"},
- { 0x1003, (char *) "NoLocalPalette", (char *) "No Local Palette"},
- { 0x1004, (char *) "Interlaced", (char *) "Interlaced"},
- { 0x1005, (char *) "FrameTime", (char *) "Frame display time"},
- { 0x1006, (char *) "DisposalMethod", (char *) "Frame disposal method"},
- { 0x0000, (char *) NULL, (char *) NULL}
- };
-
-// --------------------------------------------------------------------------
-// TagLib class definition
-// --------------------------------------------------------------------------
-
-
-/**
-This is where the tag info tables are initialized
-*/
-TagLib::TagLib() {
- // initialize all known metadata models
- // ====================================
-
- // Exif
- addMetadataModel(TagLib::EXIF_MAIN, exif_exif_tag_table);
- addMetadataModel(TagLib::EXIF_EXIF, exif_exif_tag_table);
- addMetadataModel(TagLib::EXIF_GPS, exif_gps_tag_table);
- addMetadataModel(TagLib::EXIF_INTEROP, exif_interop_tag_table);
-
- // Exif maker note
- addMetadataModel(TagLib::EXIF_MAKERNOTE_CANON, exif_canon_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_CASIOTYPE1, exif_casio_type1_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_CASIOTYPE2, exif_casio_type2_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_FUJIFILM, exif_fujifilm_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_KYOCERA, exif_kyocera_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_MINOLTA, exif_minolta_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_NIKONTYPE1, exif_nikon_type1_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_NIKONTYPE2, exif_nikon_type2_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_NIKONTYPE3, exif_nikon_type3_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_OLYMPUSTYPE1, exif_olympus_type1_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_PANASONIC, exif_panasonic_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_ASAHI, exif_asahi_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_PENTAX, exif_pentax_tag_table);
- addMetadataModel(TagLib::EXIF_MAKERNOTE_SONY, exif_sony_tag_table);
-
- // IPTC/NAA
- addMetadataModel(TagLib::IPTC, iptc_tag_table);
-
- // GeoTIFF
- addMetadataModel(TagLib::GEOTIFF, geotiff_tag_table);
-
- // Animation
- addMetadataModel(TagLib::ANIMATION, animation_tag_table);
-}
-
-BOOL TagLib::addMetadataModel(MDMODEL md_model, TagInfo *tag_table) {
- // check that the model doesn't already exist
- if((_table_map.find(md_model) == _table_map.end()) && (tag_table != NULL)) {
-
- // add the tag description table
- TAGINFO *info_map = new(std::nothrow) TAGINFO();
- if(!info_map) return FALSE;
-
- for(int i = 0; ; i++) {
- if((tag_table[i].tag == 0) && (tag_table[i].fieldname == NULL))
- break;
- (*info_map)[tag_table[i].tag] = &tag_table[i];
- }
-
- // add the metadata model
- _table_map[md_model] = info_map;
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-TagLib::~TagLib() {
- // delete metadata models
- for(TABLEMAP::iterator i = _table_map.begin(); i != _table_map.end(); i++) {
- TAGINFO *info_map = (*i).second;
- delete info_map;
- }
-}
-
-
-TagLib&
-TagLib::instance() {
- static TagLib s;
- return s;
-}
-
-const TagInfo*
-TagLib::getTagInfo(MDMODEL md_model, WORD tagID) {
-
- if(_table_map.find(md_model) != _table_map.end()) {
-
- TAGINFO *info_map = (TAGINFO*)_table_map[md_model];
- if(info_map->find(tagID) != info_map->end()) {
- return (*info_map)[tagID];
- }
- }
- return NULL;
-}
-
-const char*
-TagLib::getTagFieldName(MDMODEL md_model, WORD tagID, char *defaultKey) {
-
- const TagInfo *info = getTagInfo(md_model, tagID);
- if(NULL == info) {
- if(defaultKey != NULL) {
- sprintf(defaultKey, "Tag 0x%04X", tagID);
- return &defaultKey[0];
- } else {
- return NULL;
- }
- }
-
- return info->fieldname;
-}
-
-const char*
-TagLib::getTagDescription(MDMODEL md_model, WORD tagID) {
-
- const TagInfo *info = getTagInfo(md_model, tagID);
- if(info) {
- return info->description;
- }
-
- return NULL;
-}
-
-int TagLib::getTagID(MDMODEL md_model, const char *key) {
-
- if(_table_map.find(md_model) != _table_map.end()) {
-
- TAGINFO *info_map = (TAGINFO*)_table_map[md_model];
- for(TAGINFO::iterator i = info_map->begin(); i != info_map->end(); i++) {
- const TagInfo *info = (*i).second;
- if(info && (strcmp(info->fieldname, key) == 0)) {
- return (int)info->tag;
- }
- }
- }
- return -1;
-}
-
-FREE_IMAGE_MDMODEL
-TagLib::getFreeImageModel(MDMODEL model) {
- switch(model) {
- case EXIF_MAIN:
- return FIMD_EXIF_MAIN;
-
- case EXIF_EXIF:
- return FIMD_EXIF_EXIF;
-
- case EXIF_GPS:
- return FIMD_EXIF_GPS;
-
- case EXIF_INTEROP:
- return FIMD_EXIF_INTEROP;
-
- case EXIF_MAKERNOTE_CANON:
- case EXIF_MAKERNOTE_CASIOTYPE1:
- case EXIF_MAKERNOTE_CASIOTYPE2:
- case EXIF_MAKERNOTE_FUJIFILM:
- case EXIF_MAKERNOTE_KYOCERA:
- case EXIF_MAKERNOTE_MINOLTA:
- case EXIF_MAKERNOTE_NIKONTYPE1:
- case EXIF_MAKERNOTE_NIKONTYPE2:
- case EXIF_MAKERNOTE_NIKONTYPE3:
- case EXIF_MAKERNOTE_OLYMPUSTYPE1:
- case EXIF_MAKERNOTE_PANASONIC:
- case EXIF_MAKERNOTE_ASAHI:
- case EXIF_MAKERNOTE_PENTAX:
- case EXIF_MAKERNOTE_SONY:
- return FIMD_EXIF_MAKERNOTE;
-
- case IPTC:
- return FIMD_IPTC;
-
- case GEOTIFF:
- return FIMD_GEOTIFF;
-
- case ANIMATION:
- return FIMD_ANIMATION;
- }
-
- return FIMD_NODATA;
-}
-
+// ==========================================================
+// Tag library
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// Implementation notes :
+// ----------------------
+// The tag info tables declared in this file should probably
+// be loaded from an XML file.
+// This would allow internationalization features and also
+// more extensibility.
+// Maybe in a future release ?
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageTag.h"
+
+/**
+ HOW-TO : add a new TagInfo table
+ --------------------------------------------------------------------------
+ 1) add a table identifier in the TagLib class definition (see enum MDMODEL)
+ 2) declare the tag table as static and use a 0/NULL value as last entry
+ 3) initialize the table in TagLib::TagLib
+ 4) provide a conversion in TagLib::getFreeImageModel
+*/
+
+// --------------------------------------------------------------------------
+// EXIF standard tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ exif_exif_tag_table[] =
+ {
+ { 0x0100, (char *) "ImageWidth", (char *) "Image width"},
+ { 0x0101, (char *) "ImageLength", (char *) "Image height"},
+ { 0x0102, (char *) "BitsPerSample", (char *) "Number of bits per component"},
+ { 0x0103, (char *) "Compression", (char *) "Compression scheme"},
+ { 0x0106, (char *) "PhotometricInterpretation", (char *) "Pixel composition"},
+ { 0x010A, (char *) "FillOrder", (char*) NULL},
+ { 0x010D, (char *) "DocumentName", (char *) NULL},
+ { 0x010E, (char *) "ImageDescription", (char *) "Image title"},
+ { 0x010F, (char *) "Make", (char *) "Image input equipment manufacturer"},
+ { 0x0110, (char *) "Model", (char *) "Image input equipment model"},
+ { 0x0111, (char *) "StripOffsets", (char *) "Image data location"},
+ { 0x0112, (char *) "Orientation", (char *) "Orientation of image"},
+ { 0x0115, (char *) "SamplesPerPixel", (char *) "Number of components"},
+ { 0x0116, (char *) "RowsPerStrip", (char *) "Number of rows per strip"},
+ { 0x0117, (char *) "StripByteCounts", (char *) "Bytes per compressed strip"},
+ { 0x011A, (char *) "XResolution", (char *) "Image resolution in width direction"},
+ { 0x011B, (char *) "YResolution", (char *) "Image resolution in height direction"},
+ { 0x011C, (char *) "PlanarConfiguration", (char *) "Image data arrangement"},
+ { 0x011D, (char *) "PageName", (char *) "Name of the page"},
+ { 0x011E, (char *) "XPosition", (char *) "X position of the image"},
+ { 0x011F, (char *) "YPosition", (char *) "Y position of the image"},
+ { 0x0128, (char *) "ResolutionUnit", (char *) "Unit of X and Y resolution"},
+ { 0x0129, (char *) "PageNumber", (char *) "Page number"},
+ { 0x012D, (char *) "TransferFunction", (char *) "Transfer function"},
+ { 0x0131, (char *) "Software", (char *) "Software used"},
+ { 0x0132, (char *) "DateTime", (char *) "File change date and time"},
+ { 0x013B, (char *) "Artist", (char *) "Person who created the image"},
+ { 0x013C, (char *) "HostComputer", (char *) "Host computer used to generate the image"},
+ { 0x013E, (char *) "WhitePoint", (char *) "White point chromaticity"},
+ { 0x013F, (char *) "PrimaryChromaticities", (char *) "Chromaticities of primaries"},
+ { 0x0156, (char *) "TransferRange", (char *) NULL},
+ { 0x0200, (char *) "JPEGProc", (char *) NULL},
+ { 0x0201, (char *) "JPEGInterchangeFormat", (char *) "Offset to JPEG SOI"},
+ { 0x0202, (char *) "JPEGInterchangeFormatLength", (char *) "Bytes of JPEG data"},
+ { 0x0211, (char *) "YCbCrCoefficients", (char *) "Color space transformation matrix coefficients"},
+ { 0x0212, (char *) "YCbCrSubSampling", (char *) "Subsampling ratio of Y to C"},
+ { 0x0213, (char *) "YCbCrPositioning", (char *) "Y and C positioning"},
+ { 0x0214, (char *) "ReferenceBlackWhite", (char *) "Pair of black and white reference values"},
+ { 0x828D, (char *) "CFARepeatPatternDim", (char *) NULL},
+ { 0x828E, (char *) "CFAPattern", (char *) NULL},
+ { 0x828F, (char *) "BatteryLevel", (char *) NULL},
+ { 0x8298, (char *) "Copyright", (char *) "Copyright holder"},
+ { 0x829A, (char *) "ExposureTime", (char *) "Exposure time"},
+ { 0x829D, (char *) "FNumber", (char *) "F number"},
+ { 0x83BB, (char *) "IPTC/NAA", (char *) NULL},
+ { 0x8773, (char *) "InterColorProfile", (char *) NULL},
+ { 0x8822, (char *) "ExposureProgram", (char *) "Exposure program"},
+ { 0x8824, (char *) "SpectralSensitivity", (char *) "Spectral sensitivity"},
+ { 0x8825, (char *) "GPSInfo", (char *) NULL},
+ { 0x8827, (char *) "ISOSpeedRatings", (char *) "ISO speed rating"},
+ { 0x8828, (char *) "OECF", (char *) "Optoelectric conversion factor"},
+ { 0x9000, (char *) "ExifVersion", (char *) "Exif version"},
+ { 0x9003, (char *) "DateTimeOriginal", (char *) "Date and time of original data generation"},
+ { 0x9004, (char *) "DateTimeDigitized", (char *) "Date and time of digital data generation"},
+ { 0x9101, (char *) "ComponentsConfiguration", (char *) "Meaning of each component"},
+ { 0x9102, (char *) "CompressedBitsPerPixel", (char *) "Image compression mode"},
+ { 0x9201, (char *) "ShutterSpeedValue", (char *) "Shutter speed"},
+ { 0x9202, (char *) "ApertureValue", (char *) "Aperture"},
+ { 0x9203, (char *) "BrightnessValue", (char *) "Brightness"},
+ { 0x9204, (char *) "ExposureBiasValue", (char *) "Exposure bias"},
+ { 0x9205, (char *) "MaxApertureValue", (char *) "Maximum lens aperture"},
+ { 0x9206, (char *) "SubjectDistance", (char *) "Subject distance"},
+ { 0x9207, (char *) "MeteringMode", (char *) "Metering mode"},
+ { 0x9208, (char *) "LightSource", (char *) "Light source"},
+ { 0x9209, (char *) "Flash", (char *) "Flash"},
+ { 0x920A, (char *) "FocalLength", (char *) "Lens focal length"},
+ { 0x9214, (char *) "SubjectArea", (char *) "Subject area"},
+ { 0x927C, (char *) "MakerNote", (char *) "Manufacturer notes"},
+ { 0x9286, (char *) "UserComment", (char *) "User comments"},
+ { 0x9290, (char *) "SubSecTime", (char *) "DateTime subseconds"},
+ { 0x9291, (char *) "SubSecTimeOriginal", (char *) "DateTimeOriginal subseconds"},
+ { 0x9292, (char *) "SubSecTimeDigitized", (char *) "DateTimeDigitized subseconds"},
+ { 0xA000, (char *) "FlashPixVersion", (char *) "Supported Flashpix version"},
+ { 0xA001, (char *) "ColorSpace", (char *) "Color space information"},
+ { 0xA002, (char *) "PixelXDimension", (char *) "Valid image width"},
+ { 0xA003, (char *) "PixelYDimension", (char *) "Valid image height"},
+ { 0xA004, (char *) "RelatedSoundFile", (char *) "Related audio file"},
+ { 0xA005, (char *) "InteroperabilityOffset", (char *) NULL},
+ { 0xA20B, (char *) "FlashEnergy", (char *) "Flash energy"},
+ { 0xA20C, (char *) "SpatialFrequencyResponse", (char *) "Spatial frequency response"},
+ { 0xA20E, (char *) "FocalPlaneXResolution", (char *) "Focal plane X resolution"},
+ { 0xA20F, (char *) "FocalPlaneYResolution", (char *) "Focal plane Y resolution"},
+ { 0xA210, (char *) "FocalPlaneResolutionUnit", (char *) "Focal plane resolution unit"},
+ { 0xA214, (char *) "SubjectLocation", (char *) "Subject location"},
+ { 0xA215, (char *) "ExposureIndex", (char *) "Exposure index"},
+ { 0xA217, (char *) "SensingMethod", (char *) "Sensing method"},
+ { 0xA300, (char *) "FileSrc", (char *) "File source"},
+ { 0xA301, (char *) "SceneType", (char *) "Scene type"},
+ { 0xA302, (char *) "CFAPattern", (char *) "CFA pattern"},
+ { 0xA401, (char *) "CustomRendered", (char *) "Custom image processing"},
+ { 0xA402, (char *) "ExposureMode", (char *) "Exposure mode"},
+ { 0xA403, (char *) "WhiteBalance", (char *) "White balance"},
+ { 0xA404, (char *) "DigitalZoomRatio", (char *) "Digital zoom ratio"},
+ { 0xA405, (char *) "FocalLengthIn35mmFilm", (char *) "Focal length in 35 mm film"},
+ { 0xA406, (char *) "SceneCaptureType", (char *) "Scene capture type"},
+ { 0xA407, (char *) "GainControl", (char *) "Gain control"},
+ { 0xA408, (char *) "Contrast", (char *) "Contrast"},
+ { 0xA409, (char *) "Saturation", (char *) "Saturation"},
+ { 0xA40A, (char *) "Sharpness", (char *) "Sharpness"},
+ { 0xA40B, (char *) "DeviceSettingDescription", (char *) "Device settings description"},
+ { 0xA40C, (char *) "SubjectDistanceRange", (char *) "Subject distance range"},
+ { 0xA420, (char *) "ImageUniqueID", (char *) "Unique image ID"},
+ { 0xA430, (char *) "CameraOwnerName", (char *) "Camera owner name"},
+ { 0xA431, (char *) "BodySerialNumber", (char *) "Body serial number"},
+ { 0xA432, (char *) "LensSpecification", (char *) "Lens specification"},
+ { 0xA433, (char *) "LensMake", (char *) "Lens make"},
+ { 0xA434, (char *) "LensModel", (char *) "Lens model"},
+ { 0xA435, (char *) "LensSerialNumber", (char *) "Lens serial number"},
+
+ // These tags are not part of the Exiv v2.3 specifications but are often loaded by applications as Exif data
+ { 0x4746, (char *) "Rating", (char *) "Rating tag used by Windows"},
+ { 0x4749, (char *) "RatingPercent", (char *) "Rating tag used by Windows, value in percent"},
+ { 0x9C9B, (char *) "XPTitle", (char *) "Title tag used by Windows, encoded in UCS2"},
+ { 0x9C9C, (char *) "XPComment", (char *) "Comment tag used by Windows, encoded in UCS2"},
+ { 0x9C9D, (char *) "XPAuthor", (char *) "Author tag used by Windows, encoded in UCS2"},
+ { 0x9C9E, (char *) "XPKeywords", (char *) "Keywords tag used by Windows, encoded in UCS2"},
+ { 0x9C9F, (char *) "XPSubject", (char *) "Subject tag used by Windows, encoded in UCS2"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// EXIF GPS tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ exif_gps_tag_table[] =
+ {
+ { 0x0000, (char *) "GPSVersionID", (char *) "GPS tag version"},
+ { 0x0001, (char *) "GPSLatitudeRef", (char *) "North or South Latitude"},
+ { 0x0002, (char *) "GPSLatitude", (char *) "Latitude"},
+ { 0x0003, (char *) "GPSLongitudeRef", (char *) "East or West Longitude"},
+ { 0x0004, (char *) "GPSLongitude", (char *) "Longitude"},
+ { 0x0005, (char *) "GPSAltitudeRef", (char *) "Altitude reference"},
+ { 0x0006, (char *) "GPSAltitude", (char *) "Altitude"},
+ { 0x0007, (char *) "GPSTimeStamp", (char *) "GPS time (atomic clock)"},
+ { 0x0008, (char *) "GPSSatellites", (char *) "GPS satellites used for measurement"},
+ { 0x0009, (char *) "GPSStatus", (char *) "GPS receiver status"},
+ { 0x000A, (char *) "GPSMeasureMode", (char *) "GPS measurement mode"},
+ { 0x000B, (char *) "GPSDOP", (char *) "Measurement precision"},
+ { 0x000C, (char *) "GPSSpeedRef", (char *) "Speed unit"},
+ { 0x000D, (char *) "GPSSpeed", (char *) "Speed of GPS receiver"},
+ { 0x000E, (char *) "GPSTrackRef", (char *) "Reference for direction of movement"},
+ { 0x000F, (char *) "GPSTrack", (char *) "Direction of movement"},
+ { 0x0010, (char *) "GPSImgDirectionRef", (char *) "Reference for direction of image"},
+ { 0x0011, (char *) "GPSImgDirection", (char *) "Direction of image"},
+ { 0x0012, (char *) "GPSMapDatum", (char *) "Geodetic survey data used"},
+ { 0x0013, (char *) "GPSDestLatitudeRef", (char *) "Reference for latitude of destination"},
+ { 0x0014, (char *) "GPSDestLatitude", (char *) "Latitude of destination"},
+ { 0x0015, (char *) "GPSDestLongitudeRef", (char *) "Reference for longitude of destination"},
+ { 0x0016, (char *) "GPSDestLongitude", (char *) "Longitude of destination"},
+ { 0x0017, (char *) "GPSDestBearingRef", (char *) "Reference for bearing of destination"},
+ { 0x0018, (char *) "GPSDestBearing", (char *) "Bearing of destination"},
+ { 0x0019, (char *) "GPSDestDistanceRef", (char *) "Reference for distance to destination"},
+ { 0x001A, (char *) "GPSDestDistance", (char *) "Distance to destination"},
+ { 0x001B, (char *) "GPSProcessingMethod", (char *) "Name of GPS processing method"},
+ { 0x001C, (char *) "GPSAreaInformation", (char *) "Name of GPS area"},
+ { 0x001D, (char *) "GPSDateStamp", (char *) "GPS date"},
+ { 0x001E, (char *) "GPSDifferential", (char *) "GPS differential correction"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// EXIF interoperability tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ exif_interop_tag_table[] =
+ {
+ { 0x0001, (char *) "InteroperabilityIndex", (char *) "Interoperability Identification"},
+ { 0x0002, (char *) "InteroperabilityVersion", (char *) "Interoperability version"},
+ { 0x1000, (char *) "RelatedImageFileFormat", (char *) "File format of image file"},
+ { 0x1001, (char *) "RelatedImageWidth", (char *) "Image width"},
+ { 0x1002, (char *) "RelatedImageLength", (char *) "Image height"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// EXIF maker note tags definition
+// --------------------------------------------------------------------------
+
+/**
+Canon maker note
+*/
+static TagInfo
+ exif_canon_tag_table[] =
+ {
+ { 0x0001, (char *) "CanonCameraSettings", (char *) "Canon CameraSettings Tags"},
+ { 0x0002, (char *) "CanonFocalLength", (char *) "Canon FocalLength Tags"},
+ { 0x0003, (char *) "CanonFlashInfo?", (char *) NULL},
+ { 0x0004, (char *) "CanonShotInfo", (char *) "Canon ShotInfo Tags"},
+ { 0x0005, (char *) "CanonPanorama", (char *) "Canon Panorama Tags"},
+ { 0x0006, (char *) "CanonImageType", (char *) NULL},
+ { 0x0007, (char *) "CanonFirmwareVersion", (char *) NULL},
+ { 0x0008, (char *) "FileNumber", (char *) NULL},
+ { 0x0009, (char *) "OwnerName", (char *) NULL},
+ { 0x000A, (char *) "UnknownD30", (char *) "Canon UnknownD30 Tags"},
+ { 0x000C, (char *) "SerialNumber", (char *) NULL},
+ { 0x000D, (char *) "CanonCameraInfo", (char *) "Canon CameraInfo Tags"},
+ { 0x000E, (char *) "CanonFileLength", (char *) NULL},
+ { 0x000F, (char *) "CanonCustomFunctions", (char *) "Custom Functions"},
+ { 0x0010, (char *) "CanonModelID", (char *) NULL},
+ { 0x0012, (char *) "CanonAFInfo", (char *) "Canon AFInfo Tags"},
+ { 0x0013, (char *) "ThumbnailImageValidArea", (char *) NULL},
+ { 0x0015, (char *) "SerialNumberFormat", (char *) NULL},
+ { 0x001A, (char *) "SuperMacro", (char *) NULL},
+ { 0x001C, (char *) "DateStampMode", (char *) NULL},
+ { 0x001D, (char *) "MyColors", (char *) NULL},
+ { 0x001E, (char *) "FirmwareRevision", (char *) NULL},
+ { 0x0023, (char *) "Categories", (char *) NULL},
+ { 0x0024, (char *) "FaceDetect1", (char *) NULL},
+ { 0x0025, (char *) "FaceDetect2", (char *) NULL},
+ { 0x0026, (char *) "CanonAFInfo2", (char *) "Canon AFInfo2 Tags"},
+ { 0x0028, (char *) "ImageUniqueID", (char *) NULL},
+ { 0x0081, (char *) "RawDataOffset", (char *) NULL},
+ { 0x0083, (char *) "OriginalDecisionDataOffset", (char *) NULL},
+ { 0x0090, (char *) "CustomFunctions1D", (char *) "CanonCustom Functions1D Tags"},
+ { 0x0091, (char *) "PersonalFunctions", (char *) "CanonCustom PersonalFuncs Tags"},
+ { 0x0092, (char *) "PersonalFunctionValues", (char *) "CanonCustom PersonalFuncValues Tags"},
+ { 0x0093, (char *) "CanonFileInfo", (char *) "Canon FileInfo Tags"},
+ { 0x0094, (char *) "AFPointsInFocus1D", (char *) NULL},
+ { 0x0095, (char *) "LensModel", (char *) NULL},
+ { 0x0096, (char *) "SerialInfo", (char *) NULL},
+ { 0x0097, (char *) "DustRemovalData", (char *) NULL},
+ { 0x0098, (char *) "CropInfo", (char *) NULL},
+ { 0x0099, (char *) "CustomFunctions2", (char *) NULL},
+ { 0x009A, (char *) "AspectInfo", (char *) NULL},
+ { 0x00A0, (char *) "ProcessingInfo", (char *) NULL},
+ { 0x00A1, (char *) "ToneCurveTable", (char *) NULL},
+ { 0x00A2, (char *) "SharpnessTable", (char *) NULL},
+ { 0x00A3, (char *) "SharpnessFreqTable", (char *) NULL},
+ { 0x00A4, (char *) "WhiteBalanceTable", (char *) NULL},
+ { 0x00A9, (char *) "ColorBalance", (char *) NULL},
+ { 0x00AA, (char *) "MeasuredColor", (char *) NULL},
+ { 0x00AE, (char *) "ColorTemperature", (char *) NULL},
+ { 0x00B0, (char *) "CanonFlags", (char *) NULL},
+ { 0x00B1, (char *) "ModifiedInfo", (char *) NULL},
+ { 0x00B2, (char *) "ToneCurveMatching", (char *) NULL},
+ { 0x00B3, (char *) "WhiteBalanceMatching", (char *) NULL},
+ { 0x00B4, (char *) "ColorSpace", (char *) NULL},
+ { 0x00B6, (char *) "PreviewImageInfo", (char *) NULL},
+ { 0x00D0, (char *) "VRDOffset", (char *) "Offset of VRD 'recipe data' if it exists"},
+ { 0x00E0, (char *) "SensorInfo", (char *) NULL},
+ { 0x4001, (char *) "ColorData", (char *) "Canon ColorData Tags"},
+ { 0x4002, (char *) "CRWParam?", (char *) NULL},
+ { 0x4003, (char *) "ColorInfo", (char *) NULL},
+ { 0x4005, (char *) "Flavor?", (char *) NULL},
+ { 0x4008, (char *) "BlackLevel?", (char *) NULL},
+ { 0x4010, (char *) "CustomPictureStyleFileName", (char *) NULL},
+ { 0x4013, (char *) "AFMicroAdj", (char *) NULL},
+ { 0x4015, (char *) "VignettingCorr", (char *) NULL},
+ { 0x4016, (char *) "VignettingCorr2", (char *) NULL},
+ { 0x4018, (char *) "LightingOpt", (char *) NULL},
+ { 0x4019, (char *) "LensInfo", (char *) NULL},
+ { 0x4020, (char *) "AmbienceInfo", (char *) NULL},
+ { 0x4024, (char *) "FilterInfo", (char *) NULL},
+
+ // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment
+
+ // Fields under tag 0x0001 (we add 0xC100 to make unique tag id)
+ { 0xC100 + 1, (char *) "CameraSettings:MacroMode", (char *) NULL},
+ { 0xC100 + 2, (char *) "CameraSettings:SelfTimer", (char *) NULL},
+ { 0xC100 + 3, (char *) "CameraSettings:Quality", (char *) NULL},
+ { 0xC100 + 4, (char *) "CameraSettings:CanonFlashMode", (char *) NULL},
+ { 0xC100 + 5, (char *) "CameraSettings:ContinuousDrive", (char *) NULL},
+ { 0xC100 + 6, (char *) "CameraSettings:0x0006", (char *) NULL},
+ { 0xC100 + 7, (char *) "CameraSettings:FocusMode", (char *) NULL},
+ { 0xC100 + 8, (char *) "CameraSettings:0x0008", (char *) NULL},
+ { 0xC100 + 9, (char *) "CameraSettings:RecordMode", (char *) NULL},
+ { 0xC100 + 10, (char *) "CameraSettings:CanonImageSize", (char *) NULL},
+ { 0xC100 + 11, (char *) "CameraSettings:EasyMode", (char *) NULL},
+ { 0xC100 + 12, (char *) "CameraSettings:DigitalZoom", (char *) NULL},
+ { 0xC100 + 13, (char *) "CameraSettings:Contrast", (char *) NULL},
+ { 0xC100 + 14, (char *) "CameraSettings:Saturation", (char *) NULL},
+ { 0xC100 + 15, (char *) "CameraSettings:Sharpness", (char *) NULL},
+ { 0xC100 + 16, (char *) "CameraSettings:CameraISO", (char *) NULL},
+ { 0xC100 + 17, (char *) "CameraSettings:MeteringMode", (char *) NULL},
+ { 0xC100 + 18, (char *) "CameraSettings:FocusRange", (char *) NULL},
+ { 0xC100 + 19, (char *) "CameraSettings:AFPoint", (char *) NULL},
+ { 0xC100 + 20, (char *) "CameraSettings:CanonExposureMode", (char *) NULL},
+ { 0xC100 + 21, (char *) "CameraSettings:0x0015", (char *) NULL},
+ { 0xC100 + 22, (char *) "CameraSettings:LensType", (char *) NULL},
+ { 0xC100 + 23, (char *) "CameraSettings:LongFocal", (char *) NULL},
+ { 0xC100 + 24, (char *) "CameraSettings:ShortFocal", (char *) NULL},
+ { 0xC100 + 25, (char *) "CameraSettings:FocalUnits", (char *) "Focal Units per mm"},
+ { 0xC100 + 26, (char *) "CameraSettings:MaxAperture", (char *) NULL},
+ { 0xC100 + 27, (char *) "CameraSettings:MinAperture", (char *) NULL},
+ { 0xC100 + 28, (char *) "CameraSettings:FlashActivity", (char *) NULL},
+ { 0xC100 + 29, (char *) "CameraSettings:FlashBits", (char *) NULL},
+ { 0xC100 + 30, (char *) "CameraSettings:0x001E", (char *) NULL},
+ { 0xC100 + 31, (char *) "CameraSettings:0x001F", (char *) NULL},
+ { 0xC100 + 32, (char *) "CameraSettings:FocusContinuous", (char *) NULL},
+ { 0xC100 + 33, (char *) "CameraSettings:AESetting", (char *) NULL},
+ { 0xC100 + 34, (char *) "CameraSettings:ImageStabilization", (char *) NULL},
+ { 0xC100 + 35, (char *) "CameraSettings:DisplayAperture", (char *) NULL},
+ { 0xC100 + 36, (char *) "CameraSettings:ZoomSourceWidth", (char *) NULL},
+ { 0xC100 + 37, (char *) "CameraSettings:ZoomTargetWidth", (char *) NULL},
+ { 0xC100 + 38, (char *) "CameraSettings:0x0026", (char *) NULL},
+ { 0xC100 + 39, (char *) "CameraSettings:SpotMeteringMode", (char *) NULL},
+ { 0xC100 + 40, (char *) "CameraSettings:PhotoEffect", (char *) NULL},
+ { 0xC100 + 41, (char *) "CameraSettings:ManualFlashOutput", (char *) NULL},
+ { 0xC100 + 42, (char *) "CameraSettings:ColorTone", (char *) NULL},
+ { 0xC100 + 43, (char *) "CameraSettings:0x002B", (char *) NULL},
+ { 0xC100 + 44, (char *) "CameraSettings:0x002C", (char *) NULL},
+ { 0xC100 + 45, (char *) "CameraSettings:0x002D", (char *) NULL},
+ { 0xC100 + 46, (char *) "CameraSettings:SRAWQuality", (char *) NULL},
+ { 0xC100 + 47, (char *) "CameraSettings:0x002F", (char *) NULL},
+ { 0xC100 + 48, (char *) "CameraSettings:0x0030", (char *) NULL},
+
+ // Fields under tag 0x0002 (we add 0xC200 to make unique tag id)
+ { 0xC200 + 0, (char *) "FocalLength:FocalType", (char *) NULL},
+ { 0xC200 + 1, (char *) "FocalLength:FocalLength", (char *) NULL},
+ { 0xC200 + 2, (char *) "FocalLength:FocalPlaneXSize", (char *) NULL},
+ { 0xC200 + 3, (char *) "FocalLength:FocalPlaneYSize", (char *) NULL},
+
+ // Fields under tag 0x0004 (we add 0xC400 to make unique tag id)
+ { 0xC400 + 1, (char *) "ShotInfo:AutoISO", (char *) NULL},
+ { 0xC400 + 2, (char *) "ShotInfo:BaseISO", (char *) NULL},
+ { 0xC400 + 3, (char *) "ShotInfo:MeasuredEV", (char *) NULL},
+ { 0xC400 + 4, (char *) "ShotInfo:TargetAperture", (char *) NULL},
+ { 0xC400 + 5, (char *) "ShotInfo:TargetExposureTime", (char *) NULL},
+ { 0xC400 + 6, (char *) "ShotInfo:ExposureCompensation", (char *) NULL},
+ { 0xC400 + 7, (char *) "ShotInfo:WhiteBalance", (char *) NULL},
+ { 0xC400 + 8, (char *) "ShotInfo:SlowShutter", (char *) NULL},
+ { 0xC400 + 9, (char *) "ShotInfo:SequenceNumber", (char *) NULL},
+ { 0xC400 + 10, (char *) "ShotInfo:OpticalZoomCode", (char *) NULL},
+ { 0xC400 + 11, (char *) "ShotInfo:0x000B", (char *) NULL},
+ { 0xC400 + 12, (char *) "ShotInfo:CameraTemperature", (char *) NULL},
+ { 0xC400 + 13, (char *) "ShotInfo:FlashGuideNumber", (char *) NULL},
+ { 0xC400 + 14, (char *) "ShotInfo:AFPointsInFocus", (char *) NULL},
+ { 0xC400 + 15, (char *) "ShotInfo:FlashExposureComp", (char *) NULL},
+ { 0xC400 + 16, (char *) "ShotInfo:AutoExposureBracketing", (char *) NULL},
+ { 0xC400 + 17, (char *) "ShotInfo:AEBBracketValue", (char *) NULL},
+ { 0xC400 + 18, (char *) "ShotInfo:ControlMode", (char *) NULL},
+ { 0xC400 + 19, (char *) "ShotInfo:FocusDistanceUpper", (char *) NULL},
+ { 0xC400 + 20, (char *) "ShotInfo:FocusDistanceLower", (char *) NULL},
+ { 0xC400 + 21, (char *) "ShotInfo:FNumber", (char *) NULL},
+ { 0xC400 + 22, (char *) "ShotInfo:ExposureTime", (char *) NULL},
+ { 0xC400 + 23, (char *) "ShotInfo:MeasuredEV2", (char *) NULL},
+ { 0xC400 + 24, (char *) "ShotInfo:BulbDuration", (char *) NULL},
+ { 0xC400 + 25, (char *) "ShotInfo:0x0019", (char *) NULL},
+ { 0xC400 + 26, (char *) "ShotInfo:CameraType", (char *) NULL},
+ { 0xC400 + 27, (char *) "ShotInfo:AutoRotate", (char *) NULL},
+ { 0xC400 + 28, (char *) "ShotInfo:NDFilter", (char *) NULL},
+ { 0xC400 + 29, (char *) "ShotInfo:SelfTimer2", (char *) NULL},
+ { 0xC400 + 30, (char *) "ShotInfo:0x001E", (char *) NULL},
+ { 0xC400 + 31, (char *) "ShotInfo:0x001F", (char *) NULL},
+ { 0xC400 + 32, (char *) "ShotInfo:0x0020", (char *) NULL},
+ { 0xC400 + 33, (char *) "ShotInfo:FlashOutput", (char *) NULL},
+
+ // Fields under tag 0x0012 (we add 0x1200 to make unique tag id)
+ { 0x1200 + 0, (char *) "AFInfo:NumAFPoints", (char *) NULL},
+ { 0x1200 + 1, (char *) "AFInfo:ValidAFPoints", (char *) NULL},
+ { 0x1200 + 2, (char *) "AFInfo:CanonImageWidth", (char *) NULL},
+ { 0x1200 + 3, (char *) "AFInfo:CanonImageHeight", (char *) NULL},
+ { 0x1200 + 4, (char *) "AFInfo:AFImageWidth", (char *) NULL},
+ { 0x1200 + 5, (char *) "AFInfo:AFImageHeight", (char *) NULL},
+ { 0x1200 + 6, (char *) "AFInfo:AFAreaWidth", (char *) NULL},
+ { 0x1200 + 7, (char *) "AFInfo:AFAreaHeight", (char *) NULL},
+ { 0x1200 + 8, (char *) "AFInfo:AFAreaXPositions", (char *) NULL},
+ { 0x1200 + 9, (char *) "AFInfo:AFAreaYPositions", (char *) NULL},
+ { 0x1200 + 10, (char *) "AFInfo:AFPointsInFocus", (char *) NULL},
+ { 0x1200 + 11, (char *) "AFInfo:PrimaryAFPoint?", (char *) NULL},
+ { 0x1200 + 12, (char *) "AFInfo:PrimaryAFPoint", (char *) NULL},
+ { 0x1200 + 13, (char *) "AFInfo:0x000D", (char *) NULL},
+ { 0x1200 + 14, (char *) "AFInfo:0x000E", (char *) NULL},
+ { 0x1200 + 15, (char *) "AFInfo:0x000F", (char *) NULL},
+ { 0x1200 + 16, (char *) "AFInfo:0x0010", (char *) NULL},
+ { 0x1200 + 17, (char *) "AFInfo:0x0011", (char *) NULL},
+ { 0x1200 + 18, (char *) "AFInfo:0x0012", (char *) NULL},
+ { 0x1200 + 19, (char *) "AFInfo:0x0013", (char *) NULL},
+ { 0x1200 + 20, (char *) "AFInfo:0x0014", (char *) NULL},
+ { 0x1200 + 21, (char *) "AFInfo:0x0015", (char *) NULL},
+ { 0x1200 + 22, (char *) "AFInfo:0x0016", (char *) NULL},
+ { 0x1200 + 23, (char *) "AFInfo:0x0017", (char *) NULL},
+ { 0x1200 + 24, (char *) "AFInfo:0x0018", (char *) NULL},
+ { 0x1200 + 25, (char *) "AFInfo:0x0019", (char *) NULL},
+ { 0x1200 + 26, (char *) "AFInfo:0x001A", (char *) NULL},
+ { 0x1200 + 27, (char *) "AFInfo:0x001B", (char *) NULL},
+
+ // Fields under tag 0x00A0 (we add 0xCA00 to make unique tag id)
+ { 0xCA00 + 1, (char *) "ProcessingInfo:ToneCurve", (char *) NULL},
+ { 0xCA00 + 2, (char *) "ProcessingInfo:Sharpness", (char *) NULL},
+ { 0xCA00 + 3, (char *) "ProcessingInfo:SharpnessFrequency", (char *) NULL},
+ { 0xCA00 + 4, (char *) "ProcessingInfo:SensorRedLevel", (char *) NULL},
+ { 0xCA00 + 5, (char *) "ProcessingInfo:SensorBlueLevel", (char *) NULL},
+ { 0xCA00 + 6, (char *) "ProcessingInfo:WhiteBalanceRed", (char *) NULL},
+ { 0xCA00 + 7, (char *) "ProcessingInfo:WhiteBalanceBlue", (char *) NULL},
+ { 0xCA00 + 8, (char *) "ProcessingInfo:WhiteBalance", (char *) NULL},
+ { 0xCA00 + 9, (char *) "ProcessingInfo:ColorTemperature", (char *) NULL},
+ { 0xCA00 + 10, (char *) "ProcessingInfo:PictureStyle", (char *) NULL},
+ { 0xCA00 + 11, (char *) "ProcessingInfo:DigitalGain", (char *) NULL},
+ { 0xCA00 + 12, (char *) "ProcessingInfo:WBShiftAB", (char *) NULL},
+ { 0xCA00 + 13, (char *) "ProcessingInfo:WBShiftGM", (char *) NULL},
+
+ // Fields under tag 0x00E0 (we add 0xCE00 to make unique tag id)
+ { 0xCE00 + 1, (char *) "SensorInfo:SensorWidth", (char *) NULL},
+ { 0xCE00 + 2, (char *) "SensorInfo:SensorHeight", (char *) NULL},
+ { 0xCE00 + 3, (char *) "SensorInfo:0x0003", (char *) NULL},
+ { 0xCE00 + 4, (char *) "SensorInfo:0x0004", (char *) NULL},
+ { 0xCE00 + 5, (char *) "SensorInfo:SensorLeftBorder", (char *) NULL},
+ { 0xCE00 + 6, (char *) "SensorInfo:SensorTopBorder", (char *) NULL},
+ { 0xCE00 + 7, (char *) "SensorInfo:SensorRightBorder", (char *) NULL},
+ { 0xCE00 + 8, (char *) "SensorInfo:SensorBottomBorder", (char *) NULL},
+ { 0xCE00 + 9, (char *) "SensorInfo:BlackMaskLeftBorder", (char *) NULL},
+ { 0xCE00 + 10, (char *) "SensorInfo:BlackMaskTopBorder", (char *) NULL},
+ { 0xCE00 + 11, (char *) "SensorInfo:BlackMaskRightBorder", (char *) NULL},
+ { 0xCE00 + 12, (char *) "SensorInfo:BlackMaskBottomBorder", (char *) NULL},
+ { 0xCE00 + 13, (char *) "SensorInfo:0x000D", (char *) NULL},
+ { 0xCE00 + 14, (char *) "SensorInfo:0x000E", (char *) NULL},
+ { 0xCE00 + 15, (char *) "SensorInfo:0x000F", (char *) NULL},
+ { 0xCE00 + 16, (char *) "SensorInfo:0x0010", (char *) NULL},
+
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Casio type 1 maker note
+*/
+static TagInfo
+ exif_casio_type1_tag_table[] =
+ {
+ { 0x0001, (char *) "RecordingMode", (char *) NULL},
+ { 0x0002, (char *) "Quality", (char *) NULL},
+ { 0x0003, (char *) "FocusMode", (char *) NULL},
+ { 0x0004, (char *) "FlashMode", (char *) NULL},
+ { 0x0005, (char *) "FlashIntensity", (char *) NULL},
+ { 0x0006, (char *) "ObjectDistance", (char *) NULL},
+ { 0x0007, (char *) "WhiteBalance", (char *) NULL},
+ { 0x000A, (char *) "DigitalZoom", (char *) NULL},
+ { 0x000B, (char *) "Sharpness", (char *) NULL},
+ { 0x000C, (char *) "Contrast", (char *) NULL},
+ { 0x000D, (char *) "Saturation", (char *) NULL},
+ { 0x0014, (char *) "ISO", (char *) NULL},
+ { 0x0015, (char *) "FirmwareDate", (char *) NULL},
+ { 0x0016, (char *) "Enhancement", (char *) NULL},
+ { 0x0017, (char *) "ColorFilter", (char *) NULL},
+ { 0x0018, (char *) "AFPoint", (char *) NULL},
+ { 0x0019, (char *) "FlashIntensity", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Casio type 2 maker note
+*/
+static TagInfo
+ exif_casio_type2_tag_table[] =
+ {
+ { 0x0002, (char *) "PreviewImageSize", (char *) NULL},
+ { 0x0003, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x0004, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x0008, (char *) "QualityMode", (char *) NULL},
+ { 0x0009, (char *) "CasioImageSize", (char *) NULL},
+ { 0x000D, (char *) "FocusMode", (char *) NULL},
+ { 0x0014, (char *) "ISO", (char *) NULL},
+ { 0x0019, (char *) "WhiteBalance", (char *) NULL},
+ { 0x001D, (char *) "FocalLength", (char *) NULL},
+ { 0x001F, (char *) "Saturation", (char *) NULL},
+ { 0x0020, (char *) "Contrast", (char *) NULL},
+ { 0x0021, (char *) "Sharpness", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x2000, (char *) "PreviewImage", (char *) NULL},
+ { 0x2001, (char *) "FirmwareDate", (char *) NULL},
+ { 0x2011, (char *) "WhiteBalanceBias", (char *) NULL},
+ { 0x2012, (char *) "WhiteBalance", (char *) NULL},
+ { 0x2021, (char *) "AFPointPosition", (char *) NULL},
+ { 0x2022, (char *) "ObjectDistance", (char *) NULL},
+ { 0x2034, (char *) "FlashDistance", (char *) NULL},
+ { 0x2076, (char *) "SpecialEffectMode", (char *) NULL},
+ { 0x3000, (char *) "RecordMode", (char *) NULL},
+ { 0x3001, (char *) "ReleaseMode", (char *) NULL},
+ { 0x3002, (char *) "Quality", (char *) NULL},
+ { 0x3003, (char *) "FocusMode", (char *) NULL},
+ { 0x3006, (char *) "HometownCity", (char *) NULL},
+ { 0x3007, (char *) "BestShotMode", (char *) NULL},
+ { 0x3008, (char *) "AutoISO", (char *) NULL},
+ { 0x3009, (char *) "AFMode", (char *) NULL},
+ { 0x3011, (char *) "Sharpness", (char *) NULL},
+ { 0x3012, (char *) "Contrast", (char *) NULL},
+ { 0x3013, (char *) "Saturation", (char *) NULL},
+ { 0x3014, (char *) "ISO", (char *) NULL},
+ { 0x3015, (char *) "ColorMode", (char *) NULL},
+ { 0x3016, (char *) "Enhancement", (char *) NULL},
+ { 0x3017, (char *) "ColorFilter", (char *) NULL},
+ { 0x301C, (char *) "SequenceNumber", (char *) NULL},
+ { 0x301D, (char *) "BracketSequence", (char *) NULL},
+ { 0x3020, (char *) "ImageStabilization", (char *) NULL},
+ { 0x302A, (char *) "LightingMode", (char *) NULL},
+ { 0x302B, (char *) "PortraitRefiner", (char *) NULL},
+ { 0x3030, (char *) "SpecialEffectLevel", (char *) NULL},
+ { 0x3031, (char *) "SpecialEffectSetting", (char *) NULL},
+ { 0x3103, (char *) "DriveMode", (char *) NULL},
+ { 0x4001, (char *) "CaptureFrameRate", (char *) NULL},
+ { 0x4003, (char *) "VideoQuality", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+FujiFilm maker note
+*/
+static TagInfo
+ exif_fujifilm_tag_table[] =
+ {
+ { 0x0000, (char *) "Version", (char *) NULL},
+ { 0x0010, (char *) "InternalSerialNumber", (char *) NULL},
+ { 0x1000, (char *) "Quality", (char *) NULL},
+ { 0x1001, (char *) "Sharpness", (char *) NULL},
+ { 0x1002, (char *) "WhiteBalance", (char *) NULL},
+ { 0x1003, (char *) "Saturation", (char *) NULL},
+ { 0x1004, (char *) "Contrast", (char *) NULL},
+ { 0x1005, (char *) "ColorTemperature", (char *) NULL},
+ { 0x100A, (char *) "WhiteBalanceFineTune", (char *) NULL},
+ { 0x100B, (char *) "NoiseReduction", (char *) NULL},
+ { 0x1010, (char *) "FujiFlashMode", (char *) NULL},
+ { 0x1011, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x1020, (char *) "Macro", (char *) NULL},
+ { 0x1021, (char *) "FocusMode", (char *) NULL},
+ { 0x1023, (char *) "FocusPixel", (char *) NULL},
+ { 0x1030, (char *) "SlowSync", (char *) NULL},
+ { 0x1031, (char *) "PictureMode", (char *) NULL},
+ { 0x1033, (char *) "EXRAuto", (char *) NULL},
+ { 0x1034, (char *) "EXRMode", (char *) NULL},
+ { 0x1100, (char *) "AutoBracketting", (char *) NULL},
+ { 0x1101, (char *) "SequenceNumber", (char *) NULL},
+ { 0x1210, (char *) "ColorMode", (char *) NULL},
+ { 0x1300, (char *) "BlurWarning", (char *) NULL},
+ { 0x1301, (char *) "FocusWarning", (char *) NULL},
+ { 0x1302, (char *) "ExposureWarning", (char *) NULL},
+ { 0x1400, (char *) "DynamicRange", (char *) NULL},
+ { 0x1401, (char *) "FilmMode", (char *) NULL},
+ { 0x1402, (char *) "DynamicRangeSetting", (char *) NULL},
+ { 0x1403, (char *) "DevelopmentDynamicRange", (char *) NULL},
+ { 0x1404, (char *) "MinFocalLength", (char *) NULL},
+ { 0x1405, (char *) "MaxFocalLength", (char *) NULL},
+ { 0x1406, (char *) "MaxApertureAtMinFocal", (char *) NULL},
+ { 0x1407, (char *) "MaxApertureAtMaxFocal", (char *) NULL},
+ { 0x4100, (char *) "FacesDetected", (char *) NULL},
+ { 0x4103, (char *) "FacePositions", (char *) NULL},
+ { 0x8000, (char *) "FileSource", (char *) NULL},
+ { 0x8002, (char *) "OrderNumber", (char *) NULL},
+ { 0x8003, (char *) "FrameNumber", (char *) NULL},
+ { 0xB211, (char *) "Parallax", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Kyocera maker note
+*/
+static TagInfo
+ exif_kyocera_tag_table[] =
+ {
+ { 0x0001, (char *) "ThumbnailImage", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) "Print Image Matching Info"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Olympus Type 1 / Epson / Agfa maker note
+*/
+static TagInfo
+ exif_olympus_type1_tag_table[] =
+ {
+ { 0x0000, (char *) "MakerNoteVersion", (char *) NULL},
+ { 0x0001, (char *) "MinoltaCameraSettingsOld", (char *) NULL},
+ { 0x0003, (char *) "MinoltaCameraSettings", (char *) NULL},
+ { 0x0040, (char *) "CompressedImageSize", (char *) NULL},
+ { 0x0081, (char *) "PreviewImageData", (char *) NULL},
+ { 0x0088, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x0089, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x0100, (char *) "ThumbnailImage", (char *) NULL},
+ { 0x0104, (char *) "BodyFirmwareVersion", (char *) NULL},
+ { 0x0200, (char *) "SpecialMode", (char *) NULL},
+ { 0x0201, (char *) "Quality", (char *) NULL},
+ { 0x0202, (char *) "Macro", (char *) NULL},
+ { 0x0203, (char *) "BWMode", (char *) NULL},
+ { 0x0204, (char *) "DigitalZoom", (char *) NULL},
+ { 0x0205, (char *) "FocalPlaneDiagonal", (char *) NULL},
+ { 0x0206, (char *) "LensDistortionParams", (char *) NULL},
+ { 0x0207, (char *) "CameraType", (char *) NULL},
+ { 0x0208, (char *) "TextInfo", (char *) "Olympus TextInfo Tags"},
+ { 0x0209, (char *) "CameraID", (char *) NULL},
+ { 0x020B, (char *) "EpsonImageWidth", (char *) NULL},
+ { 0x020C, (char *) "EpsonImageHeight", (char *) NULL},
+ { 0x020D, (char *) "EpsonSoftware", (char *) NULL},
+ { 0x0280, (char *) "PreviewImage", (char *) NULL},
+ { 0x0300, (char *) "PreCaptureFrames", (char *) NULL},
+ { 0x0301, (char *) "WhiteBoard", (char *) NULL},
+ { 0x0302, (char *) "OneTouchWB", (char *) NULL},
+ { 0x0303, (char *) "WhiteBalanceBracket", (char *) NULL},
+ { 0x0304, (char *) "WhiteBalanceBias", (char *) NULL},
+ { 0x0403, (char *) "SceneMode", (char *) NULL},
+ { 0x0404, (char *) "SerialNumber", (char *) NULL},
+ { 0x0405, (char *) "Firmware", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) "PrintIM Tags"},
+ { 0x0F00, (char *) "DataDump", (char *) NULL},
+ { 0x0F01, (char *) "DataDump2", (char *) NULL},
+ { 0x1000, (char *) "ShutterSpeedValue", (char *) NULL},
+ { 0x1001, (char *) "ISOValue", (char *) NULL},
+ { 0x1002, (char *) "ApertureValue", (char *) NULL},
+ { 0x1003, (char *) "BrightnessValue", (char *) NULL},
+ { 0x1004, (char *) "FlashMode", (char *) NULL},
+ { 0x1005, (char *) "FlashDevice", (char *) NULL},
+ { 0x1006, (char *) "ExposureCompensation", (char *) NULL},
+ { 0x1007, (char *) "SensorTemperature", (char *) NULL},
+ { 0x1008, (char *) "LensTemperature", (char *) NULL},
+ { 0x1009, (char *) "LightCondition", (char *) NULL},
+ { 0x100A, (char *) "FocusRange", (char *) NULL},
+ { 0x100B, (char *) "FocusMode", (char *) NULL},
+ { 0x100C, (char *) "ManualFocusDistance", (char *) NULL},
+ { 0x100D, (char *) "ZoomStepCount", (char *) NULL},
+ { 0x100E, (char *) "FocusStepCount", (char *) NULL},
+ { 0x100F, (char *) "Sharpness", (char *) NULL},
+ { 0x1010, (char *) "FlashChargeLevel", (char *) NULL},
+ { 0x1011, (char *) "ColorMatrix", (char *) NULL},
+ { 0x1012, (char *) "BlackLevel", (char *) NULL},
+ { 0x1015, (char *) "WBMode", (char *) NULL},
+ { 0x1017, (char *) "RedBalance", (char *) NULL},
+ { 0x1018, (char *) "BlueBalance", (char *) NULL},
+ { 0x1019, (char *) "ColorMatrixNumber", (char *) NULL},
+ { 0x101A, (char *) "SerialNumber", (char *) NULL},
+ { 0x1023, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x1024, (char *) "InternalFlashTable", (char *) NULL},
+ { 0x1025, (char *) "ExternalFlashGValue", (char *) NULL},
+ { 0x1026, (char *) "ExternalFlashBounce", (char *) NULL},
+ { 0x1027, (char *) "ExternalFlashZoom", (char *) NULL},
+ { 0x1028, (char *) "ExternalFlashMode", (char *) NULL},
+ { 0x1029, (char *) "Contrast", (char *) NULL},
+ { 0x102A, (char *) "SharpnessFactor", (char *) NULL},
+ { 0x102B, (char *) "ColorControl", (char *) NULL},
+ { 0x102C, (char *) "ValidBits", (char *) NULL},
+ { 0x102D, (char *) "CoringFilter", (char *) NULL},
+ { 0x102E, (char *) "OlympusImageWidth", (char *) NULL},
+ { 0x102F, (char *) "OlympusImageHeight", (char *) NULL},
+ { 0x1030, (char *) "SceneDetect", (char *) NULL},
+ { 0x1031, (char *) "SceneArea?", (char *) NULL},
+ { 0x1033, (char *) "SceneDetectData?", (char *) NULL},
+ { 0x1034, (char *) "CompressionRatio", (char *) NULL},
+ { 0x1035, (char *) "PreviewImageValid", (char *) NULL},
+ { 0x1036, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x1037, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x1038, (char *) "AFResult", (char *) NULL},
+ { 0x1039, (char *) "CCDScanMode", (char *) NULL},
+ { 0x103A, (char *) "NoiseReduction", (char *) NULL},
+ { 0x103B, (char *) "InfinityLensStep", (char *) NULL},
+ { 0x103C, (char *) "NearLensStep", (char *) NULL},
+ { 0x103D, (char *) "LightValueCenter", (char *) NULL},
+ { 0x103E, (char *) "LightValuePeriphery", (char *) NULL},
+ { 0x2010, (char *) "Equipment", (char *) "Olympus Equipment Tags"},
+ { 0x2020, (char *) "CameraSettings", (char *) "Olympus CameraSettings Tags"},
+ { 0x2030, (char *) "RawDevelopment", (char *) "Olympus RawDevelopment Tags"},
+ { 0x2040, (char *) "ImageProcessing", (char *) "Olympus ImageProcessing Tags"},
+ { 0x2050, (char *) "FocusInfo", (char *) "Olympus FocusInfo Tags"},
+ { 0x2100, (char *) "Olympus2100", (char *) "Olympus FE Tags"},
+ { 0x2200, (char *) "Olympus2200", (char *) "Olympus FE Tags"},
+ { 0x2300, (char *) "Olympus2300", (char *) "Olympus FE Tags"},
+ { 0x2400, (char *) "Olympus2400", (char *) "Olympus FE Tags"},
+ { 0x2500, (char *) "Olympus2500", (char *) "Olympus FE Tags"},
+ { 0x2600, (char *) "Olympus2600", (char *) "Olympus FE Tags"},
+ { 0x2700, (char *) "Olympus2700", (char *) "Olympus FE Tags"},
+ { 0x2800, (char *) "Olympus2800", (char *) "Olympus FE Tags"},
+ { 0x2900, (char *) "Olympus2900", (char *) "Olympus FE Tags"},
+ { 0x3000, (char *) "RawInfo", (char *) "Olympus RawInfo Tags"},
+ { 0x4000, (char *) "MainInfo", (char *) "Olympus MainInfo Tags"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Minolta maker note
+*/
+static TagInfo
+ exif_minolta_tag_table[] =
+ {
+ { 0x0000, (char *) "MakerNoteVersion", (char *) NULL},
+ { 0x0001, (char *) "MinoltaCameraSettingsOld", (char *) NULL},
+ { 0x0003, (char *) "MinoltaCameraSettings", (char *) NULL},
+ { 0x0004, (char *) "MinoltaCameraSettings7D", (char *) NULL},
+ { 0x0018, (char *) "ImageStabilization", (char *) NULL},
+ { 0x0040, (char *) "CompressedImageSize", (char *) NULL},
+ { 0x0081, (char *) "PreviewImage", (char *) NULL},
+ { 0x0088, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x0089, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x0100, (char *) "SceneMode", (char *) NULL},
+ { 0x0101, (char *) "ColorMode", (char *) NULL},
+ { 0x0102, (char *) "MinoltaQuality", (char *) NULL},
+ { 0x0103, (char *) "MinoltaImageSize", (char *) NULL},
+ { 0x0104, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x0105, (char *) "Teleconverter", (char *) NULL},
+ { 0x0107, (char *) "ImageStabilization", (char *) NULL},
+ { 0x0109, (char *) "RawAndJpgRecording", (char *) NULL},
+ { 0x010A, (char *) "ZoneMatching", (char *) NULL},
+ { 0x010B, (char *) "ColorTemperature", (char *) NULL},
+ { 0x010C, (char *) "LensType", (char *) NULL},
+ { 0x0111, (char *) "ColorCompensationFilter", (char *) NULL},
+ { 0x0112, (char *) "WhiteBalanceFineTune", (char *) NULL},
+ { 0x0113, (char *) "ImageStabilization", (char *) NULL},
+ { 0x0114, (char *) "MinoltaCameraSettings5D", (char *) NULL},
+ { 0x0115, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x0F00, (char *) "MinoltaCameraSettings2", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+There are 3 formats of Nikon's MakerNote. MakerNote of E700/E800/E900/E900S/E910/E950
+starts from ASCII string "Nikon". Data format is the same as IFD, but it starts from
+offset 0x08. This is the same as Olympus except start string.
+*/
+
+/**
+TYPE 1 is for E-Series cameras prior to (not including) E990
+*/
+static TagInfo
+ exif_nikon_type1_tag_table[] =
+ {
+ { 0x0002, (char *) "FamilyID", (char *) NULL},
+ { 0x0003, (char *) "Quality", (char *) NULL},
+ { 0x0004, (char *) "ColorMode", (char *) NULL},
+ { 0x0005, (char *) "ImageAdjustment", (char *) NULL},
+ { 0x0006, (char *) "CCDSensitivity", (char *) NULL},
+ { 0x0007, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0008, (char *) "Focus", (char *) NULL},
+ { 0x000A, (char *) "DigitalZoom", (char *) NULL},
+ { 0x000B, (char *) "FisheyeConverter", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Nikon type 2 maker note
+*/
+static TagInfo
+ exif_nikon_type2_tag_table[] =
+ {
+ { 0x0001, (char *) "MakerNoteVersion", (char *) NULL},
+ { 0x0002, (char *) "ISO", (char *) NULL},
+ { 0x0003, (char *) "ColorMode", (char *) NULL},
+ { 0x0004, (char *) "Quality", (char *) NULL},
+ { 0x0005, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0006, (char *) "Sharpness", (char *) NULL},
+ { 0x0007, (char *) "FocusMode", (char *) NULL},
+ { 0x0008, (char *) "FlashSetting", (char *) NULL},
+ { 0x0009, (char *) "FlashType", (char *) NULL},
+ { 0x000B, (char *) "WhiteBalanceFineTune", (char *) NULL},
+ { 0x000F, (char *) "ISOSelection", (char *) NULL},
+ { 0x0010, (char *) "DataDump", (char *) NULL},
+ { 0x0080, (char *) "ImageAdjustment", (char *) NULL},
+ { 0x0082, (char *) "AuxiliaryLens", (char *) NULL},
+ { 0x0085, (char *) "ManualFocusDistance", (char *) NULL},
+ { 0x0086, (char *) "DigitalZoom", (char *) NULL},
+ { 0x0088, (char *) "AFInfo", (char *) NULL},
+ { 0x0089, (char *) "ShootingMode", (char *) NULL},
+ { 0x008D, (char *) "ColorMode", (char *) NULL},
+ { 0x008F, (char *) "SceneMode", (char *) NULL},
+ { 0x0092, (char *) "HueAdjustment", (char *) NULL},
+ { 0x0094, (char *) "Saturation", (char *) NULL},
+ { 0x0095, (char *) "NoiseReduction", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+The type-3 directory is for D-Series cameras such as the D1 and D100.
+see http://www.timelesswanderings.net/equipment/D100/NEF.html
+*/
+static TagInfo
+ exif_nikon_type3_tag_table[] =
+ {
+ { 0x0001, (char *) "MakerNoteVersion", (char *) NULL},
+ { 0x0002, (char *) "ISO", (char *) NULL},
+ { 0x0003, (char *) "ColorMode", (char *) NULL},
+ { 0x0004, (char *) "Quality", (char *) NULL},
+ { 0x0005, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0006, (char *) "Sharpness", (char *) NULL},
+ { 0x0007, (char *) "FocusMode", (char *) NULL},
+ { 0x0008, (char *) "FlashSetting", (char *) NULL},
+ { 0x0009, (char *) "FlashType", (char *) NULL},
+ { 0x000B, (char *) "WhiteBalanceFineTune", (char *) NULL},
+ { 0x000C, (char *) "WB_RBLevels", (char *) NULL},
+ { 0x000D, (char *) "ProgramShift", (char *) NULL},
+ { 0x000E, (char *) "ExposureDifference", (char *) NULL},
+ { 0x000F, (char *) "ISOSelection", (char *) NULL},
+ { 0x0010, (char *) "DataDump", (char *) NULL},
+ { 0x0011, (char *) "PreviewIFD", (char *) NULL},
+ { 0x0012, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x0013, (char *) "ISOSetting", (char *) NULL},
+ { 0x0014, (char *) "ColorBalanceA", (char *) NULL},
+ { 0x0016, (char *) "ImageBoundary", (char *) NULL},
+ { 0x0017, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x0018, (char *) "FlashExposureBracketValue", (char *) NULL},
+ { 0x0019, (char *) "ExposureBracketValue", (char *) NULL},
+ { 0x001A, (char *) "ImageProcessing", (char *) NULL},
+ { 0x001B, (char *) "CropHiSpeed", (char *) NULL},
+ { 0x001C, (char *) "ExposureTuning", (char *) NULL},
+ { 0x001D, (char *) "SerialNumber", (char *) NULL},
+ { 0x001E, (char *) "ColorSpace", (char *) NULL},
+ { 0x001F, (char *) "VRInfo", (char *) NULL},
+ { 0x0020, (char *) "ImageAuthentication", (char *) NULL},
+ { 0x0022, (char *) "ActiveD-Lighting", (char *) NULL},
+ { 0x0023, (char *) "PictureControl", (char *) NULL},
+ { 0x0024, (char *) "WorldTime", (char *) NULL},
+ { 0x0025, (char *) "ISOInfo", (char *) NULL},
+ { 0x002A, (char *) "VignetteControl", (char *) NULL},
+ { 0x002B, (char *) "DistortInfo", (char *) NULL},
+ { 0x0080, (char *) "ImageAdjustment", (char *) NULL},
+ { 0x0081, (char *) "ToneComp", (char *) NULL},
+ { 0x0082, (char *) "AuxiliaryLens", (char *) NULL},
+ { 0x0083, (char *) "LensType", (char *) NULL},
+ { 0x0084, (char *) "Lens", (char *) NULL},
+ { 0x0085, (char *) "ManualFocusDistance", (char *) NULL},
+ { 0x0086, (char *) "DigitalZoom", (char *) NULL},
+ { 0x0087, (char *) "FlashMode", (char *) NULL},
+ { 0x0088, (char *) "AFInfo", (char *) NULL},
+ { 0x0089, (char *) "ShootingMode", (char *) NULL},
+ { 0x008B, (char *) "LensFStops", (char *) NULL},
+ { 0x008C, (char *) "ContrastCurve", (char *) NULL},
+ { 0x008D, (char *) "ColorHue", (char *) NULL},
+ { 0x008F, (char *) "SceneMode", (char *) NULL},
+ { 0x0090, (char *) "LightSource", (char *) NULL},
+ { 0x0091, (char *) "ShotInfo", (char *) NULL},
+ { 0x0092, (char *) "HueAdjustment", (char *) NULL},
+ { 0x0093, (char *) "NEFCompression", (char *) NULL},
+ { 0x0094, (char *) "Saturation", (char *) NULL},
+ { 0x0095, (char *) "NoiseReduction", (char *) NULL},
+ { 0x0096, (char *) "LinearizationTable", (char *) NULL},
+ { 0x0097, (char *) "ColorBalance", (char *) NULL},
+ { 0x0098, (char *) "LensData", (char *) NULL},
+ { 0x0099, (char *) "RawImageCenter", (char *) NULL},
+ { 0x009A, (char *) "SensorPixelSize", (char *) NULL},
+ { 0x009C, (char *) "SceneAssist", (char *) NULL},
+ { 0x009E, (char *) "RetouchHistory", (char *) NULL},
+ { 0x00A0, (char *) "SerialNumber", (char *) NULL},
+ { 0x00A2, (char *) "ImageDataSize", (char *) NULL},
+ { 0x00A5, (char *) "ImageCount", (char *) NULL},
+ { 0x00A6, (char *) "DeletedImageCount", (char *) NULL},
+ { 0x00A7, (char *) "ShutterCount", (char *) NULL},
+ { 0x00A8, (char *) "FlashInfo", (char *) NULL},
+ { 0x00A9, (char *) "ImageOptimization", (char *) NULL},
+ { 0x00AA, (char *) "Saturation", (char *) NULL},
+ { 0x00AB, (char *) "VariProgram", (char *) NULL},
+ { 0x00AC, (char *) "ImageStabilization", (char *) NULL},
+ { 0x00AD, (char *) "AFResponse", (char *) NULL},
+ { 0x00B0, (char *) "MultiExposure", (char *) NULL},
+ { 0x00B1, (char *) "HighISONoiseReduction", (char *) NULL},
+ { 0x00B3, (char *) "ToningEffect", (char *) NULL},
+ { 0x00B6, (char *) "PowerUpTime", (char *) NULL},
+ { 0x00B7, (char *) "AFInfo2", (char *) NULL},
+ { 0x00B8, (char *) "FileInfo", (char *) NULL},
+ { 0x00B9, (char *) "AFTune", (char *) NULL},
+ { 0x00BD, (char *) "PictureControl", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x0E01, (char *) "NikonCaptureData", (char *) NULL},
+ { 0x0E09, (char *) "NikonCaptureVersion", (char *) NULL},
+ { 0x0E0E, (char *) "NikonCaptureOffsets", (char *) NULL},
+ { 0x0E10, (char *) "NikonScanIFD", (char *) NULL},
+ { 0x0E1D, (char *) "NikonICCProfile", (char *) NULL},
+ { 0x0E1E, (char *) "NikonCaptureOutput", (char *) NULL},
+ { 0x0E22, (char *) "NEFBitDepth", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Panasonic / Leica maker note
+*/
+static TagInfo
+ exif_panasonic_tag_table[] =
+ {
+ { 0x0001, (char *) "ImageQuality", (char *) NULL},
+ { 0x0002, (char *) "FirmwareVersion", (char *) NULL},
+ { 0x0003, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0007, (char *) "FocusMode", (char *) NULL},
+ { 0x000F, (char *) "AFAreaMode", (char *) NULL},
+ { 0x001A, (char *) "ImageStabilization", (char *) NULL},
+ { 0x001C, (char *) "MacroMode", (char *) NULL},
+ { 0x001F, (char *) "ShootingMode", (char *) NULL},
+ { 0x0020, (char *) "Audio", (char *) NULL},
+ { 0x0021, (char *) "DataDump", (char *) NULL},
+ { 0x0022, (char *) "EasyMode", (char *) NULL},
+ { 0x0023, (char *) "WhiteBalanceBias", (char *) NULL},
+ { 0x0024, (char *) "FlashBias", (char *) NULL},
+ { 0x0025, (char *) "InternalSerialNumber", (char *) NULL},
+ { 0x0026, (char *) "PanasonicExifVersion", (char *) NULL},
+ { 0x0028, (char *) "ColorEffect", (char *) NULL},
+ { 0x0029, (char *) "TimeSincePowerOn", (char *) NULL},
+ { 0x002A, (char *) "BurstMode", (char *) NULL},
+ { 0x002B, (char *) "SequenceNumber", (char *) NULL},
+ { 0x002C, (char *) "ContrastMode", (char *) NULL},
+ { 0x002D, (char *) "NoiseReduction", (char *) NULL},
+ { 0x002E, (char *) "SelfTimer", (char *) NULL},
+ { 0x0030, (char *) "Rotation", (char *) NULL},
+ { 0x0031, (char *) "AFAssistLamp", (char *) NULL},
+ { 0x0032, (char *) "ColorMode", (char *) NULL},
+ { 0x0033, (char *) "BabyAge_0x0033", (char *) NULL},
+ { 0x0034, (char *) "OpticalZoomMode", (char *) NULL},
+ { 0x0035, (char *) "ConversionLens", (char *) NULL},
+ { 0x0036, (char *) "TravelDay", (char *) NULL},
+ { 0x0039, (char *) "Contrast", (char *) NULL},
+ { 0x003A, (char *) "WorldTimeLocation", (char *) NULL},
+ { 0x003B, (char *) "TextStamp_0x003B", (char *) NULL},
+ { 0x003C, (char *) "ProgramISO", (char *) NULL},
+ { 0x003D, (char *) "AdvancedSceneMode", (char *) NULL},
+ { 0x003E, (char *) "TextStamp_0x003E", (char *) NULL},
+ { 0x003F, (char *) "FacesDetected", (char *) NULL},
+ { 0x0040, (char *) "Saturation", (char *) NULL},
+ { 0x0041, (char *) "Sharpness", (char *) NULL},
+ { 0x0042, (char *) "FilmMode", (char *) NULL},
+ { 0x0046, (char *) "WBAdjustAB", (char *) NULL},
+ { 0x0047, (char *) "WBAdjustGM", (char *) NULL},
+ { 0x004B, (char *) "PanasonicImageWidth", (char *) NULL},
+ { 0x004C, (char *) "PanasonicImageHeight", (char *) NULL},
+ { 0x004D, (char *) "AFPointPosition", (char *) NULL},
+ { 0x004E, (char *) "FaceDetInfo", (char *) "Panasonic FaceDetInfo Tags"},
+ { 0x0051, (char *) "LensType", (char *) NULL},
+ { 0x0052, (char *) "LensSerialNumber", (char *) NULL},
+ { 0x0053, (char *) "AccessoryType", (char *) NULL},
+ { 0x0059, (char *) "Transform", (char *) NULL},
+ { 0x005D, (char *) "IntelligentExposure", (char *) NULL},
+ { 0x0061, (char *) "FaceRecInfo", (char *) "Panasonic FaceRecInfo Tags"},
+ { 0x0062, (char *) "FlashWarning", (char *) NULL},
+ { 0x0063, (char *) "RecognizedFaceFlags?", (char *) NULL},
+ { 0x0065, (char *) "Title", (char *) NULL},
+ { 0x0066, (char *) "BabyName", (char *) NULL},
+ { 0x0067, (char *) "Location", (char *) NULL},
+ { 0x0069, (char *) "Country", (char *) NULL},
+ { 0x006B, (char *) "State", (char *) NULL},
+ { 0x006D, (char *) "City", (char *) NULL},
+ { 0x006F, (char *) "Landmark", (char *) NULL},
+ { 0x0070, (char *) "IntelligentResolution", (char *) NULL},
+ { 0x0079, (char *) "IntelligentD-Range", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x8000, (char *) "MakerNoteVersion", (char *) NULL},
+ { 0x8001, (char *) "SceneMode", (char *) NULL},
+ { 0x8004, (char *) "WBRedLevel", (char *) NULL},
+ { 0x8005, (char *) "WBGreenLevel", (char *) NULL},
+ { 0x8006, (char *) "WBBlueLevel", (char *) NULL},
+ { 0x8007, (char *) "FlashFired", (char *) NULL},
+ { 0x8008, (char *) "TextStamp_0x8008", (char *) NULL},
+ { 0x8009, (char *) "TextStamp_0x8009", (char *) NULL},
+ { 0x8010, (char *) "BabyAge_0x8010", (char *) NULL},
+ { 0x8012, (char *) "Transform", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Pentax (Asahi) maker note type 1
+*/
+static TagInfo
+ exif_asahi_tag_table[] =
+ {
+ { 0x0001, (char *) "Capture Mode", (char *) NULL},
+ { 0x0002, (char *) "Quality Level", (char *) NULL},
+ { 0x0003, (char *) "Focus Mode", (char *) NULL},
+ { 0x0004, (char *) "Flash Mode", (char *) NULL},
+ { 0x0007, (char *) "White Balance", (char *) NULL},
+ { 0x000A, (char *) "Digital Zoom", (char *) NULL},
+ { 0x000B, (char *) "Sharpness", (char *) NULL},
+ { 0x000C, (char *) "Contrast", (char *) NULL},
+ { 0x000D, (char *) "Saturation", (char *) NULL},
+ { 0x0014, (char *) "ISO Speed", (char *) NULL},
+ { 0x0017, (char *) "Color", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x1000, (char *) "Time Zone", (char *) NULL},
+ { 0x1001, (char *) "Daylight Savings", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Pentax maker note type 2
+*/
+static TagInfo
+ exif_pentax_tag_table[] =
+ {
+ { 0x0000, (char *) "PentaxVersion", (char *) NULL},
+ { 0x0001, (char *) "PentaxMode", (char *) NULL},
+ { 0x0002, (char *) "PreviewImageSize", (char *) NULL},
+ { 0x0003, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x0004, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x0005, (char *) "PentaxModelID", (char *) "Pentax PentaxModelID Values"},
+ { 0x0006, (char *) "Date", (char *) NULL},
+ { 0x0007, (char *) "Time", (char *) NULL},
+ { 0x0008, (char *) "Quality", (char *) NULL},
+ { 0x0009, (char *) "PentaxImageSize", (char *) NULL},
+ { 0x000B, (char *) "PictureMode", (char *) NULL},
+ { 0x000C, (char *) "FlashMode", (char *) NULL},
+ { 0x000D, (char *) "FocusMode", (char *) NULL},
+ { 0x000E, (char *) "AFPointSelected", (char *) NULL},
+ { 0x000F, (char *) "AFPointsInFocus", (char *) NULL},
+ { 0x0010, (char *) "FocusPosition", (char *) NULL},
+ { 0x0012, (char *) "ExposureTime", (char *) NULL},
+ { 0x0013, (char *) "FNumber", (char *) NULL},
+ { 0x0014, (char *) "ISO", (char *) NULL},
+ { 0x0015, (char *) "LightReading", (char *) NULL},
+ { 0x0016, (char *) "ExposureCompensation", (char *) NULL},
+ { 0x0017, (char *) "MeteringMode", (char *) NULL},
+ { 0x0018, (char *) "AutoBracketing", (char *) NULL},
+ { 0x0019, (char *) "WhiteBalance", (char *) NULL},
+ { 0x001A, (char *) "WhiteBalanceMode", (char *) NULL},
+ { 0x001B, (char *) "BlueBalance", (char *) NULL},
+ { 0x001C, (char *) "RedBalance", (char *) NULL},
+ { 0x001D, (char *) "FocalLength", (char *) NULL},
+ { 0x001E, (char *) "DigitalZoom", (char *) NULL},
+ { 0x001F, (char *) "Saturation", (char *) NULL},
+ { 0x0020, (char *) "Contrast", (char *) NULL},
+ { 0x0021, (char *) "Sharpness", (char *) NULL},
+ { 0x0022, (char *) "WorldTimeLocation", (char *) NULL},
+ { 0x0023, (char *) "HometownCity", (char *) "Pentax City Values"},
+ { 0x0024, (char *) "DestinationCity", (char *) "Pentax City Values"},
+ { 0x0025, (char *) "HometownDST", (char *) NULL},
+ { 0x0026, (char *) "DestinationDST", (char *) NULL},
+ { 0x0027, (char *) "DSPFirmwareVersion", (char *) NULL},
+ { 0x0028, (char *) "CPUFirmwareVersion", (char *) NULL},
+ { 0x0029, (char *) "FrameNumber", (char *) NULL},
+ { 0x002D, (char *) "EffectiveLV", (char *) NULL},
+ { 0x0032, (char *) "ImageProcessing", (char *) NULL},
+ { 0x0033, (char *) "PictureMode", (char *) NULL},
+ { 0x0034, (char *) "DriveMode", (char *) NULL},
+ { 0x0035, (char *) "SensorSize", (char *) NULL},
+ { 0x0037, (char *) "ColorSpace", (char *) NULL},
+ { 0x0039, (char *) "RawImageSize", (char *) NULL},
+ { 0x003C, (char *) "AFPointsInFocus", (char *) NULL},
+ { 0x003E, (char *) "PreviewImageBorders", (char *) NULL},
+ { 0x003F, (char *) "LensType", (char *) "Pentax LensType Values"},
+ { 0x0040, (char *) "SensitivityAdjust", (char *) NULL},
+ { 0x0041, (char *) "ImageProcessingCount", (char *) NULL},
+ { 0x0047, (char *) "CameraTemperature", (char *) NULL},
+ { 0x0048, (char *) "AELock", (char *) NULL},
+ { 0x0049, (char *) "NoiseReduction", (char *) NULL},
+ { 0x004D, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x004F, (char *) "ImageTone", (char *) NULL},
+ { 0x0050, (char *) "ColorTemperature", (char *) NULL},
+ { 0x005C, (char *) "ShakeReductionInfo", (char *) "Pentax SRInfo Tags"},
+ { 0x005D, (char *) "ShutterCount", (char *) NULL},
+ { 0x0060, (char *) "FaceInfo", (char *) "Pentax FaceInfo Tags"},
+ { 0x0067, (char *) "Hue", (char *) NULL},
+ { 0x0068, (char *) "AWBInfo", (char *) "Pentax AWBInfo Tags"},
+ { 0x0069, (char *) "DynamicRangeExpansion", (char *) NULL},
+ { 0x006B, (char *) "TimeInfo", (char *) "Pentax TimeInfo Tags"},
+ { 0x006C, (char *) "HighLowKeyAdj", (char *) NULL},
+ { 0x006D, (char *) "ContrastHighlight", (char *) NULL},
+ { 0x006E, (char *) "ContrastShadow", (char *) NULL},
+ { 0x006F, (char *) "ContrastHighlightShadowAdj", (char *) NULL},
+ { 0x0070, (char *) "FineSharpness", (char *) NULL},
+ { 0x0071, (char *) "HighISONoiseReduction", (char *) NULL},
+ { 0x0072, (char *) "AFAdjustment", (char *) NULL},
+ { 0x0073, (char *) "MonochromeFilterEffect", (char *) NULL},
+ { 0x0074, (char *) "MonochromeToning", (char *) NULL},
+ { 0x0076, (char *) "FaceDetect", (char *) NULL},
+ { 0x0077, (char *) "FaceDetectFrameSize", (char *) NULL},
+ { 0x0079, (char *) "ShadowCompensation", (char *) NULL},
+ { 0x007A, (char *) "ISOAutoParameters", (char *) NULL},
+ { 0x007B, (char *) "CrossProcess", (char *) NULL},
+ { 0x007D, (char *) "LensCorr", (char *) "Pentax LensCorr Tags"},
+ { 0x007F, (char *) "BleachBypassToning", (char *) NULL},
+ { 0x0200, (char *) "BlackPoint", (char *) NULL},
+ { 0x0201, (char *) "WhitePoint", (char *) NULL},
+ { 0x0203, (char *) "ColorMatrixA", (char *) NULL},
+ { 0x0204, (char *) "ColorMatrixB", (char *) NULL},
+ { 0x0205, (char *) "CameraSettings", (char *) "Pentax CameraSettings Tags"},
+ { 0x0206, (char *) "AEInfo", (char *) "Pentax AEInfo Tags"},
+ { 0x0207, (char *) "LensInfo", (char *) "Pentax LensInfo Tags"},
+ { 0x0208, (char *) "FlashInfo", (char *) "Pentax FlashInfo Tags"},
+ { 0x0209, (char *) "AEMeteringSegments", (char *) NULL},
+ { 0x020A, (char *) "FlashMeteringSegments", (char *) NULL},
+ { 0x020B, (char *) "SlaveFlashMeteringSegments", (char *) NULL},
+ { 0x020D, (char *) "WB_RGGBLevelsDaylight", (char *) NULL},
+ { 0x020E, (char *) "WB_RGGBLevelsShade", (char *) NULL},
+ { 0x020F, (char *) "WB_RGGBLevelsCloudy", (char *) NULL},
+ { 0x0210, (char *) "WB_RGGBLevelsTungsten", (char *) NULL},
+ { 0x0211, (char *) "WB_RGGBLevelsFluorescentD", (char *) NULL},
+ { 0x0212, (char *) "WB_RGGBLevelsFluorescentN", (char *) NULL},
+ { 0x0213, (char *) "WB_RGGBLevelsFluorescentW", (char *) NULL},
+ { 0x0214, (char *) "WB_RGGBLevelsFlash", (char *) NULL},
+ { 0x0215, (char *) "CameraInfo", (char *) "Pentax CameraInfo Tags"},
+ { 0x0216, (char *) "BatteryInfo", (char *) "Pentax BatteryInfo Tags"},
+ { 0x021B, (char *) "SaturationInfo", (char *) NULL},
+ { 0x021F, (char *) "AFInfo", (char *) "Pentax AFInfo Tags"},
+ { 0x0222, (char *) "ColorInfo", (char *) "Pentax ColorInfo Tags"},
+ { 0x0224, (char *) "EVStepInfo", (char *) "Pentax EVStepInfo Tags"},
+ { 0x0226, (char *) "ShotInfo", (char *) "Pentax ShotInfo Tags"},
+ { 0x0227, (char *) "FacePos", (char *) "Pentax FacePos Tags"},
+ { 0x0228, (char *) "FaceSize", (char *) "Pentax FaceSize Tags"},
+ { 0x0229, (char *) "SerialNumber", (char *) NULL},
+ { 0x022A, (char *) "FilterInfo", (char *) "Pentax FilterInfo Tags"},
+ { 0x022B, (char *) "LevelInfo", (char *) "Pentax LevelInfo Tags"},
+ { 0x022E, (char *) "Artist", (char *) NULL},
+ { 0x022F, (char *) "Copyright", (char *) NULL},
+ { 0x0230, (char *) "FirmwareVersion", (char *) NULL},
+ { 0x0231, (char *) "ContrastDetectAFArea", (char *) NULL},
+ { 0x0235, (char *) "CrossProcessParams", (char *) NULL},
+ { 0x03FE, (char *) "DataDump", (char *) NULL},
+ { 0x0402, (char *) "ToneCurve", (char *) NULL},
+ { 0x0403, (char *) "ToneCurves", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x1000, (char *) "HometownCityCode", (char *) NULL},
+ { 0x1001, (char *) "DestinationCityCode", (char *) NULL},
+ { 0x2000, (char *) "PreviewImageData", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Sony maker note
+*/
+static TagInfo
+ exif_sony_tag_table[] =
+ {
+ { 0x0102, (char *) "Quality", (char *) NULL},
+ { 0x0104, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x0105, (char *) "Teleconverter", (char *) NULL},
+ { 0x0112, (char *) "WhiteBalanceFineTune", (char *) NULL},
+ { 0x0114, (char *) "CameraSettings", (char *) NULL},
+ { 0x0115, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x1000, (char *) "MultiBurstMode", (char *) NULL},
+ { 0x1001, (char *) "MultiBurstImageWidth", (char *) NULL},
+ { 0x1002, (char *) "MultiBurstImageHeight", (char *) NULL},
+ { 0x1003, (char *) "Panorama", (char *) NULL},
+ { 0x2001, (char *) "PreviewImage", (char *) NULL},
+ { 0x2004, (char *) "Contrast", (char *) NULL},
+ { 0x2005, (char *) "Saturation", (char *) NULL},
+ { 0x2006, (char *) "Sharpness", (char *) NULL},
+ { 0x2007, (char *) "Brightness", (char *) NULL},
+ { 0x2008, (char *) "LongExposureNoiseReduction", (char *) NULL},
+ { 0x2009, (char *) "HighISONoiseReduction", (char *) NULL},
+ { 0x200A, (char *) "HDR", (char *) NULL},
+ { 0x200B, (char *) "MultiFrameNoiseReduction", (char *) NULL},
+ { 0x3000, (char *) "ShotInfo", (char *) NULL},
+ { 0xB000, (char *) "FileFormat", (char *) NULL},
+ { 0xB001, (char *) "SonyModelID", (char *) NULL},
+ { 0xB020, (char *) "ColorReproduction", (char *) NULL},
+ { 0xB021, (char *) "ColorTemperature", (char *) NULL},
+ { 0xB022, (char *) "ColorCompensationFilter", (char *) NULL},
+ { 0xB023, (char *) "SceneMode", (char *) NULL},
+ { 0xB024, (char *) "ZoneMatching", (char *) NULL},
+ { 0xB025, (char *) "DynamicRangeOptimizer", (char *) NULL},
+ { 0xB026, (char *) "ImageStabilization", (char *) NULL},
+ { 0xB027, (char *) "LensType", (char *) NULL},
+ { 0xB028, (char *) "MinoltaMakerNote", (char *) NULL},
+ { 0xB029, (char *) "ColorMode", (char *) NULL},
+ { 0xB02B, (char *) "FullImageSize", (char *) NULL},
+ { 0xB02C, (char *) "PreviewImageSize", (char *) NULL},
+ { 0xB040, (char *) "Macro", (char *) NULL},
+ { 0xB041, (char *) "ExposureMode", (char *) NULL},
+ { 0xB042, (char *) "FocusMode", (char *) NULL},
+ { 0xB043, (char *) "AFMode", (char *) NULL},
+ { 0xB044, (char *) "AFIlluminator", (char *) NULL},
+ { 0xB047, (char *) "Quality2", (char *) NULL},
+ { 0xB048, (char *) "FlashLevel", (char *) NULL},
+ { 0xB049, (char *) "ReleaseMode", (char *) NULL},
+ { 0xB04A, (char *) "SequenceNumber", (char *) NULL},
+ { 0xB04B, (char *) "Anti-Blur", (char *) NULL},
+ { 0xB04E, (char *) "LongExposureNoiseReduction", (char *) NULL},
+ { 0xB04F, (char *) "DynamicRangeOptimizer", (char *) NULL},
+ { 0xB052, (char *) "IntelligentAuto", (char *) NULL},
+ { 0xB054, (char *) "WhiteBalance2", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Sigma SD1 maker note
+*/
+static TagInfo
+ exif_sigma_sd1_tag_table[] =
+ {
+ { 0x0002, (char *) "SerialNumber", (char *) NULL},
+ { 0x0003, (char *) "DriveMode", (char *) NULL},
+ { 0x0004, (char *) "ResolutionMode", (char *) NULL},
+ { 0x0005, (char *) "AFMode", (char *) NULL},
+ { 0x0006, (char *) "FocusSetting", (char *) NULL},
+ { 0x0007, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0008, (char *) "ExposureMode", (char *) NULL},
+ { 0x0009, (char *) "MeteringMode", (char *) NULL},
+ { 0x000A, (char *) "LensFocalRange", (char *) NULL},
+ { 0x000B, (char *) "ColorSpace", (char *) NULL},
+ { 0x000C, (char *) "ExposureCompensation", (char *) NULL},
+ { 0x000D, (char *) "Contrast", (char *) NULL},
+ { 0x000E, (char *) "Shadow", (char *) NULL},
+ { 0x000F, (char *) "Highlight", (char *) NULL},
+ { 0x0010, (char *) "Saturation", (char *) NULL},
+ { 0x0011, (char *) "Sharpness", (char *) NULL},
+ { 0x0012, (char *) "X3FillLight", (char *) NULL},
+ { 0x0014, (char *) "ColorAdjustment", (char *) NULL},
+ { 0x0015, (char *) "AdjustmentMode", (char *) NULL},
+ { 0x0016, (char *) "Quality", (char *) NULL},
+ { 0x0017, (char *) "Firmware", (char *) NULL},
+ { 0x0018, (char *) "Software", (char *) NULL},
+ { 0x0019, (char *) "AutoBracket", (char *) NULL},
+ { 0x001A, (char *) "ChrominanceNoiseReduction", (char *) NULL},
+ { 0x001B, (char *) "LuminanceNoiseReduction", (char *) NULL},
+ { 0x001C, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x001D, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x001F, (char *) "MakerNoteVersion", (char *) NULL},
+ { 0x0026, (char *) "FileFormat", (char *) NULL},
+ { 0x002C, (char *) "ColorMode", (char *) NULL},
+ { 0x0030, (char *) "Calibration", (char *) NULL},
+ { 0x0048, (char *) "LensApertureRange", (char *) NULL},
+ { 0x0049, (char *) "FNumber", (char *) NULL},
+ { 0x004A, (char *) "ExposureTime", (char *) NULL},
+ { 0x004B, (char *) "ExposureTime2", (char *) NULL},
+ { 0x004D, (char *) "ExposureCompensation_SD1", (char *) NULL},
+ { 0x0055, (char *) "SensorTemperature", (char *) NULL},
+ { 0x0056, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x0057, (char *) "Firmware_SD1", (char *) NULL},
+ { 0x0058, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Sigma / Foveon maker note (others than SD1 models)
+NB: many tags are not consistent between different models
+*/
+static TagInfo
+ exif_sigma_foveon_tag_table[] =
+ {
+ { 0x0002, (char *) "SerialNumber", (char *) NULL},
+ { 0x0003, (char *) "DriveMode", (char *) NULL},
+ { 0x0004, (char *) "ResolutionMode", (char *) NULL},
+ { 0x0005, (char *) "AFMode", (char *) NULL},
+ { 0x0006, (char *) "FocusSetting", (char *) NULL},
+ { 0x0007, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0008, (char *) "ExposureMode", (char *) NULL},
+ { 0x0009, (char *) "MeteringMode", (char *) NULL},
+ { 0x000A, (char *) "LensFocalRange", (char *) NULL},
+ { 0x000B, (char *) "ColorSpace", (char *) NULL},
+ { 0x000C, (char *) "ExposureCompensation", (char *) NULL},
+ { 0x000D, (char *) "Contrast", (char *) NULL},
+ { 0x000E, (char *) "Shadow", (char *) NULL},
+ { 0x000F, (char *) "Highlight", (char *) NULL},
+ { 0x0010, (char *) "Saturation", (char *) NULL},
+ { 0x0011, (char *) "Sharpness", (char *) NULL},
+ { 0x0012, (char *) "X3FillLight", (char *) NULL},
+ { 0x0014, (char *) "ColorAdjustment", (char *) NULL},
+ { 0x0015, (char *) "AdjustmentMode", (char *) NULL},
+ { 0x0016, (char *) "Quality", (char *) NULL},
+ { 0x0017, (char *) "Firmware", (char *) NULL},
+ { 0x0018, (char *) "Software", (char *) NULL},
+ { 0x0019, (char *) "AutoBracket", (char *) NULL},
+ { 0x001A, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x001B, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x001C, (char *) "PreviewImageSize", (char *) NULL},
+ { 0x001D, (char *) "MakerNoteVersion", (char *) NULL},
+ { 0x001F, (char *) "AFPoint", (char *) NULL},
+ { 0x0022, (char *) "FileFormat", (char *) NULL},
+ { 0x0024, (char *) "Calibration", (char *) NULL},
+ { 0x002C, (char *) "ColorMode", (char *) NULL},
+ { 0x0030, (char *) "LensApertureRange", (char *) NULL},
+ { 0x0031, (char *) "FNumber", (char *) NULL},
+ { 0x0032, (char *) "ExposureTime", (char *) NULL},
+ { 0x0033, (char *) "ExposureTime2", (char *) NULL},
+ { 0x0034, (char *) "BurstShot", (char *) NULL},
+ { 0x0035, (char *) "ExposureCompensation", (char *) NULL},
+ { 0x0039, (char *) "SensorTemperature", (char *) NULL},
+ { 0x003A, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x003B, (char *) "Firmware", (char *) NULL},
+ { 0x003C, (char *) "WhiteBalance", (char *) NULL},
+ { 0x003D, (char *) "PictureMode", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// IPTC tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ iptc_tag_table[] =
+ {
+ // IPTC-NAA IIM version 4
+ { 0x0200 + 0, (char *) "ApplicationRecordVersion", (char *) "Application Record Version"},
+ { 0x0200 + 3, (char *) "ObjectTypeReference", (char *) "Object Type Reference"},
+ { 0x0200 + 4, (char *) "ObjectAttributeReference", (char *) "Object Attribute Reference"},
+ { 0x0200 + 5, (char *) "ObjectName", (char *) "Title"},
+ { 0x0200 + 7, (char *) "EditStatus", (char *) "Edit Status"},
+ { 0x0200 + 8, (char *) "EditorialUpdate", (char *) "Editorial Update"},
+ { 0x0200 + 10, (char *) "Urgency", (char *) "Urgency"},
+ { 0x0200 + 12, (char *) "SubjectReference", (char *) "Subject Reference"},
+ { 0x0200 + 15, (char *) "Category", (char *) "Category"},
+ { 0x0200 + 20, (char *) "SupplementalCategories", (char *) "Supplemental Categories"},
+ { 0x0200 + 22, (char *) "FixtureIdentifier", (char *) "Fixture Identifier"},
+ { 0x0200 + 25, (char *) "Keywords", (char *) "Keywords"},
+ { 0x0200 + 26, (char *) "ContentLocationCode", (char *) "Content Location Code"},
+ { 0x0200 + 27, (char *) "ContentLocationName", (char *) "Content Location Name"},
+ { 0x0200 + 30, (char *) "ReleaseDate", (char *) "Release Date"},
+ { 0x0200 + 35, (char *) "ReleaseTime", (char *) "Release Time"},
+ { 0x0200 + 37, (char *) "ExpirationDate", (char *) "Expiration Date"},
+ { 0x0200 + 38, (char *) "ExpirationTime", (char *) "Expiration Time"},
+ { 0x0200 + 40, (char *) "SpecialInstructions", (char *) "Instructions"},
+ { 0x0200 + 42, (char *) "ActionAdvised", (char *) "Action Advised"},
+ { 0x0200 + 45, (char *) "ReferenceService", (char *) "Reference Service"},
+ { 0x0200 + 47, (char *) "ReferenceDate", (char *) "Reference Date"},
+ { 0x0200 + 50, (char *) "ReferenceNumber", (char *) "Reference Number"},
+ { 0x0200 + 55, (char *) "DateCreated", (char *) "Date Created"},
+ { 0x0200 + 60, (char *) "TimeCreated", (char *) "Time Created"},
+ { 0x0200 + 62, (char *) "DigitalCreationDate", (char *) "Digital Creation Date"},
+ { 0x0200 + 63, (char *) "DigitalCreationTime", (char *) "Digital Creation Time"},
+ { 0x0200 + 65, (char *) "OriginatingProgram", (char *) "Originating Program"},
+ { 0x0200 + 70, (char *) "ProgramVersion", (char *) "Program Version"},
+ { 0x0200 + 75, (char *) "ObjectCycle", (char *) "Object Cycle"},
+ { 0x0200 + 80, (char *) "By-line", (char *) "Author"},
+ { 0x0200 + 85, (char *) "By-lineTitle", (char *) "Author's Position"},
+ { 0x0200 + 90, (char *) "City", (char *) "City"},
+ { 0x0200 + 92, (char *) "SubLocation", (char *) "Sub-Location"},
+ { 0x0200 + 95, (char *) "Province-State", (char *) "State/Province"},
+ { 0x0200 + 100, (char *) "Country-PrimaryLocationCode", (char *) "Country Code"},
+ { 0x0200 + 101, (char *) "Country-PrimaryLocationName", (char *) "Country Name"},
+ { 0x0200 + 103, (char *) "OriginalTransmissionReference", (char *) "Transmission Reference"},
+ { 0x0200 + 105, (char *) "Headline", (char *) "Headline"},
+ { 0x0200 + 110, (char *) "Credit", (char *) "Credit"},
+ { 0x0200 + 115, (char *) "Source", (char *) "Source"},
+ { 0x0200 + 116, (char *) "CopyrightNotice", (char *) "Copyright Notice"},
+ { 0x0200 + 118, (char *) "Contact", (char *) "Contact"},
+ { 0x0200 + 120, (char *) "Caption-Abstract", (char *) "Caption"},
+ { 0x0200 + 122, (char *) "Writer-Editor", (char *) "Caption Writer"},
+ { 0x0200 + 125, (char *) "RasterizedCaption", (char *) "Rasterized Caption"},
+ { 0x0200 + 130, (char *) "ImageType", (char *) "Image Type"},
+ { 0x0200 + 131, (char *) "ImageOrientation", (char *) "Image Orientation"},
+ { 0x0200 + 135, (char *) "LanguageIdentifier", (char *) "Language Identifier"},
+ { 0x0200 + 150, (char *) "AudioType", (char *) "Audio Type"},
+ { 0x0200 + 151, (char *) "AudioSamplingRate", (char *) "Audio Sampling Rate"},
+ { 0x0200 + 152, (char *) "AudioSamplingResolution", (char *) "Audio Sampling Resolution"},
+ { 0x0200 + 153, (char *) "AudioDuration", (char *) "Audio Duration"},
+ { 0x0200 + 154, (char *) "AudioOutcue", (char *) "Audio Outcue"},
+ // Metadata seen in other softwares (see also http://owl.phy.queensu.ca/~phil/exiftool/TagNames/IPTC.html#ApplicationRecord)
+ { 0x0200 + 184, (char *) "JobID", (char *) "Job ID"},
+ { 0x0200 + 185, (char *) "MasterDocumentID", (char *) "Master Document ID"},
+ { 0x0200 + 186, (char *) "ShortDocumentID", (char *) "Short Document ID"},
+ { 0x0200 + 187, (char *) "UniqueDocumentID", (char *) "Unique Document ID"},
+ { 0x0200 + 188, (char *) "OwnerID", (char *) "Owner ID"},
+ // IPTC-NAA IIM version 4
+ { 0x0200 + 200, (char *) "ObjectPreviewFileFormat", (char *) "Object Preview File Format"},
+ { 0x0200 + 201, (char *) "ObjectPreviewFileVersion", (char *) "Object Preview File Version"},
+ { 0x0200 + 202, (char *) "ObjectPreviewData", (char *) "Audio Outcue"},
+ // Metadata seen in other softwares (see also http://owl.phy.queensu.ca/~phil/exiftool/TagNames/IPTC.html#ApplicationRecord)
+ { 0x0200 + 221, (char *) "Prefs", (char *) "PhotoMechanic preferences"},
+ { 0x0200 + 225, (char *) "ClassifyState", (char *) "Classify State"},
+ { 0x0200 + 228, (char *) "SimilarityIndex", (char *) "Similarity Index"},
+ { 0x0200 + 230, (char *) "DocumentNotes", (char *) "Document Notes"},
+ { 0x0200 + 231, (char *) "DocumentHistory", (char *) "Document History"},
+ { 0x0200 + 232, (char *) "ExifCameraInfo", (char *) "Exif Camera Info"},
+
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// GeoTIFF tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ geotiff_tag_table[] =
+ {
+ { 0x830E, (char *) "GeoPixelScale", (char *) NULL},
+ { 0x8480, (char *) "Intergraph TransformationMatrix", (char *) NULL},
+ { 0x8482, (char *) "GeoTiePoints", (char *) NULL},
+ { 0x85D7, (char *) "JPL Carto IFD offset", (char *) NULL},
+ { 0x85D8, (char *) "GeoTransformationMatrix", (char *) NULL},
+ { 0x87AF, (char *) "GeoKeyDirectory", (char *) NULL},
+ { 0x87B0, (char *) "GeoDoubleParams", (char *) NULL},
+ { 0x87B1, (char *) "GeoASCIIParams", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// Animation tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ animation_tag_table[] =
+ {
+ { 0x0001, (char *) "LogicalWidth", (char *) "Logical width"},
+ { 0x0002, (char *) "LogicalHeight", (char *) "Logical height"},
+ { 0x0003, (char *) "GlobalPalette", (char *) "Global Palette"},
+ { 0x0004, (char *) "Loop", (char *) "loop"},
+ { 0x1001, (char *) "FrameLeft", (char *) "Frame left"},
+ { 0x1002, (char *) "FrameTop", (char *) "Frame top"},
+ { 0x1003, (char *) "NoLocalPalette", (char *) "No Local Palette"},
+ { 0x1004, (char *) "Interlaced", (char *) "Interlaced"},
+ { 0x1005, (char *) "FrameTime", (char *) "Frame display time"},
+ { 0x1006, (char *) "DisposalMethod", (char *) "Frame disposal method"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// TagLib class definition
+// --------------------------------------------------------------------------
+
+
+/**
+This is where the tag info tables are initialized
+*/
+TagLib::TagLib() {
+ // initialize all known metadata models
+ // ====================================
+
+ // Exif
+ addMetadataModel(TagLib::EXIF_MAIN, exif_exif_tag_table);
+ addMetadataModel(TagLib::EXIF_EXIF, exif_exif_tag_table);
+ addMetadataModel(TagLib::EXIF_GPS, exif_gps_tag_table);
+ addMetadataModel(TagLib::EXIF_INTEROP, exif_interop_tag_table);
+
+ // Exif maker note
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_CANON, exif_canon_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_CASIOTYPE1, exif_casio_type1_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_CASIOTYPE2, exif_casio_type2_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_FUJIFILM, exif_fujifilm_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_KYOCERA, exif_kyocera_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_MINOLTA, exif_minolta_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_NIKONTYPE1, exif_nikon_type1_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_NIKONTYPE2, exif_nikon_type2_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_NIKONTYPE3, exif_nikon_type3_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_OLYMPUSTYPE1, exif_olympus_type1_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_PANASONIC, exif_panasonic_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_ASAHI, exif_asahi_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_PENTAX, exif_pentax_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_SONY, exif_sony_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_SIGMA_SD1, exif_sigma_sd1_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_SIGMA_FOVEON, exif_sigma_foveon_tag_table);
+
+ // IPTC/NAA
+ addMetadataModel(TagLib::IPTC, iptc_tag_table);
+
+ // GeoTIFF
+ addMetadataModel(TagLib::GEOTIFF, geotiff_tag_table);
+
+ // Animation
+ addMetadataModel(TagLib::ANIMATION, animation_tag_table);
+}
+
+BOOL TagLib::addMetadataModel(MDMODEL md_model, TagInfo *tag_table) {
+ // check that the model doesn't already exist
+ if((_table_map.find(md_model) == _table_map.end()) && (tag_table != NULL)) {
+
+ // add the tag description table
+ TAGINFO *info_map = new(std::nothrow) TAGINFO();
+ if(!info_map) return FALSE;
+
+ for(int i = 0; ; i++) {
+ if((tag_table[i].tag == 0) && (tag_table[i].fieldname == NULL))
+ break;
+ (*info_map)[tag_table[i].tag] = &tag_table[i];
+ }
+
+ // add the metadata model
+ _table_map[md_model] = info_map;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+TagLib::~TagLib() {
+ // delete metadata models
+ for(TABLEMAP::iterator i = _table_map.begin(); i != _table_map.end(); i++) {
+ TAGINFO *info_map = (*i).second;
+ delete info_map;
+ }
+}
+
+
+TagLib&
+TagLib::instance() {
+ static TagLib s;
+ return s;
+}
+
+const TagInfo*
+TagLib::getTagInfo(MDMODEL md_model, WORD tagID) {
+
+ if(_table_map.find(md_model) != _table_map.end()) {
+
+ TAGINFO *info_map = (TAGINFO*)_table_map[md_model];
+ if(info_map->find(tagID) != info_map->end()) {
+ return (*info_map)[tagID];
+ }
+ }
+ return NULL;
+}
+
+const char*
+TagLib::getTagFieldName(MDMODEL md_model, WORD tagID, char *defaultKey) {
+
+ const TagInfo *info = getTagInfo(md_model, tagID);
+ if(NULL == info) {
+ if(defaultKey != NULL) {
+ sprintf(defaultKey, "Tag 0x%04X", tagID);
+ return &defaultKey[0];
+ } else {
+ return NULL;
+ }
+ }
+
+ return info->fieldname;
+}
+
+const char*
+TagLib::getTagDescription(MDMODEL md_model, WORD tagID) {
+
+ const TagInfo *info = getTagInfo(md_model, tagID);
+ if(info) {
+ return info->description;
+ }
+
+ return NULL;
+}
+
+int TagLib::getTagID(MDMODEL md_model, const char *key) {
+
+ if(_table_map.find(md_model) != _table_map.end()) {
+
+ TAGINFO *info_map = (TAGINFO*)_table_map[md_model];
+ for(TAGINFO::iterator i = info_map->begin(); i != info_map->end(); i++) {
+ const TagInfo *info = (*i).second;
+ if(info && (strcmp(info->fieldname, key) == 0)) {
+ return (int)info->tag;
+ }
+ }
+ }
+ return -1;
+}
+
+FREE_IMAGE_MDMODEL
+TagLib::getFreeImageModel(MDMODEL model) {
+ switch(model) {
+ case EXIF_MAIN:
+ return FIMD_EXIF_MAIN;
+
+ case EXIF_EXIF:
+ return FIMD_EXIF_EXIF;
+
+ case EXIF_GPS:
+ return FIMD_EXIF_GPS;
+
+ case EXIF_INTEROP:
+ return FIMD_EXIF_INTEROP;
+
+ case EXIF_MAKERNOTE_CANON:
+ case EXIF_MAKERNOTE_CASIOTYPE1:
+ case EXIF_MAKERNOTE_CASIOTYPE2:
+ case EXIF_MAKERNOTE_FUJIFILM:
+ case EXIF_MAKERNOTE_KYOCERA:
+ case EXIF_MAKERNOTE_MINOLTA:
+ case EXIF_MAKERNOTE_NIKONTYPE1:
+ case EXIF_MAKERNOTE_NIKONTYPE2:
+ case EXIF_MAKERNOTE_NIKONTYPE3:
+ case EXIF_MAKERNOTE_OLYMPUSTYPE1:
+ case EXIF_MAKERNOTE_PANASONIC:
+ case EXIF_MAKERNOTE_ASAHI:
+ case EXIF_MAKERNOTE_PENTAX:
+ case EXIF_MAKERNOTE_SONY:
+ case EXIF_MAKERNOTE_SIGMA_SD1:
+ case EXIF_MAKERNOTE_SIGMA_FOVEON:
+ return FIMD_EXIF_MAKERNOTE;
+
+ case IPTC:
+ return FIMD_IPTC;
+
+ case GEOTIFF:
+ return FIMD_GEOTIFF;
+
+ case ANIMATION:
+ return FIMD_ANIMATION;
+ }
+
+ return FIMD_NODATA;
+}
+
diff --git a/plugins/FreeImage/Source/Metadata/XTIFF.cpp b/plugins/FreeImage/Source/Metadata/XTIFF.cpp
index 862384db24..c6ec5ba858 100644
--- a/plugins/FreeImage/Source/Metadata/XTIFF.cpp
+++ b/plugins/FreeImage/Source/Metadata/XTIFF.cpp
@@ -29,7 +29,7 @@
#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
#endif
-#include "../LibTIFF/tiffiop.h"
+#include "../LibTIFF4/tiffiop.h"
#include "FreeImage.h"
#include "Utilities.h"
@@ -198,15 +198,15 @@ tiff_write_geotiff_profile(TIFF *tif, FIBITMAP *dib) {
}
// ----------------------------------------------------------
-// EXIF tag reading
+// EXIF tag reading & writing
// ----------------------------------------------------------
/**
Read a single exif tag
*/
static BOOL
-tiff_read_exif_tag(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib, TagLib& tagLib, TIFFDirectory *td, ttag_t tag) {
- const TIFFFieldInfo *fip;
+tiff_read_exif_tag(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib, TagLib& tagLib, TIFFDirectory *td, uint32 tag) {
+ const TIFFField *fip;
uint32 value_count;
int mem_alloc = 0;
void *raw_data = NULL;
@@ -226,27 +226,6 @@ tiff_read_exif_tag(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib, TagLib& t
return TRUE;
}
- // ### for some reason TIFFFieldWithTag returns wrong version (TIFF_LONG vs TIFF_SHORT) for some params, correct this
- if(fip->field_tag == TIFFTAG_IMAGEWIDTH && fip->field_type == TIFF_SHORT) {
- fip = TIFFFindFieldInfo(tif, tag, TIFF_LONG);
- } else if(fip->field_tag == TIFFTAG_IMAGELENGTH && fip->field_type == TIFF_SHORT) {
- fip = TIFFFindFieldInfo(tif, tag, TIFF_LONG);
- } else if(fip->field_tag == TIFFTAG_BITSPERSAMPLE && fip->field_type == TIFF_LONG) {
- fip = TIFFFindFieldInfo(tif, tag, TIFF_SHORT);
- } else if(fip->field_tag == TIFFTAG_COMPRESSION && fip->field_type == TIFF_LONG) {
- fip = TIFFFindFieldInfo(tif, tag, TIFF_SHORT);
- } else if(fip->field_tag == TIFFTAG_PHOTOMETRIC && fip->field_type == TIFF_LONG) {
- fip = TIFFFindFieldInfo(tif, tag, TIFF_SHORT);
- } else if(fip->field_tag == TIFFTAG_ROWSPERSTRIP && fip->field_type == TIFF_SHORT) {
- fip = TIFFFindFieldInfo(tif, tag, TIFF_LONG);
- } else if(fip->field_tag == TIFFTAG_STRIPOFFSETS && fip->field_type == TIFF_SHORT) {
- fip = TIFFFindFieldInfo(tif, tag, TIFF_LONG);
- } else if(fip->field_tag == TIFFTAG_STRIPBYTECOUNTS && fip->field_type == TIFF_SHORT) {
- fip = TIFFFindFieldInfo(tif, tag, TIFF_LONG);
- }
- // ### the tags left unchecked are SGI, Pixar and DNG tags filtered by tagLib.getTagFieldName
-
-
if(fip->field_passcount) { //<- "passcount" means "returns count"
if (fip->field_readcount != TIFF_VARIABLE2) { //<- TIFF_VARIABLE2 means "uses LONG count"
@@ -451,6 +430,27 @@ tiff_read_exif_tag(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib, TagLib& t
FreeImage_SetTagValue(fitag, raw_data);
break;
+ case TIFF_LONG8: // BigTIFF 64-bit unsigned integer
+ FreeImage_SetTagType(fitag, FIDT_LONG8);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_IFD8: // BigTIFF 64-bit unsigned integer (offset)
+ FreeImage_SetTagType(fitag, FIDT_IFD8);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_SLONG8: // BigTIFF 64-bit signed integer
+ FreeImage_SetTagType(fitag, FIDT_SLONG8);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
default: {
size_t length = strlen((char*)raw_data) + 1;
FreeImage_SetTagType(fitag, FIDT_ASCII);
@@ -480,7 +480,8 @@ tiff_read_exif_tag(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib, TagLib& t
/**
Read all known exif tags
*/
-BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
+BOOL
+tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
int i;
short count;
@@ -490,7 +491,7 @@ BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
count = (short) TIFFGetTagListCount(tif);
for(i = 0; i < count; i++) {
- ttag_t tag = TIFFGetTagListEntry(tif, i);
+ uint32 tag = TIFFGetTagListEntry(tif, i);
// read the tag
if (!tiff_read_exif_tag(tif, md_model, dib, tagLib, td, tag))
return FALSE;
@@ -502,38 +503,38 @@ BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
// ### uses private data, but there is no other way
if(md_model == TagLib::EXIF_MAIN) {
- ttag_t lastTag = 0; //<- used to prevent reading some tags twice (as stored in tif_fieldinfo)
+ uint32 lastTag = 0; //<- used to prevent reading some tags twice (as stored in tif_fieldinfo)
for (int fi = 0, nfi = (int)tif->tif_nfields; nfi > 0; nfi--, fi++) {
- const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi];
+ const TIFFField *fld = tif->tif_fields[fi];
- if(fip->field_tag == lastTag)
+ if(fld->field_tag == lastTag)
continue;
// test if tag value is set
// (lifted directly form LibTiff _TIFFWriteDirectory)
- if( fip->field_bit == FIELD_CUSTOM ) {
+ if( fld->field_bit == FIELD_CUSTOM ) {
int ci, is_set = FALSE;
for( ci = 0; ci < td->td_customValueCount; ci++ ) {
- is_set |= (td->td_customValues[ci].info == fip);
+ is_set |= (td->td_customValues[ci].info == fld);
}
if( !is_set ) {
continue;
}
- } else if(!TIFFFieldSet(tif, fip->field_bit)) {
+ } else if(!TIFFFieldSet(tif, fld->field_bit)) {
continue;
}
// process *all* other tags (some will be ignored)
- tiff_read_exif_tag(tif, md_model, dib, tagLib, td, fip->field_tag);
+ tiff_read_exif_tag(tif, md_model, dib, tagLib, td, fld->field_tag);
- lastTag = fip->field_tag;
+ lastTag = fld->field_tag;
}
}
@@ -541,3 +542,120 @@ BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
return TRUE;
}
+
+
+/**
+Skip tags that are already handled by the LibTIFF writing process
+*/
+static BOOL
+skip_write_field(TIFF* tif, uint32 tag) {
+ switch (tag) {
+ case TIFFTAG_SAMPLEFORMAT:
+ case TIFFTAG_IMAGEWIDTH:
+ case TIFFTAG_IMAGELENGTH:
+ case TIFFTAG_SAMPLESPERPIXEL:
+ case TIFFTAG_BITSPERSAMPLE:
+ case TIFFTAG_PHOTOMETRIC:
+ case TIFFTAG_PLANARCONFIG:
+ case TIFFTAG_ROWSPERSTRIP:
+ case TIFFTAG_RESOLUTIONUNIT:
+ case TIFFTAG_XRESOLUTION:
+ case TIFFTAG_YRESOLUTION:
+ case TIFFTAG_SUBFILETYPE:
+ case TIFFTAG_PAGENUMBER:
+ case TIFFTAG_COLORMAP:
+ case TIFFTAG_ORIENTATION:
+ case TIFFTAG_COMPRESSION:
+ case TIFFTAG_PREDICTOR:
+ case TIFFTAG_GROUP3OPTIONS:
+ case TIFFTAG_FILLORDER:
+ // skip always, values have been set in SaveOneTIFF()
+ return TRUE;
+ break;
+
+ case TIFFTAG_RICHTIFFIPTC:
+ // skip always, IPTC metadata model is set in tiff_write_iptc_profile()
+ return TRUE;
+ break;
+
+ case TIFFTAG_YCBCRCOEFFICIENTS:
+ case TIFFTAG_REFERENCEBLACKWHITE:
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ // skip as they cannot be filled yet
+ return TRUE;
+ break;
+
+ case TIFFTAG_PAGENAME:
+ {
+ char *value = NULL;
+ TIFFGetField(tif, TIFFTAG_PAGENAME, &value);
+ // only skip if no value has been set
+ if(value == NULL) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+ default:
+ return FALSE;
+ break;
+ }
+}
+
+/**
+Write all known exif tags
+*/
+BOOL
+tiff_write_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
+ char defaultKey[16];
+
+ // only EXIF_MAIN so far
+ if(md_model != TagLib::EXIF_MAIN) {
+ return FALSE;
+ }
+
+ if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib) == 0) {
+ return FALSE;
+ }
+
+ TagLib& tag_lib = TagLib::instance();
+
+ for (int fi = 0, nfi = (int)tif->tif_nfields; nfi > 0; nfi--, fi++) {
+ const TIFFField *fld = tif->tif_fields[fi];
+
+ if(skip_write_field(tif, fld->field_tag)) {
+ // skip tags that are already handled by the LibTIFF writing process
+ continue;
+ }
+
+ FITAG *tag = NULL;
+ // get the tag key
+ const char *key = tag_lib.getTagFieldName(TagLib::EXIF_MAIN, (WORD)fld->field_tag, defaultKey);
+
+ if(FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, key, &tag)) {
+ FREE_IMAGE_MDTYPE tag_type = FreeImage_GetTagType(tag);
+ TIFFDataType tif_tag_type = fld->field_type;
+
+ // check for identical formats
+
+ // (enum value are the sames between FREE_IMAGE_MDTYPE and TIFFDataType types)
+ if((int)tif_tag_type != (int)tag_type) {
+ // skip tag or _TIFFmemcpy will fail
+ continue;
+ }
+ // type of storage may differ (e.g. rationnal array vs float array type)
+ if(_TIFFDataSize(tif_tag_type) != FreeImage_TagDataWidth(tag_type)) {
+ // skip tag or _TIFFmemcpy will fail
+ continue;
+ }
+
+ if(tag_type == FIDT_ASCII) {
+ TIFFSetField(tif, fld->field_tag, FreeImage_GetTagValue(tag));
+ } else {
+ TIFFSetField(tif, fld->field_tag, FreeImage_GetTagCount(tag), FreeImage_GetTagValue(tag));
+ }
+ }
+ }
+
+ return TRUE;
+}