📄 reconciletiff.cpp
字号:
} // ImportArrayTIFF_Double// =================================================================================================// ImportArrayTIFF// ===============static voidImportArrayTIFF ( const TIFF_Manager::TagInfo & tagInfo, const bool nativeEndian, SXMPMeta * xmp, const char * xmpNS, const char * xmpProp ){ // We've got a tag to map to XMP, decide how based on actual type and the expected count. Using // the actual type eliminates a ShortOrLong case. Using the expected count is needed to know // whether to create an XMP array. The actual count for an array could be 1. Put the most // common cases first for better iCache utilization. switch ( tagInfo.type ) { case kTIFF_ShortType : ImportArrayTIFF_Short ( tagInfo, nativeEndian, xmp, xmpNS, xmpProp ); break; case kTIFF_LongType : ImportArrayTIFF_Long ( tagInfo, nativeEndian, xmp, xmpNS, xmpProp ); break; case kTIFF_RationalType : ImportArrayTIFF_Rational ( tagInfo, nativeEndian, xmp, xmpNS, xmpProp ); break; case kTIFF_SRationalType : ImportArrayTIFF_SRational ( tagInfo, nativeEndian, xmp, xmpNS, xmpProp ); break; case kTIFF_ASCIIType : ImportArrayTIFF_ASCII ( tagInfo, xmp, xmpNS, xmpProp ); break; case kTIFF_ByteType : ImportArrayTIFF_Byte ( tagInfo, xmp, xmpNS, xmpProp ); break; case kTIFF_SByteType : ImportArrayTIFF_SByte ( tagInfo, xmp, xmpNS, xmpProp ); break; case kTIFF_SShortType : ImportArrayTIFF_SShort ( tagInfo, nativeEndian, xmp, xmpNS, xmpProp ); break; case kTIFF_SLongType : ImportArrayTIFF_SLong ( tagInfo, nativeEndian, xmp, xmpNS, xmpProp ); break; case kTIFF_FloatType : ImportArrayTIFF_Float ( tagInfo, nativeEndian, xmp, xmpNS, xmpProp ); break; case kTIFF_DoubleType : ImportArrayTIFF_Double ( tagInfo, nativeEndian, xmp, xmpNS, xmpProp ); break; }} // ImportArrayTIFF// =================================================================================================// ImportTIFF_VerifyImport// =======================//// Decide whether to proceed with the import based on the digest state and presence of the legacy// and XMP. Will also delete existing XMP if appropriate.static boolImportTIFF_VerifyImport ( const TIFF_Manager & tiff, SXMPMeta * xmp, int digestState, XMP_Uns8 tiffIFD, XMP_Uns16 tiffID, const char * xmpNS, const char * xmpProp, TIFF_Manager::TagInfo * tagInfo ){ bool found = false; try { // Don't let errors with one stop the others. if ( digestState == kDigestDiffers ) { xmp->DeleteProperty ( xmpNS, xmpProp ); } else { XMP_Assert ( digestState == kDigestMissing ); if ( xmp->DoesPropertyExist ( xmpNS, xmpProp ) ) return false; } found = tiff.GetTag ( tiffIFD, tiffID, tagInfo ); } catch ( ... ) { found = false; } return found;} // ImportTIFF_VerifyImport// =================================================================================================// ImportTIFF_CheckStandardMapping// ===============================static boolImportTIFF_CheckStandardMapping ( const TIFF_Manager::TagInfo & tagInfo, const TIFF_MappingToXMP & mapInfo ){ XMP_Assert ( (kTIFF_ByteType <= tagInfo.type) && (tagInfo.type <= kTIFF_LastType) ); XMP_Assert ( mapInfo.type <= kTIFF_LastType ); if ( (tagInfo.type < kTIFF_ByteType) || (tagInfo.type > kTIFF_LastType) ) return false; if ( tagInfo.type != mapInfo.type ) { if ( mapInfo.type != kTIFF_ShortOrLongType ) return false; if ( (tagInfo.type != kTIFF_ShortType) && (tagInfo.type != kTIFF_LongType) ) return false; } if ( (tagInfo.count != mapInfo.count) && (mapInfo.count != kAnyCount) ) return false; return true;} // ImportTIFF_CheckStandardMapping// =================================================================================================// ImportTIFF_StandardMappings// ===========================static voidImportTIFF_StandardMappings ( XMP_Uns8 ifd, const TIFF_Manager & tiff, SXMPMeta * xmp, int digestState ){ const bool nativeEndian = tiff.IsNativeEndian(); TIFF_Manager::TagInfo tagInfo; const TIFF_MappingToXMP * mappings = 0; const char * xmpNS = 0; if ( ifd == kTIFF_PrimaryIFD ) { mappings = sPrimaryIFDMappings; xmpNS = kXMP_NS_TIFF; } else if ( ifd == kTIFF_ExifIFD ) { mappings = sExifIFDMappings; xmpNS = kXMP_NS_EXIF; } else if ( ifd == kTIFF_GPSInfoIFD ) { mappings = sGPSInfoIFDMappings; xmpNS = kXMP_NS_EXIF; // ! Yes, the GPS Info tags go into the exif: namespace. } else { XMP_Throw ( "Invalid IFD for standard mappings", kXMPErr_InternalFailure ); } for ( size_t i = 0; mappings[i].id != 0xFFFF; ++i ) { try { // Don't let errors with one stop the others. const TIFF_MappingToXMP & mapInfo = mappings[i]; const bool mapSingle = ((mapInfo.count == 1) || (mapInfo.type == kTIFF_ASCIIType)); // Skip tags that have special mappings, they are handled individually later. Delete any // existing XMP property before going further. But after the special mapping check since we // don't have the XMP property name for those. This lets legacy deletions propagate and // eliminates any problems with existing XMP property form. Make sure the actual tag has // the expected type and count, ignore it (pretend it is not present) if not. if ( mapInfo.name[0] == 0 ) continue; // Skip special mappings. bool ok = ImportTIFF_VerifyImport ( tiff, xmp, digestState, ifd, mapInfo.id, xmpNS, mapInfo.name, &tagInfo ); if (! ok ) continue; XMP_Assert ( tagInfo.type != kTIFF_UndefinedType ); // These have a special mapping. if ( tagInfo.type == kTIFF_UndefinedType ) continue; if ( ! ImportTIFF_CheckStandardMapping ( tagInfo, mapInfo ) ) continue; if ( mapSingle ) { ImportSingleTIFF ( tagInfo, nativeEndian, xmp, xmpNS, mapInfo.name ); } else { ImportArrayTIFF ( tagInfo, nativeEndian, xmp, xmpNS, mapInfo.name ); } } catch ( ... ) { // Do nothing, let other imports proceed. // ? Notify client? } }} // ImportTIFF_StandardMappings// =================================================================================================// =================================================================================================// =================================================================================================// ImportTIFF_Date// ===============//// Convert an Exif 2.2 master date/time tag plus associated fractional seconds to an XMP date/time.// The Exif date/time part is a 20 byte ASCII value formatted as "YYYY:MM:DD HH:MM:SS" with a// terminating nul. Any of the numeric portions can be blanks if unknown. The fractional seconds// are a nul terminated ASCII string with possible space padding. They are literally the fractional// part, the digits that would be to the right of the decimal point.static voidImportTIFF_Date ( const TIFF_Manager & tiff, const TIFF_Manager::TagInfo & dateInfo, XMP_Uns16 secID, SXMPMeta * xmp, const char * xmpNS, const char * xmpProp ){ try { // Don't let errors with one stop the others. const char * dateStr = (const char *) dateInfo.dataPtr; if ( (dateStr[4] != ':') || (dateStr[7] != ':') || (dateStr[10] != ' ') || (dateStr[13] != ':') || (dateStr[16] != ':') ) return; XMP_DateTime binValue; binValue.year = GatherInt ( &dateStr[0], 4 ); binValue.month = GatherInt ( &dateStr[5], 2 ); binValue.day = GatherInt ( &dateStr[8], 2 ); binValue.hour = GatherInt ( &dateStr[11], 2 ); binValue.minute = GatherInt ( &dateStr[14], 2 ); binValue.second = GatherInt ( &dateStr[17], 2 ); binValue.nanoSecond = 0; // Get the fractional seconds later. binValue.tzSign = binValue.tzHour = binValue.tzMinute = 0; SXMPUtils::SetTimeZone ( &binValue ); // Assume local time. TIFF_Manager::TagInfo secInfo; bool found = tiff.GetTag ( kTIFF_ExifIFD, secID, &secInfo ); if ( found && (secInfo.type == kTIFF_ASCIIType) ) { const char * fracPtr = (const char *) secInfo.dataPtr; binValue.nanoSecond = GatherInt ( fracPtr, secInfo.dataLen ); size_t digits = 0; for ( ; (('0' <= *fracPtr) && (*fracPtr <= '9')); ++fracPtr ) ++digits; for ( ; digits < 9; ++digits ) binValue.nanoSecond *= 10; } xmp->SetProperty_Date ( xmpNS, xmpProp, binValue ); } catch ( ... ) { // Do nothing, let other imports proceed. // ? Notify client? }} // ImportTIFF_Date// =================================================================================================// ImportTIFF_LocTextASCII// =======================static voidImportTIFF_LocTextASCII ( const TIFF_Manager & tiff, XMP_Uns8 ifd, XMP_Uns16 tagID, SXMPMeta * xmp, const char * xmpNS, const char * xmpProp ){ try { // Don't let errors with one stop the others. TIFF_Manager::TagInfo tagInfo; bool found = tiff.GetTag ( ifd, tagID, &tagInfo ); if ( (! found) || (tagInfo.type != kTIFF_ASCIIType) ) return; const char * chPtr = (const char *)tagInfo.dataPtr; const bool hasNul = (chPtr[tagInfo.dataLen-1] == 0); const bool isUTF8 = ReconcileUtils::IsUTF8 ( chPtr, tagInfo.dataLen ); if ( isUTF8 && hasNul ) { xmp->SetLocalizedText ( xmpNS, xmpProp, "", "x-default", chPtr ); } else { std::string strValue; if ( isUTF8 ) { strValue.assign ( chPtr, tagInfo.dataLen ); } else { ReconcileUtils::LocalToUTF8 ( chPtr, tagInfo.dataLen, &strValue ); } xmp->SetLocalizedText ( xmpNS, xmpProp, "", "x-default", strValue.c_str() ); } } catch ( ... ) { // Do nothing, let other imports proceed. // ? Notify client? }} // ImportTIFF_LocTextASCII// =================================================================================================// ImportTIFF_EncodedString// ========================static voidImportTIFF_EncodedString ( const TIFF_Manager & tiff, const TIFF_Manager::TagInfo & tagInfo, SXMPMeta * xmp, const char * xmpNS, const char * xmpProp ){ try { // Don't let errors with one stop the others. std::string strValue; bool ok = tiff.DecodeString ( tagInfo.dataPtr, tagInfo.dataLen, &strValue ); if ( ok ) xmp->SetProperty ( xmpNS, xmpProp, strValue.c_str() ); } catch ( ... ) { // Do nothing, let other imports proceed. // ? Notify client? } } // ImportTIFF_EncodedString// =================================================================================================// ImportTIFF_Flash// ================static voidImportTIFF_Flash ( const TIFF_Manager::TagInfo & tagInfo, bool nativeEndian, SXMPMeta * xmp, const char * xmpNS, const char * xmpProp ){ try { // Don't let errors with one stop the others. XMP_Uns16 binValue = *((XMP_Uns16*)tagInfo.dataPtr); if ( ! nativeEndian ) binValue = Flip2 ( binValue ); bool fired = (bool)(binValue & 1); // Avoid implicit 0/1 conversion. int rtrn = (binValue >> 1) & 3; int mode = (binValue >> 3) & 3; bool function = (bool)((binValue >> 5) & 1); bool redEye = (bool)((binValue >> 6) & 1); static const char * sTwoBits[] = { "0", "1", "2", "3" }; xmp->SetStructField ( kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF, "Fired", (fired ? kXMP_TrueStr : kXMP_FalseStr) ); xmp->SetStructField ( kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF, "Return", sTwoBits[rtrn] ); xmp->SetStructField ( kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF, "Mode", sTwoBits[mode] ); xmp->SetStructField ( kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF, "Function", (function ? kXMP_TrueStr : kXMP_FalseStr) ); xmp->SetStructField ( kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF, "RedEyeMode", (redEye ? kXMP_TrueStr : kXMP_FalseStr) ); } catch ( ... ) { // Do nothing, let other imports proceed. // ? Notify client? }} // ImportTIFF_Flash// =================================================================================================// ImportTIFF_OECFTable// ====================// // Although the XMP for the OECF and SFR tables is the same, the Exif is not. The OECF table has// signed rational values and the SFR table has unsigned.static voidImportTIFF_OECFTable ( const TIFF_Manager::TagInfo & tagInfo, bool nativeEndian, SXMPMeta * xmp, const char * xmpNS, const char * xmpProp ){ try { // Don't let errors with one stop the others. const XMP_Uns8 * bytePtr = (XMP_Uns8*)tagInfo.dataPtr; const XMP_Uns8 * byteEnd = bytePtr + tagInfo.dataLen; XMP_Uns16 columns = *((XMP_Uns16*)bytePtr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -