#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.

v0.27.3
Robin Mills 9 years ago
parent 9d06081616
commit 3d57bbc6e6

@ -1185,16 +1185,14 @@ namespace Action {
image->readMetadata(); image->readMetadata();
std::string iccPath = newFilePath(path_,".icc"); 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_) { if (Params::instance().verbose_) {
std::cout << _("Writing iccProfile: ") << iccPath << std::endl; 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; return 0;
} // Extract::writeIccProfile } // Extract::writeIccProfile

@ -463,17 +463,34 @@ namespace Exiv2 {
--search; --search;
} }
else if ( marker == app2_ && memcmp(buf.pData_ + 2, iccId_,11)==0) { else if ( marker == app2_ && memcmp(buf.pData_ + 2, iccId_,11)==0) {
// skip the profile, we'll recover it later. // ICC profile
if ( ! foundIccData ) { if ( ! foundIccData ) {
foundIccData = true ; foundIccData = true ;
--search ; --search ;
} }
if (io_->seek(size - bufRead, BasicIo::cur)) throw Error(14);
#ifdef DEBUG #ifdef DEBUG
int chunk = (int) buf.pData_[2+12]; int chunk = (int) buf.pData_[2+12];
int chunks = (int) buf.pData_[2+13]; int chunks = (int) buf.pData_[2+13];
std::cerr << "Found ICC Profile chunk " << chunk <<" of "<< chunks << "\n"; std::cerr << "Found ICC Profile chunk " << chunk <<" of "<< chunks << "\n";
#endif #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_) ) { else if ( pixelHeight_ == 0 && inRange2(marker,sof0_,sof3_,sof5_,sof15_) ) {
// We hit a SOFn (start-of-frame) marker // We hit a SOFn (start-of-frame) marker
@ -533,22 +550,6 @@ namespace Exiv2 {
} }
} // psBlob.size() > 0 } // 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) { if (rc != 0) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "JPEG format error, rc = " << rc << "\n"; EXV_WARNING << "JPEG format error, rc = " << rc << "\n";

@ -177,7 +177,6 @@ namespace Exiv2 {
if (io_->open() != 0) { if (io_->open() != 0) {
throw Error(9, io_->path(), strError()); throw Error(9, io_->path(), strError());
} }
IoCloser closer(*io_);
// Ensure that this is the correct image type // Ensure that this is the correct image type
if (!isPngType(*io_, true)) { if (!isPngType(*io_, true)) {
if (io_->error() || io_->eof()) throw Error(14); if (io_->error() || io_->eof()) throw Error(14);
@ -363,7 +362,8 @@ namespace Exiv2 {
!memcmp(cheaderBuf.pData_ + 4, "IHDR", 4) || !memcmp(cheaderBuf.pData_ + 4, "IHDR", 4) ||
!memcmp(cheaderBuf.pData_ + 4, "tEXt", 4) || !memcmp(cheaderBuf.pData_ + 4, "tEXt", 4) ||
!memcmp(cheaderBuf.pData_ + 4, "zTXt", 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. // Extract chunk data.
@ -408,6 +408,14 @@ namespace Exiv2 {
#endif #endif
PngChunk::decodeTXTChunk(this, cdataBuf, PngChunk::iTXt_Chunk); 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. // Set dataOffset to null like chunk data have been extracted previously.
dataOffset = 0; dataOffset = 0;

@ -192,6 +192,15 @@ namespace Exiv2 {
io_->mmap(), io_->mmap(),
io_->size()); io_->size());
setByteOrder(bo); 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 } // TiffImage::readMetadata
void TiffImage::writeMetadata() void TiffImage::writeMetadata()
@ -218,6 +227,19 @@ namespace Exiv2 {
bo = littleEndian; bo = littleEndian;
} }
setByteOrder(bo); 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 TiffParser::encode(*io_, pData, size, bo, exifData_, iptcData_, xmpData_); // may throw
} // TiffImage::writeMetadata } // TiffImage::writeMetadata
@ -2503,7 +2525,7 @@ namespace Exiv2 {
{ 0x0214, ifd0Id }, // Exif.Image.ReferenceBlackWhite { 0x0214, ifd0Id }, // Exif.Image.ReferenceBlackWhite
{ 0x828d, ifd0Id }, // Exif.Image.CFARepeatPatternDim { 0x828d, ifd0Id }, // Exif.Image.CFARepeatPatternDim
{ 0x828e, ifd0Id }, // Exif.Image.CFAPattern { 0x828e, ifd0Id }, // Exif.Image.CFAPattern
{ 0x8773, ifd0Id }, // Exif.Image.InterColorProfile // { 0x8773, ifd0Id }, // Exif.Image.InterColorProfile
{ 0x8824, ifd0Id }, // Exif.Image.SpectralSensitivity { 0x8824, ifd0Id }, // Exif.Image.SpectralSensitivity
{ 0x8828, ifd0Id }, // Exif.Image.OECF { 0x8828, ifd0Id }, // Exif.Image.OECF
{ 0x9102, ifd0Id }, // Exif.Image.CompressedBitsPerPixel { 0x9102, ifd0Id }, // Exif.Image.CompressedBitsPerPixel

Loading…
Cancel
Save