summaryrefslogtreecommitdiff
path: root/XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp')
-rw-r--r--XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp117
1 files changed, 62 insertions, 55 deletions
diff --git a/XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp b/XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp
index aecfec1..5d06220 100644
--- a/XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp
+++ b/XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp
@@ -273,12 +273,6 @@ void PSIR_FileWriter::ParseMemoryResources ( const void* data, XMP_Uns32 length,
void PSIR_FileWriter::ParseFileResources ( XMP_IO* fileRef, XMP_Uns32 length )
{
- bool ok;
-
- this->DeleteExistingInfo();
- this->fileParsed = true;
- if ( length == 0 ) return;
-
// Parse the image resource block. We're using a map keyed by ID, so only one resource of each
// ID is recognized. Redundant resources are not legit, but have been seen in the field. In
// particular, one case has been seen of a duplicate IIM block with one empty. In general we
@@ -286,45 +280,54 @@ void PSIR_FileWriter::ParseFileResources ( XMP_IO* fileRef, XMP_Uns32 length )
// taken though if the current one is empty.
// ! Don't use map[id] to lookup, that creates a default entry if none exists!
+
+ // PSIR layout:
+ // - Uns32 type, usually '8BIM'
+ // - Uns16 ID
+ // - PString name
+ // - Uns8 optional pad for even alignment
+ // - Uns32 data size
+ // - data
+ // - Uns8 optional pad for even alignment
+
+ static const size_t kMinPSIRSize = 12; // 4+2+1+1+4
+
+ this->DeleteExistingInfo();
+ this->fileParsed = true;
+ if ( length == 0 ) return;
- IOBuffer ioBuf;
- ioBuf.filePos = fileRef->Offset();
-
- XMP_Int64 psirOrigin = ioBuf.filePos; // Need this to determine the resource data offsets.
- XMP_Int64 fileEnd = ioBuf.filePos + length;
+ XMP_Int64 psirOrigin = fileRef->Offset(); // Need this to determine the resource data offsets.
+ XMP_Int64 fileEnd = psirOrigin + length;
- std::string rsrcPName;
+ char nameBuffer [260]; // The name is a PString, at 1+255+1 including length and pad.
- while ( (ioBuf.filePos + (ioBuf.ptr - ioBuf.data)) < fileEnd ) {
+ while ( fileRef->Offset() < fileEnd ) {
- ok = CheckFileSpace ( fileRef, &ioBuf, 12 ); // The minimal image resource takes 12 bytes.
- if ( ! ok ) break; // Bad image resource. Throw instead?
+ if ( ! XIO::CheckFileSpace ( fileRef, kMinPSIRSize ) ) break; // Bad image resource.
- XMP_Int64 thisRsrcPos = ioBuf.filePos + (ioBuf.ptr - ioBuf.data);
+ XMP_Int64 thisRsrcPos = fileRef->Offset();
- XMP_Uns32 type = GetUns32BE(ioBuf.ptr);
- XMP_Uns16 id = GetUns16BE(ioBuf.ptr+4);
- ioBuf.ptr += 6; // Advance to the resource name.
+ XMP_Uns32 type = XIO::ReadUns32_BE ( fileRef );
+ XMP_Uns16 id = XIO::ReadUns16_BE ( fileRef );
- XMP_Uns16 nameLen = ioBuf.ptr[0]; // ! The length for the Pascal string.
+ XMP_Uns8 nameLen = XIO::ReadUns8 ( fileRef ); // ! The length for the Pascal string.
XMP_Uns16 paddedLen = (nameLen + 2) & 0xFFFE; // ! Round up to an even total. Yes, +2!
- ok = CheckFileSpace ( fileRef, &ioBuf, paddedLen+4 ); // Get the name text and the data length.
- if ( ! ok ) break; // Bad image resource. Throw instead?
+ if ( ! XIO::CheckFileSpace ( fileRef, paddedLen+4 ) ) break; // Bad image resource.
- if ( nameLen > 0 ) rsrcPName.assign ( (char*)(ioBuf.ptr), paddedLen ); // ! Include the length byte and pad.
+ nameBuffer[0] = nameLen;
+ fileRef->ReadAll ( &nameBuffer[1], paddedLen-1 ); // Include the pad byte, present for zero nameLen.
- ioBuf.ptr += paddedLen; // Move to the data length.
- XMP_Uns32 dataLen = GetUns32BE(ioBuf.ptr);
+ XMP_Uns32 dataLen = XIO::ReadUns32_BE ( fileRef );
XMP_Uns32 dataTotal = ((dataLen + 1) & 0xFFFFFFFEUL); // Round up to an even total.
- ioBuf.ptr += 4; // Advance to the resource data.
+ if ( ! XIO::CheckFileSpace ( fileRef, dataTotal ) ) break; // Bad image resource.
- XMP_Int64 thisDataPos = ioBuf.filePos + (ioBuf.ptr - ioBuf.data);
+ XMP_Int64 thisDataPos = fileRef->Offset();
XMP_Int64 nextRsrcPos = thisDataPos + dataTotal;
if ( type != k8BIM ) {
XMP_Uns32 fullRsrcLen = (XMP_Uns32) (nextRsrcPos - thisRsrcPos);
this->otherRsrcs.push_back ( OtherRsrcInfo ( (XMP_Uns32)thisRsrcPos, fullRsrcLen ) );
- MoveToOffset ( fileRef, nextRsrcPos, &ioBuf );
+ fileRef->Seek ( nextRsrcPos, kXMP_SeekFromStart );
continue;
}
@@ -335,7 +338,7 @@ void PSIR_FileWriter::ParseFileResources ( XMP_IO* fileRef, XMP_Uns32 length )
} else if ( (rsrcPos->second.dataLen == 0) && (newInfo.dataLen != 0) ) {
rsrcPos->second = newInfo;
} else {
- MoveToOffset ( fileRef, nextRsrcPos, &ioBuf );
+ fileRef->Seek ( nextRsrcPos, kXMP_SeekFromStart );
continue;
}
InternalRsrcInfo* rsrcPtr = &rsrcPos->second;
@@ -345,29 +348,17 @@ void PSIR_FileWriter::ParseFileResources ( XMP_IO* fileRef, XMP_Uns32 length )
if ( nameLen > 0 ) {
rsrcPtr->rsrcName = (XMP_Uns8*) malloc ( paddedLen );
if ( rsrcPtr->rsrcName == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );
- memcpy ( (void*)rsrcPtr->rsrcName, rsrcPName.c_str(), paddedLen ); // AUDIT: Safe, allocated enough bytes above.
+ memcpy ( (void*)rsrcPtr->rsrcName, nameBuffer, paddedLen ); // AUDIT: Safe, allocated enough bytes above.
}
if ( ! IsMetadataImgRsrc ( id ) ) {
- MoveToOffset ( fileRef, nextRsrcPos, &ioBuf );
+ fileRef->Seek ( nextRsrcPos, kXMP_SeekFromStart );
continue;
}
- rsrcPtr->dataPtr = malloc ( dataLen ); // ! Allocate after the IsMetadataImgRsrc check.
+ rsrcPtr->dataPtr = malloc ( dataTotal ); // ! Allocate after the IsMetadataImgRsrc check.
if ( rsrcPtr->dataPtr == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );
-
- if ( dataTotal <= kIOBufferSize ) {
- // The image resource data fits within the I/O buffer.
- ok = CheckFileSpace ( fileRef, &ioBuf, dataTotal );
- if ( ! ok ) break; // Bad image resource. Throw instead?
- memcpy ( (void*)rsrcPtr->dataPtr, ioBuf.ptr, dataLen ); // AUDIT: Safe, malloc'ed dataLen bytes above.
- ioBuf.ptr += dataTotal; // ! Add the rounded length.
- } else {
- // The image resource data is bigger than the I/O buffer.
- fileRef->Seek ( (ioBuf.filePos + (ioBuf.ptr - ioBuf.data)), kXMP_SeekFromStart );
- fileRef->ReadAll ( (void*)rsrcPtr->dataPtr, dataLen );
- FillBuffer ( fileRef, nextRsrcPos, &ioBuf );
- }
+ fileRef->ReadAll ( (void*)rsrcPtr->dataPtr, dataTotal );
}
@@ -492,11 +483,10 @@ XMP_Uns32 PSIR_FileWriter::UpdateMemoryResources ( void** dataPtr )
// ====================================
XMP_Uns32 PSIR_FileWriter::UpdateFileResources ( XMP_IO* sourceRef, XMP_IO* destRef,
- void * _ioBuf, XMP_AbortProc abortProc, void * abortArg )
+ XMP_AbortProc abortProc, void * abortArg,
+ XMP_ProgressTracker* progressTracker )
{
- IgnoreParam(_ioBuf);
const XMP_Uns32 zero32 = 0;
-
const bool checkAbort = (abortProc != 0);
struct RsrcHeader {
@@ -507,9 +497,29 @@ XMP_Uns32 PSIR_FileWriter::UpdateFileResources ( XMP_IO* sourceRef, XMP_IO* dest
if ( this->memParsed ) XMP_Throw ( "Not file based", kXMPErr_EnforceFailure );
- XMP_Int64 destLenOffset = destRef->Offset();
- XMP_Uns32 destLength = 0;
+ InternalRsrcMap::const_iterator rsrcPos;
+ InternalRsrcMap::const_iterator rsrcEnd = this->imgRsrcs.end();
+
+ if ( progressTracker != 0 ) {
+
+ float totalLength = 8;
+ for ( rsrcPos = this->imgRsrcs.begin(); rsrcPos != rsrcEnd; ++rsrcPos ) {
+ const InternalRsrcInfo& currRsrc = rsrcPos->second;
+ totalLength += (currRsrc.dataLen + 12);
+ }
+
+ size_t sizeOtherRsrc = this->otherRsrcs.size();
+ for ( size_t i = 0; i < sizeOtherRsrc; ++i ) {
+ totalLength += this->otherRsrcs[i].rsrcLength;
+ }
+
+ XMP_Assert ( progressTracker->WorkInProgress() );
+ progressTracker->AddTotalWork ( totalLength );
+
+ }
+ XMP_Uns32 destLength = 0;
+ XMP_Int64 destLenOffset = destRef->Offset();
destRef->Write ( &destLength, 4 ); // Write a placeholder for the new PSIR section length.
#if 0
@@ -532,13 +542,10 @@ XMP_Uns32 PSIR_FileWriter::UpdateFileResources ( XMP_IO* sourceRef, XMP_IO* dest
RsrcHeader outHeader;
outHeader.type = MakeUns32BE ( k8BIM );
- InternalRsrcMap::iterator rsrcPos = this->imgRsrcs.begin();
- InternalRsrcMap::iterator rsrcEnd = this->imgRsrcs.end();
-
// printf ( "\nPSIR_FileWriter::UpdateFileResources - 8BIM resources\n" );
- for ( ; rsrcPos != rsrcEnd; ++rsrcPos ) {
+ for ( rsrcPos = this->imgRsrcs.begin(); rsrcPos != rsrcEnd; ++rsrcPos ) {
- InternalRsrcInfo& currRsrc = rsrcPos->second;
+ const InternalRsrcInfo& currRsrc = rsrcPos->second;
outHeader.id = MakeUns16BE ( currRsrc.id );
destRef->Write ( &outHeader, 6 );