diff --git a/include/exiv2/image.hpp b/include/exiv2/image.hpp index a2ed2edf..11d4cb48 100644 --- a/include/exiv2/image.hpp +++ b/include/exiv2/image.hpp @@ -234,6 +234,11 @@ namespace Exiv2 { @param iccProfile DataBuf containing profile (binary) */ virtual void setIccProfile(DataBuf& iccProfile); + + /*! + @brief find the iccProfile using printStructure() and call setIccProfile() + */ + virtual void findIccProfile(); /*! @brief Erase iccProfile. the profile is not removed from the actual image until the writeMetadata() method is called. diff --git a/src/image.cpp b/src/image.cpp index 6fc0e4aa..38c82b0f 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -370,6 +370,25 @@ namespace Exiv2 { { return (supportedMetadata_ & metadataId) != 0; } + + void Image::findIccProfile() + { + if (io().open() != 0) return; + + long restore = io().tell(); + std::stringstream binary( std::ios_base::out | std::ios_base::in | std::ios_base::binary ); + io().seek(0,Exiv2::BasicIo::beg); + printStructure(binary,kpsIccProfile,0); + long length = (long) binary.rdbuf()->pubseekoff(0, binary.end, binary.out); + DataBuf iccProfile(length); + binary.rdbuf()->pubseekoff(0, binary.beg, binary.out); // rewind + binary.read((char*)iccProfile.pData_,iccProfile.size_); +#if 1 + std::cerr << "findIccProfile length:" << length <<" data:"<< Internal::binaryToString(iccProfile.pData_, length > 24?24:length,0) << std::endl; +#endif + setIccProfile(iccProfile); + io().seek(restore,Exiv2::BasicIo::beg); + } // findIccProfile AccessMode Image::checkMode(MetadataId metadataId) const { @@ -579,7 +598,7 @@ namespace Exiv2 { } return Image::AutoPtr(); } // ImageFactory::create - + // ***************************************************************************** // template, inline and free functions diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp index 893f39e5..fcf44c5b 100644 --- a/src/jpgimage.cpp +++ b/src/jpgimage.cpp @@ -533,21 +533,7 @@ namespace Exiv2 { } } // psBlob.size() > 0 - if ( rc==0 && foundIccData ) { - long restore = io_->tell(); - std::stringstream binary( std::ios_base::out | std::ios_base::in | std::ios_base::binary ); - io_->seek(0,Exiv2::BasicIo::beg); - printStructure(binary,kpsIccProfile,0); - long length = (long) binary.rdbuf()->pubseekoff(0, binary.end, binary.out); - DataBuf iccProfile(length); - binary.rdbuf()->pubseekoff(0, binary.beg, binary.out); // rewind - binary.read((char*)iccProfile.pData_,iccProfile.size_); -#if DEBUG - std::cerr << "iccProfile length:" << length <<" data:"<< Internal::binaryToString(iccProfile.pData_, length > 24?24:length,0) << std::endl; -#endif - setIccProfile(iccProfile); - io_->seek(restore,Exiv2::BasicIo::beg); - } + if ( rc==0 && foundIccData ) findIccProfile(); if (rc != 0) { #ifndef SUPPRESS_WARNINGS diff --git a/src/pngimage.cpp b/src/pngimage.cpp index bc5e9b7e..2041509b 100644 --- a/src/pngimage.cpp +++ b/src/pngimage.cpp @@ -334,7 +334,18 @@ namespace Exiv2 { throw Error(3, "PNG"); } clearMetadata(); - + /* + // Add icc profile to the metadata (see comments in writeMetadata()) + if ( iccProfile_.size_ == 0 ) { + findIccProfile(); + Exiv2::ExifKey key("Exif.Image.InterColorProfile"); + if ( iccProfile_.size_ > 0 && exifData_.findKey(key) == exifData_.end() ) { + Exiv2::DataValue value(iccProfile_.pData_,iccProfile_.size_); + exifData_.add(key,&value); + } + } + */ + const long imgSize = io_->size(); DataBuf cheaderBuf(8); // Chunk header size : 4 bytes (data size) + 4 bytes (chunk type). @@ -420,7 +431,7 @@ namespace Exiv2 { io_->seek(dataOffset + 4 , BasicIo::cur); if (io_->error() || io_->eof()) throw Error(14); } - + } // PngImage::readMetadata void PngImage::writeMetadata() @@ -455,6 +466,14 @@ namespace Exiv2 { if (io_->error() || io_->eof()) throw Error(20); throw Error(22); } + + // remove the ICC profile from the exifData because it's only "parked" + // we should not store ICC profiles in the ExifData + // PNG use an ICCP segment. + Exiv2::ExifKey key("Exif.Image.InterColorProfile"); + Exiv2::ExifData::iterator pos = exifData_.findKey(key); + if ( pos != exifData_.end() ) exifData_.erase(pos); + // Write PNG Signature. if (outIo.write(pngSignature, 8) != 8) throw Error(21); @@ -510,6 +529,17 @@ namespace Exiv2 { } } + if ( iccProfile_.size_ > 0 ) + { + // Update Comment data to a new PNG chunk + //std::string chunk = PngChunk::makeMetadataChunk(comment_, mdComment); + //if (outIo.write((const byte*)chunk.data(), static_cast(chunk.size())) != (long)chunk.size()) + //{ + // throw Error(21); + //} + std::cout << "found an ICC profile" << std::endl; + } + if (exifData_.count() > 0) { // Update Exif data to a new PNG chunk diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp index b98693be..f00cf715 100644 --- a/src/tiffimage.cpp +++ b/src/tiffimage.cpp @@ -218,6 +218,19 @@ namespace Exiv2 { bo = littleEndian; } setByteOrder(bo); + + // fixup ICC profile + Exiv2::ExifKey key("Exif.Image.InterColorProfile"); + Exiv2::ExifData::iterator pos = exifData_.findKey(key); + bool found = pos != exifData_.end(); + if ( iccProfile_.size_ > 0 ) { + Exiv2::DataValue value(iccProfile_.pData_,iccProfile_.size_); + if ( found ) pos->setValue(&value); + else exifData_.add(key,&value); + } else { + if ( found ) exifData_.erase(pos); + } + TiffParser::encode(*io_, pData, size, bo, exifData_, iptcData_, xmpData_); // may throw } // TiffImage::writeMetadata @@ -2503,7 +2516,7 @@ namespace Exiv2 { { 0x0214, ifd0Id }, // Exif.Image.ReferenceBlackWhite { 0x828d, ifd0Id }, // Exif.Image.CFARepeatPatternDim { 0x828e, ifd0Id }, // Exif.Image.CFAPattern - { 0x8773, ifd0Id }, // Exif.Image.InterColorProfile + // { 0x8773, ifd0Id }, // Exif.Image.InterColorProfile { 0x8824, ifd0Id }, // Exif.Image.SpectralSensitivity { 0x8828, ifd0Id }, // Exif.Image.OECF { 0x9102, ifd0Id }, // Exif.Image.CompressedBitsPerPixel