const TIFFFieldInfo * DECLARE1(TIFFFieldWithTag, u_short, tag) { const TIFFFieldInfo *fip = TIFFFindFieldInfo(tag, TIFF_ANY); if (fip) return (fip); TIFFError("TIFFFieldWithTag", "Internal error, unknown tag 0x%x", tag); assert(fip != NULL); /*NOTREACHED*/ }
TIFFFieldInfo const * DECLARE1(TIFFFieldWithTag, u_short, tag) { TIFFFieldInfo const *fip = TIFFFindFieldInfo(tag, TIFF_ANY); if (fip) return (fip); TIFFError("TIFFFieldWithTag", "Internal error, unknown tag 0x%x", tag); exit(-1); /*NOTREACHED*/ }
const TIFFFieldInfo* TIFFFieldWithTag(TIFF* tif, ttag_t tag) { const TIFFFieldInfo* fip = TIFFFindFieldInfo(tif, tag, TIFF_ANY); if (!fip) { _TIFFError(tif, "TIFFFieldWithTag", "Internal error, unknown tag 0x%x", (unsigned int) tag); assert(fip != NULL); /*NOTREACHED*/ } return (fip); }
const TIFFFieldInfo* _TIFFFindOrRegisterFieldInfo( TIFF *tif, ttag_t tag, TIFFDataType dt ) { const TIFFFieldInfo *fld; fld = TIFFFindFieldInfo( tif, tag, dt ); if( fld == NULL ) { fld = _TIFFCreateAnonFieldInfo( tif, tag, dt ); TIFFMergeFieldInfo( tif, fld, 1 ); } return fld; }
// Search for TIFF tag 'tagid' having type 'tifftype', and if found, // add it in the obvious way to m_spec under the name 'oiioname'. void find_tag (int tifftag, TIFFDataType tifftype, const char *oiioname) { #ifdef TIFF_VERSION_BIG const TIFFField *info = TIFFFindField (m_tif, tifftag, tifftype); #else const TIFFFieldInfo *info = TIFFFindFieldInfo (m_tif, tifftag, tifftype); #endif if (! info) { // Something has gone wrong, libtiff doesn't think the field type // is the same as we do. return; } if (tifftype == TIFF_ASCII) get_string_attribute (oiioname, tifftag); else if (tifftype == TIFF_SHORT) get_short_attribute (oiioname, tifftag); else if (tifftype == TIFF_LONG) get_int_attribute (oiioname, tifftag); else if (tifftype == TIFF_RATIONAL || tifftype == TIFF_SRATIONAL || tifftype == TIFF_FLOAT || tifftype == TIFF_DOUBLE) get_float_attribute (oiioname, tifftag); }
/** 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; uint32 value_count; int mem_alloc = 0; void *raw_data = NULL; if(tag == TIFFTAG_EXIFIFD) { return TRUE; } // get the tag key - use NULL to avoid reading GeoTIFF tags const char *key = tagLib.getTagFieldName(md_model, (WORD)tag, NULL); if(key == NULL) { return TRUE; } fip = TIFFFieldWithTag(tif, tag); if(fip == NULL) { 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" // assume TIFF_VARIABLE (uses SHORT count) uint16 value_count16; if(TIFFGetField(tif, tag, &value_count16, &raw_data) != 1) { return TRUE; } value_count = value_count16; } else { if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) { return TRUE; } } } else { // determine count if (fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2) { value_count = 1; } else if (fip->field_readcount == TIFF_SPP) { value_count = td->td_samplesperpixel; } else { value_count = fip->field_readcount; } // access fields as pointers to data // (### determining this is NOT robust... and hardly can be. It is implemented looking the _TIFFVGetField code) if(fip->field_tag == TIFFTAG_TRANSFERFUNCTION) { // reading this tag cause a bug probably located somewhere inside libtiff return TRUE; } if ((fip->field_type == TIFF_ASCII || fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2 || fip->field_readcount == TIFF_SPP || value_count > 1) && fip->field_tag != TIFFTAG_PAGENUMBER && fip->field_tag != TIFFTAG_HALFTONEHINTS && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING && fip->field_tag != TIFFTAG_DOTRANGE && fip->field_tag != TIFFTAG_BITSPERSAMPLE //<- these two are tricky - && fip->field_tag != TIFFTAG_COMPRESSION //<- they are defined as TIFF_VARIABLE but in reality return a single value ) { if(TIFFGetField(tif, tag, &raw_data) != 1) { return TRUE; } } else { // access fields as values const int value_size = _TIFFDataSize(fip->field_type); raw_data = _TIFFmalloc(value_size * value_count); mem_alloc = 1; int ok = FALSE; // ### if value_count > 1, tag is PAGENUMBER or HALFTONEHINTS or YCBCRSUBSAMPLING or DOTRANGE, // all off which are value_count == 2 (see tif_dirinfo.c) switch(value_count) { case 1: ok = TIFFGetField(tif, tag, raw_data); break; case 2: ok = TIFFGetField(tif, tag, raw_data, (BYTE*)(raw_data) + value_size*1); break; /* # we might need more in the future: case 3: ok = TIFFGetField(tif, tag, raw_data, (BYTE*)(raw_data) + value_size*1, (BYTE*)(raw_data) + value_size*2); break; */ default: FreeImage_OutputMessageProc(FIF_TIFF, "Unimplemented variable number of parameters for Tiff Tag %s", fip->field_name); break; } if(ok != 1) { _TIFFfree(raw_data); return TRUE; } } } // build FreeImage tag from Tiff Tag data we collected FITAG *fitag = FreeImage_CreateTag(); if(!fitag) { if(mem_alloc) { _TIFFfree(raw_data); } return FALSE; } FreeImage_SetTagID(fitag, (WORD)tag); FreeImage_SetTagKey(fitag, key); switch(fip->field_type) { case TIFF_BYTE: FreeImage_SetTagType(fitag, FIDT_BYTE); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, raw_data); break; case TIFF_UNDEFINED: FreeImage_SetTagType(fitag, FIDT_UNDEFINED); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, raw_data); break; case TIFF_SBYTE: FreeImage_SetTagType(fitag, FIDT_SBYTE); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, raw_data); break; case TIFF_SHORT: FreeImage_SetTagType(fitag, FIDT_SHORT); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, raw_data); break; case TIFF_SSHORT: FreeImage_SetTagType(fitag, FIDT_SSHORT); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, raw_data); break; case TIFF_LONG: FreeImage_SetTagType(fitag, FIDT_LONG); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, raw_data); break; case TIFF_IFD: FreeImage_SetTagType(fitag, FIDT_IFD); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, raw_data); break; case TIFF_SLONG: FreeImage_SetTagType(fitag, FIDT_SLONG); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, raw_data); break; case TIFF_RATIONAL: { // LibTIFF converts rational to floats : reconvert floats to rationals DWORD *rvalue = (DWORD*)malloc(2 * value_count * sizeof(DWORD)); for(uint32 i = 0; i < value_count; i++) { float *fv = (float*)raw_data; FIRational rational(fv[i]); rvalue[2*i] = rational.getNumerator(); rvalue[2*i+1] = rational.getDenominator(); } FreeImage_SetTagType(fitag, FIDT_RATIONAL); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, rvalue); free(rvalue); } break; case TIFF_SRATIONAL: { // LibTIFF converts rational to floats : reconvert floats to rationals LONG *rvalue = (LONG*)malloc(2 * value_count * sizeof(LONG)); for(uint32 i = 0; i < value_count; i++) { float *fv = (float*)raw_data; FIRational rational(fv[i]); rvalue[2*i] = rational.getNumerator(); rvalue[2*i+1] = rational.getDenominator(); } FreeImage_SetTagType(fitag, FIDT_RATIONAL); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, rvalue); free(rvalue); } break; case TIFF_FLOAT: FreeImage_SetTagType(fitag, FIDT_FLOAT); FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); FreeImage_SetTagCount(fitag, value_count); FreeImage_SetTagValue(fitag, raw_data); break; case TIFF_DOUBLE: FreeImage_SetTagType(fitag, FIDT_DOUBLE); 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); FreeImage_SetTagLength(fitag, (DWORD)length); FreeImage_SetTagCount(fitag, (DWORD)length); FreeImage_SetTagValue(fitag, raw_data); } break; } const char *description = tagLib.getTagDescription(md_model, (WORD)tag); if(description) { FreeImage_SetTagDescription(fitag, description); } // store the tag FreeImage_SetMetadata(tagLib.getFreeImageModel(md_model), dib, FreeImage_GetTagKey(fitag), fitag); // destroy the tag FreeImage_DeleteTag(fitag); if(mem_alloc) { _TIFFfree(raw_data); } return TRUE; }