📄 tiff_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 "TIFF_Support.hpp"// =================================================================================================/// \file TIFF_FileWriter.cpp/// \brief TIFF_FileWriter is used for memory-based read-write access and all file-based access.////// \c TIFF_FileWriter is used for memory-based read-write access and all file-based access. The/// main internal data structure is the InternalTagMap, a std::map that uses the tag number as the/// key and InternalTagInfo as the value. There are 5 of these maps, one for each of the recognized/// IFDs. The maps contain an entry for each tag in the IFD, whether we capture the data or not. The/// dataPtr and dataLen fields in the InternalTagInfo are zero if the tag is not captured.// =================================================================================================// =================================================================================================// TIFF_FileWriter::TIFF_FileWriter// ================================//// Set big endian Get/Put routines so that routines are in place for creating TIFF without a parse.// Parsing will reset them to the proper endianness for the stream. Big endian is a good default// since JPEG and PSD files are big endian overall.TIFF_FileWriter::TIFF_FileWriter() : changed(false), memParsed(false), fileParsed(false), ownedStream(false), memStream(0), tiffLength(0){ XMP_Uns8 bogusTIFF [kEmptyTIFFLength]; bogusTIFF[0] = 0x4D; bogusTIFF[1] = 0x4D; bogusTIFF[2] = 0x00; bogusTIFF[3] = 0x2A; bogusTIFF[4] = bogusTIFF[5] = bogusTIFF[6] = bogusTIFF[7] = 0x00; (void) this->CheckTIFFHeader ( bogusTIFF, sizeof ( bogusTIFF ) ); } // TIFF_FileWriter::TIFF_FileWriter// =================================================================================================// TIFF_FileWriter::~TIFF_FileWriter// =================================//// The InternalTagInfo destructor will deallocate the data for changed tags. It does not know// whether they are memory-based or file-based though, so it won't deallocate captured but unchanged// file-based tags. Mark those as changed here to make the destructor deallocate them.TIFF_FileWriter::~TIFF_FileWriter(){ XMP_Assert ( ! (this->memParsed && this->fileParsed) ); if ( this->fileParsed && (this->jpegTNailPtr != 0) ) free ( this->jpegTNailPtr ); if ( this->ownedStream ) { XMP_Assert ( this->memStream != 0 ); free ( this->memStream ); } if ( this->fileParsed ) { for ( int ifd = 0; ifd < kTIFF_KnownIFDCount; ++ifd ) { InternalTagMap& currTagMap ( this->containedIFDs[ifd].tagMap ); InternalTagMap::iterator tagPos = currTagMap.begin(); InternalTagMap::iterator tagEnd = currTagMap.end(); for ( ; tagPos != tagEnd; ++tagPos ) { if ( tagPos->second.dataPtr != 0 ) tagPos->second.changed = true; } } }} // TIFF_FileWriter::~TIFF_FileWriter// =================================================================================================// TIFF_FileWriter::DeleteExistingInfo// ===================================void TIFF_FileWriter::DeleteExistingInfo(){ XMP_Assert ( ! (this->memParsed && this->fileParsed) ); if ( this->ownedStream ) free ( this->memStream ); // ! Current TIFF might be memory-parsed. this->memStream = 0; this->tiffLength = 0; for ( int ifd = 0; ifd < kTIFF_KnownIFDCount; ++ifd ) this->containedIFDs[ifd].clear(); this->changed = false; this->memParsed = false; this->fileParsed = false; this->ownedStream = false;} // TIFF_FileWriter::DeleteExistingInfo// =================================================================================================// TIFF_FileWriter::PickIFD// ========================XMP_Uns8 TIFF_FileWriter::PickIFD ( XMP_Uns8 ifd, XMP_Uns16 id ){ if ( ifd > kTIFF_LastRealIFD ) { if ( ifd != kTIFF_KnownIFD ) XMP_Throw ( "Invalid IFD number", kXMPErr_BadParam ); XMP_Throw ( "kTIFF_KnownIFD not yet implemented", kXMPErr_Unimplemented ); // *** Likely to stay unimplemented until there is a client need. } return ifd;} // TIFF_FileWriter::PickIFD// =================================================================================================// TIFF_FileWriter::FindTagInIFD// =============================const TIFF_FileWriter::InternalTagInfo* TIFF_FileWriter::FindTagInIFD ( XMP_Uns8 ifd, XMP_Uns16 id ) const{ ifd = PickIFD ( ifd, id ); const InternalTagMap& currIFD = this->containedIFDs[ifd].tagMap; InternalTagMap::const_iterator tagPos = currIFD.find ( id ); if ( tagPos == currIFD.end() ) return 0; return &tagPos->second;} // TIFF_FileWriter::FindTagInIFD// =================================================================================================// TIFF_FileWriter::GetIFD// =======================bool TIFF_FileWriter::GetIFD ( XMP_Uns8 ifd, TagInfoMap* ifdMap ) const { if ( ifd > kTIFF_LastRealIFD ) XMP_Throw ( "Invalid IFD number", kXMPErr_BadParam ); const InternalTagMap& currIFD = this->containedIFDs[ifd].tagMap; InternalTagMap::const_iterator tagPos = currIFD.begin(); InternalTagMap::const_iterator tagEnd = currIFD.end(); if ( ifdMap != 0 ) ifdMap->clear(); if ( tagPos == tagEnd ) return false; // Empty IFD. if ( ifdMap != 0 ) { for ( ; tagPos != tagEnd; ++tagPos ) { const InternalTagInfo& intInfo = tagPos->second; TagInfo extInfo ( intInfo.id, intInfo.type, intInfo.count, intInfo.dataPtr, intInfo.dataLen ); (*ifdMap)[intInfo.id] = extInfo; } } return true;} // TIFF_FileWriter::GetIFD// =================================================================================================// TIFF_FileWriter::GetValueOffset// ===============================XMP_Uns32 TIFF_FileWriter::GetValueOffset ( XMP_Uns8 ifd, XMP_Uns16 id ) const{ const InternalTagInfo* thisTag = this->FindTagInIFD ( ifd, id ); if ( (thisTag == 0) || (thisTag->origLen == 0) ) return 0; return thisTag->origOffset; } // TIFF_FileWriter::GetValueOffset// =================================================================================================// TIFF_FileWriter::GetTag// =======================bool TIFF_FileWriter::GetTag ( XMP_Uns8 ifd, XMP_Uns16 id, TagInfo* info ) const { const InternalTagInfo* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( info != 0 ) { info->id = thisTag->id; info->type = thisTag->type; info->count = thisTag->dataLen / kTIFF_TypeSizes[thisTag->type]; info->dataLen = thisTag->dataLen; info->dataPtr = (const void*)(thisTag->dataPtr); } return true; } // TIFF_FileWriter::GetTag// =================================================================================================// TIFF_FileWriter::SetTag// =======================void TIFF_FileWriter::SetTag ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns16 type, XMP_Uns32 count, const void* clientPtr ) { if ( (type < kTIFF_ByteType) || (type > kTIFF_LastType) ) XMP_Throw ( "Invalid TIFF tag type", kXMPErr_BadParam ); size_t typeSize = kTIFF_TypeSizes[type]; size_t fullSize = count * typeSize; ifd = PickIFD ( ifd, id ); InternalTagMap& currIFD = this->containedIFDs[ifd].tagMap; InternalTagMap::iterator tagPos = currIFD.find ( id ); if ( (tagPos != currIFD.end()) && (type == tagPos->second.type) && (count == tagPos->second.count) && (memcmp ( clientPtr, tagPos->second.dataPtr, tagPos->second.dataLen ) == 0) ) { return; // ! The value is unchanged, exit. } InternalTagInfo newTag ( id, type, count ); newTag.changed = true; newTag.dataLen = count * typeSize; if ( newTag.dataLen <= 4 ) { // The data is less than 4 bytes, store it in the dataOrOffset field. Numbers are already flipped. XMP_Assert ( sizeof ( newTag.dataOrOffset ) == 4 ); memcpy ( &newTag.dataOrOffset, clientPtr, newTag.dataLen ); // AUDIT: Safe, the length is <= 4. } else { // The data is more than 4 bytes, make a copy. newTag.dataPtr = (XMP_Uns8*) malloc ( newTag.dataLen ); if ( newTag.dataPtr == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory ); memcpy ( newTag.dataPtr, clientPtr, newTag.dataLen ); // AUDIT: Safe, malloc'ed newTag.dataLen bytes above. } if ( tagPos == currIFD.end() ) { currIFD[id] = newTag; } else { newTag.origLen = tagPos->second.origLen; newTag.origOffset = tagPos->second.origOffset; tagPos->second = newTag; // ! The InternalTagInfo assign operator transfers dataPtr ownership. } this->containedIFDs[ifd].changed = true; this->changed = true;} // TIFF_FileWriter::SetTag// =================================================================================================// TIFF_FileWriter::DeleteTag// ==========================void TIFF_FileWriter::DeleteTag ( XMP_Uns8 ifd, XMP_Uns16 id ) { ifd = PickIFD ( ifd, id ); InternalTagMap& currIFD = this->containedIFDs[ifd].tagMap; InternalTagMap::iterator tagPos = currIFD.find ( id ); if ( tagPos == currIFD.end() ) return; // ! Don't set the changed flags if the tag didn't exist. currIFD.erase ( tagPos ); this->containedIFDs[ifd].changed = true; this->changed = true;} // TIFF_FileWriter::DeleteTag// =================================================================================================// TIFF_FileWriter::GetTag_Integer// ===============================bool TIFF_FileWriter::GetTag_Integer ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32* data ) const { const InternalTagInfo* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( data != 0 ) { if ( thisTag->type == kTIFF_ShortType ) { if ( thisTag->dataLen != 2 ) return false; // Wrong count. *data = this->GetUns16 ( thisTag->dataPtr ); } else if ( thisTag->type == kTIFF_LongType ) { if ( thisTag->dataLen != 4 ) return false; // Wrong count. *data = this->GetUns32 ( thisTag->dataPtr ); } else { return false; } } return true;} // TIFF_FileWriter::GetTag_Integer// =================================================================================================// TIFF_FileWriter::GetTag_Byte// ============================bool TIFF_FileWriter::GetTag_Byte ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns8* data ) const{ const InternalTagInfo* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( (thisTag->type != kTIFF_ByteType) || (thisTag->dataLen != 1) ) return false; if ( data != 0 ) *data = *thisTag->dataPtr; return true;} // TIFF_FileWriter::GetTag_Byte// =================================================================================================// TIFF_FileWriter::GetTag_SByte// =============================bool TIFF_FileWriter::GetTag_SByte ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int8* data ) const{ const InternalTagInfo* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( (thisTag->type != kTIFF_SByteType) || (thisTag->dataLen != 1) ) return false; if ( data != 0 ) *data = *thisTag->dataPtr; return true;} // TIFF_FileWriter::GetTag_SByte// =================================================================================================// TIFF_FileWriter::GetTag_Short// =============================bool TIFF_FileWriter::GetTag_Short ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns16* data ) const{ const InternalTagInfo* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( (thisTag->type != kTIFF_ShortType) || (thisTag->dataLen != 2) ) return false; if ( data != 0 ) { *data = this->GetUns16 ( thisTag->dataPtr ); } return true;} // TIFF_FileWriter::GetTag_Short// =================================================================================================// TIFF_FileWriter::GetTag_SShort// ==============================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -