From 163f3ce7f17a143f58d857a5cba3cb7b24436a2a Mon Sep 17 00:00:00 2001 From: Robin Mills Date: Fri, 14 Oct 2016 12:44:41 +0000 Subject: [PATCH] #1243 Work-in-progress on writing ICC profiles. Fixed elusive issue in exiv2 -pS foo.jp2 --- include/exiv2/jp2image.hpp | 8 +++++++ src/jp2image.cpp | 49 +++++++++++++++++++++++++++++++++----- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/include/exiv2/jp2image.hpp b/include/exiv2/jp2image.hpp index 77318a91..1aba2b72 100644 --- a/include/exiv2/jp2image.hpp +++ b/include/exiv2/jp2image.hpp @@ -115,6 +115,14 @@ namespace Exiv2 @return 4 if opening or writing to the associated BasicIo fails */ EXV_DLLLOCAL void doWriteMetadata(BasicIo& oIo); + + /*! + @brief reformats the Jp2Header to store iccProfile + @param oldData DataBufRef to data in the file. + @param newData DataBufRef with updated data + @return length of box (including the 8 bytes of the box) + */ + uint32_t encodeJp2Header(const DataBuf& oldData,DataBuf& newData); //@} }; // class Jp2Image diff --git a/src/jp2image.cpp b/src/jp2image.cpp index e0e8e9c6..71111203 100644 --- a/src/jp2image.cpp +++ b/src/jp2image.cpp @@ -485,25 +485,32 @@ namespace Exiv2 { lf(out,bLF); - while (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox)) + while (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox) + && io_->tell() < position + box.length) // don't read beyond the box! { subBox.length = getLong((byte*)&subBox.length, bigEndian); subBox.type = getLong((byte*)&subBox.type, bigEndian); - if (subBox.type == kJp2BoxTypeClose || subBox.length < sizeof(box)) break ; - DataBuf data(subBox.length-sizeof(box)); io_->read(data.pData_,data.size_); if ( bPrint ) { out << Internal::stringFormat("%8ld | %8ld | sub:",io_->tell()-sizeof(box),subBox.length) << toAscii(subBox.type) - <<" | " << Internal::binaryToString(data,40,0); + <<" | " << Internal::binaryToString(data,30,0); bLF = true; } if(subBox.type == kJp2BoxTypeColorHeader) { long pad = 3 ; // don't know why there are 3 padding bytes + if ( bPrint ) { + out << " | pad:" ; + for ( int i = 0 ; i < 3 ; i++ ) out<< " " << (int) data.pData_[i]; + } long iccLength = getULong(data.pData_+pad, bigEndian); + if ( bPrint ) { + out << " | iccLength:" << iccLength ; + } + DataBuf icc(iccLength); if ( bICC ) out.write((const char*)icc.pData_,icc.size_); } @@ -589,6 +596,35 @@ namespace Exiv2 } // Jp2Image::writeMetadata + uint32_t Jp2Image::encodeJp2Header(const DataBuf& boxBuf,DataBuf& newBuf) + { + long result = boxBuf.size_; + newBuf.alloc(boxBuf.size_); + ::memcpy(newBuf.pData_,boxBuf.pData_,boxBuf.size_); +#ifdef DEBUG + Jp2BoxHeader& box= (Jp2BoxHeader&) *(Jp2BoxHeader*) boxBuf.pData_; + int32_t length = getLong((byte*)&box.length, bigEndian); + + uint32_t count = sizeof (Jp2BoxHeader); + char* p = (char*) boxBuf.pData_+sizeof(Jp2BoxHeader); + + bool done = false; + while ( !done ) { + Jp2BoxHeader& subBox = (Jp2BoxHeader&) *((Jp2BoxHeader*)p) ; + + subBox.length = getLong((byte*)&subBox.length, bigEndian); + subBox.type = getLong((byte*)&subBox.type, bigEndian); + done = subBox.length < sizeof(subBox) || subBox.type == kJp2BoxTypeClose || count >= length; + if ( !done ) { + std::cout << "subbox: "<< toAscii(subBox.type) << " length = " << subBox.length << std::endl; + p += subBox.length ; + count += subBox.length; + } + } +#endif + return (uint32_t) result ; + } + void Jp2Image::doWriteMetadata(BasicIo& outIo) { if (!io_->isopen()) throw Error(20); @@ -680,11 +716,12 @@ namespace Exiv2 { case kJp2BoxTypeJp2Header: { - + DataBuf newBuf ; + encodeJp2Header(boxBuf,newBuf); #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write JP2Header box (length: " << box.length << ")" << std::endl; #endif - if (outIo.write(boxBuf.pData_, boxBuf.size_) != boxBuf.size_) throw Error(21); + if (outIo.write(newBuf.pData_, newBuf.size_) != newBuf.size_) throw Error(21); // Write all updated metadata here, just after JP2Header.