📄 reconciletiff.cpp
字号:
XMP_Uns16 rows = *((XMP_Uns16*)(bytePtr+2)); if ( ! nativeEndian ) { columns = Flip2 ( columns ); rows = Flip2 ( rows ); } char buffer[40]; snprintf ( buffer, sizeof(buffer), "%d", columns ); // AUDIT: Use of sizeof(buffer) is safe. xmp->SetStructField ( xmpNS, xmpProp, kXMP_NS_EXIF, "Columns", buffer ); snprintf ( buffer, sizeof(buffer), "%d", rows ); // AUDIT: Use of sizeof(buffer) is safe. xmp->SetStructField ( xmpNS, xmpProp, kXMP_NS_EXIF, "Rows", buffer ); std::string arrayPath; SXMPUtils::ComposeStructFieldPath ( xmpNS, xmpProp, kXMP_NS_EXIF, "Names", &arrayPath ); bytePtr += 4; // Move to the list of names. for ( size_t i = columns; i > 0; --i ) { size_t nameLen = strlen((XMP_StringPtr)bytePtr) + 1; // ! Include the terminating nul. if ( (bytePtr + nameLen) > byteEnd ) goto BadExif; xmp->AppendArrayItem ( xmpNS, arrayPath.c_str(), kXMP_PropArrayIsOrdered, (XMP_StringPtr)bytePtr ); bytePtr += nameLen; } if ( (byteEnd - bytePtr) != (8 * columns * rows) ) goto BadExif; // Make sure the values are present. SXMPUtils::ComposeStructFieldPath ( xmpNS, xmpProp, kXMP_NS_EXIF, "Values", &arrayPath ); XMP_Int32 * binPtr = (XMP_Int32*)bytePtr; for ( size_t i = (columns * rows); i > 0; --i, binPtr += 2 ) { XMP_Int32 binNum = binPtr[0]; XMP_Int32 binDenom = binPtr[1]; if ( ! nativeEndian ) { Flip4 ( &binNum ); Flip4 ( &binDenom ); } snprintf ( buffer, sizeof(buffer), "%ld/%ld", binNum, binDenom ); // AUDIT: Use of sizeof(buffer) is safe. xmp->AppendArrayItem ( xmpNS, arrayPath.c_str(), kXMP_PropArrayIsOrdered, buffer ); } return; BadExif: // Ignore the tag if the table is ill-formed. xmp->DeleteProperty ( xmpNS, xmpProp ); return; } catch ( ... ) { // Do nothing, let other imports proceed. // ? Notify client? }} // ImportTIFF_OECFTable// =================================================================================================// ImportTIFF_SFRTable// ===================// // 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_SFRTable ( 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); XMP_Uns16 rows = *((XMP_Uns16*)(bytePtr+2)); if ( ! nativeEndian ) { columns = Flip2 ( columns ); rows = Flip2 ( rows ); } char buffer[40]; snprintf ( buffer, sizeof(buffer), "%d", columns ); // AUDIT: Use of sizeof(buffer) is safe. xmp->SetStructField ( xmpNS, xmpProp, kXMP_NS_EXIF, "Columns", buffer ); snprintf ( buffer, sizeof(buffer), "%d", rows ); // AUDIT: Use of sizeof(buffer) is safe. xmp->SetStructField ( xmpNS, xmpProp, kXMP_NS_EXIF, "Rows", buffer ); std::string arrayPath; SXMPUtils::ComposeStructFieldPath ( xmpNS, xmpProp, kXMP_NS_EXIF, "Names", &arrayPath ); bytePtr += 4; // Move to the list of names. for ( size_t i = columns; i > 0; --i ) { size_t nameLen = strlen((XMP_StringPtr)bytePtr) + 1; // ! Include the terminating nul. if ( (bytePtr + nameLen) > byteEnd ) goto BadExif; xmp->AppendArrayItem ( xmpNS, arrayPath.c_str(), kXMP_PropArrayIsOrdered, (XMP_StringPtr)bytePtr ); bytePtr += nameLen; } if ( (byteEnd - bytePtr) != (8 * columns * rows) ) goto BadExif; // Make sure the values are present. SXMPUtils::ComposeStructFieldPath ( xmpNS, xmpProp, kXMP_NS_EXIF, "Values", &arrayPath ); XMP_Uns32 * binPtr = (XMP_Uns32*)bytePtr; for ( size_t i = (columns * rows); i > 0; --i, binPtr += 2 ) { XMP_Uns32 binNum = binPtr[0]; XMP_Uns32 binDenom = binPtr[1]; if ( ! nativeEndian ) { binNum = Flip4 ( binNum ); binDenom = Flip4 ( binDenom ); } snprintf ( buffer, sizeof(buffer), "%lu/%lu", binNum, binDenom ); // AUDIT: Use of sizeof(buffer) is safe. xmp->AppendArrayItem ( xmpNS, arrayPath.c_str(), kXMP_PropArrayIsOrdered, buffer ); } return; BadExif: // Ignore the tag if the table is ill-formed. xmp->DeleteProperty ( xmpNS, xmpProp ); return; } catch ( ... ) { // Do nothing, let other imports proceed. // ? Notify client? }} // ImportTIFF_SFRTable// =================================================================================================// ImportTIFF_CFATable// ===================static voidImportTIFF_CFATable ( 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); XMP_Uns16 rows = *((XMP_Uns16*)(bytePtr+2)); if ( ! nativeEndian ) { columns = Flip2 ( columns ); rows = Flip2 ( rows ); } char buffer[20]; std::string arrayPath; snprintf ( buffer, sizeof(buffer), "%d", columns ); // AUDIT: Use of sizeof(buffer) is safe. xmp->SetStructField ( xmpNS, xmpProp, kXMP_NS_EXIF, "Columns", buffer ); snprintf ( buffer, sizeof(buffer), "%d", rows ); // AUDIT: Use of sizeof(buffer) is safe. xmp->SetStructField ( xmpNS, xmpProp, kXMP_NS_EXIF, "Rows", buffer ); bytePtr += 4; // Move to the matrix of values. if ( (byteEnd - bytePtr) != (columns * rows) ) goto BadExif; // Make sure the values are present. SXMPUtils::ComposeStructFieldPath ( xmpNS, xmpProp, kXMP_NS_EXIF, "Values", &arrayPath ); for ( size_t i = (columns * rows); i > 0; --i, ++bytePtr ) { snprintf ( buffer, sizeof(buffer), "%hu", *bytePtr ); // AUDIT: Use of sizeof(buffer) is safe. xmp->AppendArrayItem ( xmpNS, arrayPath.c_str(), kXMP_PropArrayIsOrdered, buffer ); } return; BadExif: // Ignore the tag if the table is ill-formed. xmp->DeleteProperty ( xmpNS, xmpProp ); return; } catch ( ... ) { // Do nothing, let other imports proceed. // ? Notify client? }} // ImportTIFF_CFATable// =================================================================================================// ImportTIFF_DSDTable// ===================static voidImportTIFF_DSDTable ( 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. const XMP_Uns8 * bytePtr = (XMP_Uns8*)tagInfo.dataPtr; const XMP_Uns8 * byteEnd = bytePtr + tagInfo.dataLen; XMP_Uns16 columns = *((XMP_Uns16*)bytePtr); XMP_Uns16 rows = *((XMP_Uns16*)(bytePtr+2)); if ( ! tiff.IsNativeEndian() ) { columns = Flip2 ( columns ); rows = Flip2 ( rows ); } char buffer[20]; snprintf ( buffer, sizeof(buffer), "%d", columns ); // AUDIT: Use of sizeof(buffer) is safe. xmp->SetStructField ( xmpNS, xmpProp, kXMP_NS_EXIF, "Columns", buffer ); snprintf ( buffer, sizeof(buffer), "%d", rows ); // AUDIT: Use of sizeof(buffer) is safe. xmp->SetStructField ( xmpNS, xmpProp, kXMP_NS_EXIF, "Rows", buffer ); std::string arrayPath; SXMPUtils::ComposeStructFieldPath ( xmpNS, xmpProp, kXMP_NS_EXIF, "Settings", &arrayPath ); bytePtr += 4; // Move to the list of settings. UTF16Unit * utf16Ptr = (UTF16Unit*)bytePtr; UTF16Unit * utf16End = (UTF16Unit*)byteEnd; std::string utf8; // Figure 17 in the Exif 2.2 spec is unclear. It has counts for rows and columns, but the // settings are listed as 1..n, not as a rectangular matrix. So, ignore the counts and copy // strings until the end of the Exif value. while ( utf16Ptr < utf16End ) { size_t nameLen = 0; while ( utf16Ptr[nameLen] != 0 ) ++nameLen; ++nameLen; // ! Include the terminating nul. if ( (utf16Ptr + nameLen) > utf16End ) goto BadExif; try { FromUTF16 ( utf16Ptr, nameLen, &utf8, tiff.IsBigEndian() ); } catch ( ... ) { goto BadExif; // Ignore the tag if there are conversion errors. } xmp->AppendArrayItem ( xmpNS, arrayPath.c_str(), kXMP_PropArrayIsOrdered, utf8.c_str() ); utf16Ptr += nameLen; } return; BadExif: // Ignore the tag if the table is ill-formed. xmp->DeleteProperty ( xmpNS, xmpProp ); return; } catch ( ... ) { // Do nothing, let other imports proceed. // ? Notify client? }} // ImportTIFF_DSDTable// =================================================================================================// ImportTIFF_GPSCoordinate// ========================static voidImportTIFF_GPSCoordinate ( const TIFF_Manager & tiff, const TIFF_Manager::TagInfo & posInfo, SXMPMeta * xmp, const char * xmpNS, const char * xmpProp ){ try { // Don't let errors with one stop the others. const bool nativeEndian = tiff.IsNativeEndian(); XMP_Uns16 refID = posInfo.id - 1; // ! The GPS refs and coordinates are all tag n and n+1. TIFF_Manager::TagInfo refInfo; bool found = tiff.GetTag ( kTIFF_GPSInfoIFD, refID, &refInfo ); if ( (! found) || (refInfo.type != kTIFF_ASCIIType) || (refInfo.count != 2) ) return; char ref = *((char*)refInfo.dataPtr); XMP_Uns32 * binPtr = (XMP_Uns32*)posInfo.dataPtr; XMP_Uns32 degNum = binPtr[0]; XMP_Uns32 degDenom = binPtr[1]; XMP_Uns32 minNum = binPtr[2]; XMP_Uns32 minDenom = binPtr[3]; XMP_Uns32 secNum = binPtr[4]; XMP_Uns32 secDenom = binPtr[5]; if ( ! nativeEndian ) { degNum = Flip4 ( degNum ); degDenom = Flip4 ( degDenom ); minNum = Flip4 ( minNum ); minDenom = Flip4 ( minDenom ); secNum = Flip4 ( secNum ); secDenom = Flip4 ( secDenom ); } char buffer[40]; if ( (degDenom == 1) && (minDenom == 1) && (secDenom == 1) ) { snprintf ( buffer, sizeof(buffer), "%lu,%lu,%lu%c", degNum, minNum, secNum, ref ); // AUDIT: Using sizeof(buffer is safe. } else { XMP_Uns32 maxDenom = degDenom; if ( minDenom > degDenom ) maxDenom = minDenom; if ( secDenom > degDenom ) maxDenom = secDenom; int fracDigits = 1; while ( maxDenom > 10 ) { ++fracDigits; maxDenom = maxDenom/10; } double temp = (double)degNum / (double)degDenom; double degrees = (double)((XMP_Uns32)temp); // Just the integral number of degrees. double minutes = ((temp - degrees) * 60.0) + ((double)minNum / (double)minDenom) + (((double)secNum / (double)secDenom) / 60.0); snprintf ( buffer, sizeof(buffer), "%.0f,%.*f%c", degrees, fracDigits, minutes, ref ); // AUDIT: Using sizeof(buffer is safe. } xmp->SetProperty ( xmpNS, xmpProp, buffer ); } catch ( ... ) { // Do nothing, let other imports proceed. // ? Notify client? }} // ImportTIFF_GPSCoordinate// =================================================================================================// ImportTIFF_GPSTimeStamp// =======================static voidImportTIFF_GPSTimeStamp ( const TIFF_Manager & tiff, const TIFF_Manager::TagInfo & timeInfo, SXMPMeta * xmp, const char * xmpNS, const char * xmpProp ){ try { // Don't let errors with one stop the others. const bool nativeEndian = tiff.IsNativeEndian(); bool haveDate; TIFF_Manager::TagInfo dateInfo; haveDate = tiff.GetTag ( kTIFF_GPSInfoIFD, kTIFF_GPSDateStamp, &dateInfo ); if ( ! haveDate ) haveDate = tiff.GetTag ( kTIFF_ExifIFD, kTIFF_DateTimeOriginal, &dateInfo ); if ( ! haveDate ) haveDate = tiff.GetTag ( kTIFF_ExifIFD, kTIFF_DateTimeDigitized, &dateInfo ); if ( ! haveDate ) return; const char * dateStr = (const char *) dateInfo.dataPtr; if ( (dateStr[4] != ':') || (dateStr[7] != ':') ) return; if ( (dateStr[10] != 0) && (dateStr[10] != ' ') ) return; XMP_Uns32 * binPtr = (XMP_Uns32*)timeInfo.dataPtr; XMP_Uns32 hourNum = binPtr[0]; XMP_Uns32 hourDenom = binPtr[1]; XMP_Uns32 minNum = binPtr[2]; XMP_Uns32 minDenom = binPtr[3]; XMP_Uns32 secNum = binPtr[4]; XMP_Uns32 secDenom = binPtr[5]; i
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -