diff --git a/include/exiv2/image.hpp b/include/exiv2/image.hpp index 8530d5cf..aa67171f 100644 --- a/include/exiv2/image.hpp +++ b/include/exiv2/image.hpp @@ -228,6 +228,17 @@ namespace Exiv2 { from the actual image until the writeMetadata() method is called. */ virtual void clearComment(); + /*! + @brief Set the image iccProfile. The new profile is not written + to the image until the writeMetadata() method is called. + @param iccProfile DataBuf containing profile (binary) + */ + virtual void setIccProfile(DataBuf& iccProfile); + /*! + @brief Erase iccProfile. the profile isnot not removed from + the actual image until the writeMetadata() method is called. + */ + virtual void clearIccProfile(); /*! @brief Copy all existing metadata from source Image. The data is copied into internal buffers and is not written to the image @@ -422,6 +433,7 @@ namespace Exiv2 { ExifData exifData_; //!< Exif data container IptcData iptcData_; //!< IPTC data container XmpData xmpData_; //!< XMP data container + DataBuf iccProfile_; //!< ICC buffer (binary data) std::string comment_; //!< User comment std::string xmpPacket_; //!< XMP packet int pixelWidth_; //!< image pixel width diff --git a/include/exiv2/jpgimage.hpp b/include/exiv2/jpgimage.hpp index b61bfc72..c04f5c5a 100644 --- a/include/exiv2/jpgimage.hpp +++ b/include/exiv2/jpgimage.hpp @@ -233,6 +233,7 @@ namespace Exiv2 { static const byte eoi_; //!< JPEG EOI marker static const byte app0_; //!< JPEG APP0 marker static const byte app1_; //!< JPEG APP1 marker + static const byte app2_; //!< JPEG APP2 marker static const byte app13_; //!< JPEG APP13 marker static const byte com_; //!< JPEG Comment marker static const byte sof0_; //!< JPEG Start-Of-Frame marker diff --git a/src/image.cpp b/src/image.cpp index 214c52e6..eceaf743 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -181,6 +181,7 @@ namespace Exiv2 { clearXmpPacket(); clearXmpData(); clearComment(); + clearIccProfile(); } ExifData& Image::exifData() @@ -283,6 +284,16 @@ namespace Exiv2 { comment_ = comment; } + void Image::setIccProfile(Exiv2::DataBuf& iccProfile) + { + iccProfile_ = iccProfile; + } + + void Image::clearIccProfile() + { + iccProfile_.release(); + } + void Image::setByteOrder(ByteOrder byteOrder) { byteOrder_ = byteOrder; diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp index 90a45646..7301ccef 100644 --- a/src/jpgimage.cpp +++ b/src/jpgimage.cpp @@ -67,6 +67,7 @@ namespace Exiv2 { const byte JpegBase::eoi_ = 0xd9; const byte JpegBase::app0_ = 0xe0; const byte JpegBase::app1_ = 0xe1; + const byte JpegBase::app2_ = 0xe2; const byte JpegBase::app13_ = 0xed; const byte JpegBase::com_ = 0xfe; @@ -351,6 +352,7 @@ namespace Exiv2 { bool foundCompletePsData = false; bool foundExifData = false; bool foundXmpData = false; + bool foundIccProfile = false; // Read section marker int marker = advanceToMarker(); @@ -449,6 +451,15 @@ namespace Exiv2 { } --search; } + else if ( !foundIccProfile && marker == app2_ ) { + // Seek to beginning and read the iccProfile + io_->seek(31 - bufRead, BasicIo::cur); + DataBuf iccProfile(size); + io_->read(iccProfile.pData_, iccProfile.size_); + if (io_->error() || io_->eof()) throw Error(14); + this->setIccProfile(iccProfile); + foundXmpData = true; + } else if ( pixelHeight_ == 0 && ( marker == sof0_ || marker == sof1_ || marker == sof2_ || marker == sof3_ || marker == sof5_ || marker == sof6_ @@ -799,6 +810,7 @@ namespace Exiv2 { int comPos = 0; int skipApp1Exif = -1; int skipApp1Xmp = -1; + int skipApp2IccProfile = -1; bool foundCompletePsData = false; std::vector skipApp13Ps3; int skipCom = -1; @@ -844,6 +856,12 @@ namespace Exiv2 { ++search; if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22); } + else if ( skipApp2IccProfile == -1 && marker == app2_) { + if (size < 31) throw Error(22); + skipApp2IccProfile = count; + ++search; + if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22); + } else if ( !foundCompletePsData && marker == app13_ && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) { #ifdef DEBUG @@ -995,6 +1013,20 @@ namespace Exiv2 { if (outIo.error()) throw Error(21); --search; } + if (iccProfile_.size_ > 0) { + // Write APP2 marker, size of APP2 field, and IccProfile + tmpBuf[0] = 0xff; + tmpBuf[1] = app2_; + + if (iccProfile_.size_ > 0xffff) throw Error(37, "IccProfile"); + us2Data(tmpBuf + 2, static_cast(iccProfile_.size_), bigEndian); + if (outIo.write(tmpBuf, 4) != 4) throw Error(21); + + // Write new iccProfile + if ( outIo.write(iccProfile_.pData_,iccProfile_.size_) != static_cast(iccProfile_.size_) ) throw Error(21); + if ( outIo.error() ) throw Error(21); + --search; + } if (foundCompletePsData || iptcData_.count() > 0) { // Set the new IPTC IRB, keeps existing IRBs but removes the // IPTC block if there is no new IPTC data to write diff --git a/src/pngimage.cpp b/src/pngimage.cpp index 67c316d7..bc5e9b7e 100644 --- a/src/pngimage.cpp +++ b/src/pngimage.cpp @@ -258,7 +258,8 @@ namespace Exiv2 { if( bDump ) { DataBuf dataBuf; - byte* data = new byte[dataOffset]; + byte* data = new byte[dataOffset+1]; + data[dataOffset]=0; io_->read(data,dataOffset); io_->seek(restore, BasicIo::beg); uint32_t name_l = (uint32_t) std::strlen((const char*)data)+1; // leading string length @@ -308,7 +309,7 @@ namespace Exiv2 { IptcData::printStructure(out,dataBuf.pData_,dataBuf.size_,depth); } } - delete [] data; + delete[] data; } io_->seek(dataOffset + 4 , BasicIo::cur); if (io_->error()) throw Error(14);