#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();
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

@ -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";

@ -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;

@ -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

Loading…
Cancel
Save