summaryrefslogtreecommitdiff
path: root/plugins/FreeImage/Source/Metadata/XTIFF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/FreeImage/Source/Metadata/XTIFF.cpp')
-rw-r--r--plugins/FreeImage/Source/Metadata/XTIFF.cpp188
1 files changed, 153 insertions, 35 deletions
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;
+}