From 3d57bbc6e6036723df3c7da352e40267c90d1640 Mon Sep 17 00:00:00 2001 From: Robin Mills Date: Mon, 12 Sep 2016 17:42:12 +0000 Subject: [PATCH] #1074 Work in progress. ICC Jpeg/Png/Tiff exiv2 -eC foo.xxx writes good foo.icc profiles. icc-test.sh is broken and to be investigated. --- src/actions.cpp | 12 +++++------- src/jpgimage.cpp | 37 +++++++++++++++++++------------------ src/pngimage.cpp | 12 ++++++++++-- src/tiffimage.cpp | 24 +++++++++++++++++++++++- 4 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/actions.cpp b/src/actions.cpp index 503ba00c..35768e4b 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -1185,16 +1185,14 @@ namespace Action { image->readMetadata(); std::string iccPath = newFilePath(path_,".icc"); - std::filebuf iccBuffer ; - iccBuffer.open(iccPath.c_str(),std::ios::out); - std::ostream iccStream(&iccBuffer); - - image->printStructure(iccStream,Exiv2::kpsIccProfile); - - iccBuffer.close(); if (Params::instance().verbose_) { std::cout << _("Writing iccProfile: ") << iccPath << std::endl; } + Exiv2::FileIo iccFile(iccPath); + iccFile.open("wb") ; + iccFile.write(image->iccProfile()->pData_,image->iccProfile()->size_); + iccFile.close(); + return 0; } // Extract::writeIccProfile diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp index 893f39e5..338991a0 100644 --- a/src/jpgimage.cpp +++ b/src/jpgimage.cpp @@ -463,17 +463,34 @@ namespace Exiv2 { --search; } else if ( marker == app2_ && memcmp(buf.pData_ + 2, iccId_,11)==0) { - // skip the profile, we'll recover it later. + // ICC profile if ( ! foundIccData ) { foundIccData = true ; --search ; } - if (io_->seek(size - bufRead, BasicIo::cur)) throw Error(14); + #ifdef DEBUG int chunk = (int) buf.pData_[2+12]; int chunks = (int) buf.pData_[2+13]; std::cerr << "Found ICC Profile chunk " << chunk <<" of "<< chunks << "\n"; #endif + + io_->seek(-bufRead , BasicIo::cur); // back up to start of buffer (after marker+size) + io_->seek( 16 , BasicIo::cur); // step over header + // read in profile + DataBuf icc(size-2-16) ; + io_->read( icc.pData_,icc.size_); + + if ( iccProfile_.size_ > 0 ) { // first block of profile + setIccProfile(icc); + } else { // extend existing profile + DataBuf profile(iccProfile_.size_+icc.size_); + if ( iccProfile_.size_ ) { + ::memcpy(profile.pData_,iccProfile_.pData_,iccProfile_.size_); + } + ::memcpy(profile.pData_+iccProfile_.size_,icc.pData_,icc.size_); + setIccProfile(profile); + } } else if ( pixelHeight_ == 0 && inRange2(marker,sof0_,sof3_,sof5_,sof15_) ) { // We hit a SOFn (start-of-frame) marker @@ -533,22 +550,6 @@ 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) { #ifndef SUPPRESS_WARNINGS EXV_WARNING << "JPEG format error, rc = " << rc << "\n"; diff --git a/src/pngimage.cpp b/src/pngimage.cpp index bc5e9b7e..aa130c41 100644 --- a/src/pngimage.cpp +++ b/src/pngimage.cpp @@ -177,7 +177,6 @@ namespace Exiv2 { if (io_->open() != 0) { throw Error(9, io_->path(), strError()); } - IoCloser closer(*io_); // Ensure that this is the correct image type if (!isPngType(*io_, true)) { if (io_->error() || io_->eof()) throw Error(14); @@ -363,7 +362,8 @@ namespace Exiv2 { !memcmp(cheaderBuf.pData_ + 4, "IHDR", 4) || !memcmp(cheaderBuf.pData_ + 4, "tEXt", 4) || !memcmp(cheaderBuf.pData_ + 4, "zTXt", 4) || - !memcmp(cheaderBuf.pData_ + 4, "iTXt", 4)) + !memcmp(cheaderBuf.pData_ + 4, "iTXt", 4) || + !memcmp(cheaderBuf.pData_ + 4, "iCCP", 4)) { // Extract chunk data. @@ -408,6 +408,14 @@ namespace Exiv2 { #endif PngChunk::decodeTXTChunk(this, cdataBuf, PngChunk::iTXt_Chunk); } + else if (!memcmp(cheaderBuf.pData_ + 4, "iCCP", 4)) + { +#if 1 + std::cout << "Exiv2::PngImage::readMetadata: Found iCCP chunk (length: " << dataOffset << ")\n"; +#endif + zlibToDataBuf(cdataBuf.pData_ +12+1,dataOffset-13,iccProfile_); // +1 = 'compressed' flag + std::cout << "Exiv2::PngImage::readMetadata: size : " << iccProfile_.size_ << "\n"; + } // Set dataOffset to null like chunk data have been extracted previously. dataOffset = 0; diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp index b98693be..7184ec35 100644 --- a/src/tiffimage.cpp +++ b/src/tiffimage.cpp @@ -192,6 +192,15 @@ namespace Exiv2 { io_->mmap(), io_->size()); setByteOrder(bo); + + // read profile from the metadata + Exiv2::ExifKey key("Exif.Image.InterColorProfile"); + Exiv2::ExifData::iterator pos = exifData_.findKey(key); + if ( pos != exifData_.end() ) { + iccProfile_.alloc(pos->count()); + pos->copy(iccProfile_.pData_,bo); + } + } // TiffImage::readMetadata void TiffImage::writeMetadata() @@ -218,6 +227,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 +2525,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