📄 psir_filewriter.cpp
字号:
// =================================================================================================// ADOBE SYSTEMS INCORPORATED// Copyright 2006-2007 Adobe Systems Incorporated// All Rights Reserved//// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms// of the Adobe license agreement accompanying it.// =================================================================================================#include "PSIR_Support.hpp"#include "EndianUtils.hpp"// =================================================================================================/// \file PSIR_FileWriter.cpp/// \brief Implementation of the file-based or read-write form of PSIR_Manager.// =================================================================================================// =================================================================================================// IsMetadataImgRsrc// =================//// The only image resources of possible interest as metadata have type '8BIM' and IDs:// 1008, 1020, 1028, 1034, 1035, 1036, 1058, 1060, 1061static inline bool IsMetadataImgRsrc ( XMP_Uns16 id ){ if ( (id < 1008) || (id > 1061) ) { return false; } else if ( id >= 1058 ) { if ( id == 1059 ) return false; } else if ( id > 1036 ) { return false; } else if ( id > 1028 ) { if ( id < 1034 ) return false; } else if ( id < 1028 ) { if ( (id != 1008) && (id != 1020) ) return false; } return true;} // IsMetadataImgRsrc// =================================================================================================// PSIR_FileWriter::DeleteExistingInfo// ===================================//// Delete all existing info about image resources.void PSIR_FileWriter::DeleteExistingInfo(){ XMP_Assert ( ! (this->memParsed && this->fileParsed) ); if ( this->memParsed ) { if ( this->ownedContent ) free ( this->memContent ); } else { InternalRsrcMap::iterator irPos = this->imgRsrcs.begin(); InternalRsrcMap::iterator irEnd = this->imgRsrcs.end(); for ( ; irPos != irEnd; ++irPos ) irPos->second.changed = true; // Fool the InternalRsrcInfo destructor. } this->imgRsrcs.clear(); this->memContent = 0; this->memLength = 0; this->changed = false; this->memParsed = false; this->fileParsed = false; this->ownedContent = false;} // PSIR_FileWriter::DeleteExistingInfo// =================================================================================================// PSIR_FileWriter::~PSIR_FileWriter// =================================//// The InternalRsrcInfo destructor will deallocate the data for changed image resources. It does not// know whether they are memory-parsed or file-parsed though, so it won't deallocate captured but// unchanged file-parsed resources. Mark those as changed to make the destructor deallocate them.PSIR_FileWriter::~PSIR_FileWriter(){ XMP_Assert ( ! (this->memParsed && this->fileParsed) ); if ( this->ownedContent ) { XMP_Assert ( this->memContent != 0 ); free ( this->memContent ); } if ( this->fileParsed ) { InternalRsrcMap::iterator irPos = this->imgRsrcs.begin(); InternalRsrcMap::iterator irEnd = this->imgRsrcs.end(); for ( ; irPos != irEnd; ++irPos ) { if ( irPos->second.dataPtr != 0 ) irPos->second.changed = true; } } } // PSIR_FileWriter::~PSIR_FileWriter// =================================================================================================// PSIR_FileWriter::GetImgRsrc// ===========================bool PSIR_FileWriter::GetImgRsrc ( XMP_Uns16 id, ImgRsrcInfo* info ) const{ InternalRsrcMap::const_iterator rsrcPos = this->imgRsrcs.find ( id ); if ( rsrcPos == this->imgRsrcs.end() ) return false; const InternalRsrcInfo & rsrcInfo = rsrcPos->second; if ( info != 0 ) { info->id = rsrcInfo.id; info->dataLen = rsrcInfo.dataLen; info->dataPtr = rsrcInfo.dataPtr; info->origOffset = rsrcInfo.origOffset; } return true; } // PSIR_FileWriter::GetImgRsrc// =================================================================================================// PSIR_FileWriter::SetImgRsrc// ===========================void PSIR_FileWriter::SetImgRsrc ( XMP_Uns16 id, const void* clientPtr, XMP_Uns32 length ){ InternalRsrcMap::iterator rsrcPos = this->imgRsrcs.find ( id ); if ( (rsrcPos != this->imgRsrcs.end()) && (length == rsrcPos->second.dataLen) && (memcmp ( rsrcPos->second.dataPtr, clientPtr, length ) == 0) ) { return; // ! The value is unchanged, exit. } void* dataPtr = malloc ( length ); if ( dataPtr == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory ); memcpy ( dataPtr, clientPtr, length ); // AUDIT: Safe, malloc'ed length bytes above. if ( rsrcPos == this->imgRsrcs.end() ) { // This resource is not yet in the map, create the map entry. InternalRsrcInfo newRsrc ( id, length, dataPtr, (XMP_Uns32)(-1) ); newRsrc.changed = true; this->imgRsrcs[id] = newRsrc; } else { // This resource is in the map, update the existing map entry. InternalRsrcInfo* rsrcInfo = &rsrcPos->second; if ( rsrcInfo->changed && (rsrcInfo->dataPtr != 0) ) free ( rsrcInfo->dataPtr ); rsrcInfo->dataPtr = dataPtr; rsrcInfo->dataLen = length; rsrcInfo->changed = true; } this->changed = true;} // PSIR_FileWriter::SetImgRsrc// =================================================================================================// PSIR_FileWriter::DeleteImgRsrc// ==============================void PSIR_FileWriter::DeleteImgRsrc ( XMP_Uns16 id ){ InternalRsrcMap::iterator rsrcPos = this->imgRsrcs.find ( id ); if ( rsrcPos == this->imgRsrcs.end() ) return; // Nothing to delete. this->imgRsrcs.erase ( id ); this->changed = true;} // PSIR_FileWriter::DeleteImgRsrc// =================================================================================================// PSIR_FileWriter::IsLegacyChanged// ================================bool PSIR_FileWriter::IsLegacyChanged(){ if ( ! this->changed ) return false; InternalRsrcMap::iterator irPos = this->imgRsrcs.begin(); InternalRsrcMap::iterator irEnd = this->imgRsrcs.end(); for ( ; irPos != irEnd; ++irPos ) { const InternalRsrcInfo & rsrcInfo = irPos->second; if ( rsrcInfo.changed && (rsrcInfo.id != kPSIR_XMP) ) return true; } return false; // Can get here if the XMP is the only thing changed. } // PSIR_FileWriter::IsLegacyChanged// =================================================================================================// PSIR_FileWriter::ParseMemoryResources// =====================================void PSIR_FileWriter::ParseMemoryResources ( const void* data, XMP_Uns32 length, bool copyData /* = true */ ){ this->DeleteExistingInfo(); this->memParsed = true; if ( length == 0 ) return; // Allocate space for the full in-memory data and copy it. if ( ! copyData ) { this->memContent = (XMP_Uns8*) data; XMP_Assert ( ! this->ownedContent ); } else { if ( length > 100*1024*1024 ) XMP_Throw ( "Outrageous length for memory-based PSIR", kXMPErr_BadPSIR ); this->memContent = (XMP_Uns8*) malloc ( length ); if ( this->memContent == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory ); memcpy ( this->memContent, data, length ); // AUDIT: Safe, malloc'ed length bytes above. this->ownedContent = true; } this->memLength = length; // Capture the info for all of the resources. XMP_Uns8* psirPtr = this->memContent; XMP_Uns8* psirEnd = psirPtr + length; XMP_Uns8* psirLimit = psirEnd - kMinImgRsrcSize; while ( psirPtr <= psirLimit ) { XMP_Uns8* origin = psirPtr; // The beginning of this resource. XMP_Uns32 type = GetUns32BE(psirPtr); XMP_Uns16 id = GetUns16BE(psirPtr+4); psirPtr += 6; // Advance to the resource name. XMP_Uns8* namePtr = psirPtr; XMP_Uns16 nameLen = namePtr[0]; // ! The length for the Pascal string, w/ room for "+2". psirPtr += ((nameLen + 2) & 0xFFFE); // ! Round up to an even offset. Yes, +2! if ( psirPtr > psirEnd-4 ) break; // Bad image resource. Throw instead? XMP_Uns32 dataLen = GetUns32BE(psirPtr); psirPtr += 4; // Advance to the resource data. XMP_Uns32 dataOffset = psirPtr - this->memContent; XMP_Uns8* nextRsrc = psirPtr + ((dataLen + 1) & 0xFFFFFFFEUL); // ! Round up to an even offset. if ( (dataLen > length) || (psirPtr > psirEnd-dataLen) ) break; // Bad image resource. Throw instead? if ( type == k8BIM ) { InternalRsrcInfo newRsrc ( id, dataLen, psirPtr, dataOffset ); this->imgRsrcs[id] = newRsrc; if ( nameLen != 0 ) this->imgRsrcs[id].rsrcName = namePtr; } else { XMP_Uns32 rsrcOffset = origin - this->memContent; XMP_Uns32 rsrcLength = nextRsrc - origin; // Includes trailing pad. XMP_Assert ( (rsrcLength & 1) == 0 ); this->otherRsrcs.push_back ( OtherRsrcInfo ( rsrcOffset, rsrcLength ) ); } psirPtr = nextRsrc; }} // PSIR_FileWriter::ParseMemoryResources// =================================================================================================// PSIR_FileWriter::ParseFileResources// ===================================void PSIR_FileWriter::ParseFileResources ( LFA_FileRef fileRef, XMP_Uns32 length ){ bool ok; this->DeleteExistingInfo(); this->fileParsed = true; if ( length == 0 ) return; // Parse the image resource block. IOBuffer ioBuf; ioBuf.filePos = LFA_Seek ( fileRef, 0, SEEK_CUR ); XMP_Int64 psirOrigin = ioBuf.filePos; // Need this to determine the resource data offsets. XMP_Int64 fileEnd = ioBuf.filePos + length;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -