void Matroska_MetaHandler::UpdateFile(bool doSafeUpdate) { if (!needsUpdate) return; // If needsUpdate is set then at least the XMP changed. needsUpdate = false; // Make sure only called once. XMP_Assert(!doSafeUpdate); // This should only be called for "unsafe" updates. XMP_Assert(parent && parent->ioRef); XMP_AbortProc abortProc = parent->abortProc; void * abortArg = parent->abortArg; const bool checkAbort = (abortProc != 0); bool localProgressTracking(false); XMP_ProgressTracker* progressTracker = parent->progressTracker; if (progressTracker) { float xmpSize = static_cast<float>(xmpPacket.size()); if (progressTracker->WorkInProgress()) { progressTracker->AddTotalWork(xmpSize); } else { localProgressTracking = true; progressTracker->BeginWork(xmpSize); } } UpdateXMP(); if (localProgressTracking) progressTracker->WorkComplete(); }
void Matroska_MetaHandler::WriteTempFile(XMP_IO* tempRef) { XMP_Assert(needsUpdate); XMP_IO* originalRef = parent->ioRef; bool localProgressTracking(false); XMP_ProgressTracker* progressTracker = parent->progressTracker; if (progressTracker) { float xmpSize = static_cast<float>(xmpPacket.size()); if (progressTracker->WorkInProgress()) { progressTracker->AddTotalWork(xmpSize); } else { localProgressTracking = true; progressTracker->BeginWork(xmpSize); } } XMP_Assert(tempRef); XMP_Assert(originalRef); tempRef->Rewind(); originalRef->Rewind(); XIO::Copy(originalRef, tempRef, originalRef->Length(), parent->abortProc, parent->abortArg); try { parent->ioRef = tempRef; // ! Fool UpdateFile into using the temp file. UpdateFile(false); parent->ioRef = originalRef; } catch (...) { parent->ioRef = originalRef; throw; } if (localProgressTracking) progressTracker->WorkComplete(); }
void TIFF_MetaHandler::UpdateFile ( bool doSafeUpdate ) { XMP_Assert ( ! doSafeUpdate ); // This should only be called for "unsafe" updates. XMP_IO* destRef = this->parent->ioRef; XMP_AbortProc abortProc = this->parent->abortProc; void * abortArg = this->parent->abortArg; XMP_Int64 oldPacketOffset = this->packetInfo.offset; XMP_Int32 oldPacketLength = this->packetInfo.length; if ( oldPacketOffset == kXMPFiles_UnknownOffset ) oldPacketOffset = 0; // ! Simplify checks. if ( oldPacketLength == kXMPFiles_UnknownLength ) oldPacketLength = 0; bool fileHadXMP = ((oldPacketOffset != 0) && (oldPacketLength != 0)); // Update the IPTC-IIM and native TIFF/Exif metadata. ExportPhotoData also trips the tiff: and // exif: copies from the XMP, so reserialize the now final XMP packet. ExportPhotoData ( kXMP_TIFFFile, &this->xmpObj, &this->tiffMgr, this->iptcMgr, this->psirMgr ); try { XMP_OptionBits options = kXMP_UseCompactFormat; if ( fileHadXMP ) options |= kXMP_ExactPacketLength; this->xmpObj.SerializeToBuffer ( &this->xmpPacket, options, oldPacketLength ); } catch ( ... ) { this->xmpObj.SerializeToBuffer ( &this->xmpPacket, kXMP_UseCompactFormat ); } // Decide whether to do an in-place update. This can only happen if all of the following are true: // - There is an XMP packet in the file. // - The are no changes to the legacy tags. (The IPTC and PSIR are in the TIFF tags.) // - The new XMP can fit in the old space. bool doInPlace = (fileHadXMP && (this->xmpPacket.size() <= (size_t)oldPacketLength)); if ( this->tiffMgr.IsLegacyChanged() ) doInPlace = false; bool localProgressTracking = false; XMP_ProgressTracker* progressTracker = this->parent->progressTracker; if ( ! doInPlace ) { #if GatherPerformanceData sAPIPerf->back().extraInfo += ", TIFF append update"; #endif if ( (progressTracker != 0) && (! progressTracker->WorkInProgress()) ) { localProgressTracking = true; progressTracker->BeginWork(); } this->tiffMgr.SetTag ( kTIFF_PrimaryIFD, kTIFF_XMP, kTIFF_UndefinedType, (XMP_Uns32)this->xmpPacket.size(), this->xmpPacket.c_str() ); this->tiffMgr.UpdateFileStream ( destRef, progressTracker ); } else { #if GatherPerformanceData sAPIPerf->back().extraInfo += ", TIFF in-place update"; #endif if ( this->xmpPacket.size() < (size_t)this->packetInfo.length ) { // They ought to match, cheap to be sure. size_t extraSpace = (size_t)this->packetInfo.length - this->xmpPacket.size(); this->xmpPacket.append ( extraSpace, ' ' ); } XMP_IO* liveFile = this->parent->ioRef; XMP_Assert ( this->xmpPacket.size() == (size_t)oldPacketLength ); // ! Done by common PutXMP logic. if ( progressTracker != 0 ) { if ( progressTracker->WorkInProgress() ) { progressTracker->AddTotalWork ( this->xmpPacket.size() ); } else { localProgressTracking = true; progressTracker->BeginWork ( this->xmpPacket.size() ); } } liveFile->Seek ( oldPacketOffset, kXMP_SeekFromStart ); liveFile->Write ( this->xmpPacket.c_str(), (XMP_Int32)this->xmpPacket.size() ); } if ( localProgressTracking ) progressTracker->WorkComplete(); this->needsUpdate = false; } // TIFF_MetaHandler::UpdateFile