[SCM] exiv2 packaging branch, master, updated. debian/0.25-3.1-3734-gdcbc29a
Maximiliano Curia
maxy at moszumanska.debian.org
Thu Jul 13 17:46:18 UTC 2017
Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/exiv2.git;a=commitdiff;h=8e7eaa6
The following commit has been merged in the master branch:
commit 8e7eaa65a7983c28ff17211fa9ab92d2bdb7ee5b
Author: Robin Mills <robin at clanmills.com>
Date: Wed Mar 9 07:51:04 2016 +0000
#1057, #1064, #922, #1148. Work in progress. This is a composite patch of several matters in development. None are totally complete at this time.
---
include/exiv2/datasets.hpp | 5 +++
include/exiv2/image.hpp | 4 +-
src/actions.cpp | 98 ++++++++++++++++++++++++++++++++++++----------
src/actions.hpp | 5 +++
src/exiv2.cpp | 38 ++++++++++++++++--
src/exiv2app.hpp | 23 +++++++----
src/jpgimage.cpp | 62 ++++++++++++++++++++---------
src/tiffimage.cpp | 10 +++--
8 files changed, 190 insertions(+), 55 deletions(-)
diff --git a/include/exiv2/datasets.hpp b/include/exiv2/datasets.hpp
index 18a4bc3..ade488c 100644
--- a/include/exiv2/datasets.hpp
+++ b/include/exiv2/datasets.hpp
@@ -369,6 +369,11 @@ namespace Exiv2 {
typedef std::set<std::string>::const_iterator StringSet_i ;
typedef std::vector<std::string> StringVector ,*StringVector_p;
typedef std::vector<std::string>::const_iterator StringVector_i;
+ typedef std::vector<uint32_t> Uint32Vector ,*Uint32Vector_p;
+ typedef std::vector<uint32_t>::const_iterator Uint32Vector_i;
+ typedef std::vector<uint32_t> Uint32Vector ,*Uint32Vector_p;
+ typedef std::vector<uint32_t>::const_iterator Uint32Vector_i;
+
// *****************************************************************************
// free functions
diff --git a/include/exiv2/image.hpp b/include/exiv2/image.hpp
index eb87d9b..8530d5c 100644
--- a/include/exiv2/image.hpp
+++ b/include/exiv2/image.hpp
@@ -74,7 +74,9 @@ namespace Exiv2 {
/*!
@brief Options for printStructure
*/
- typedef enum { kpsNone, kpsBasic, kpsXMP, kpsRecursive, kpsIccProfile } PrintStructureOption;
+ typedef enum { kpsNone, kpsBasic, kpsXMP, kpsRecursive
+ , kpsIccProfile , kpsIptcErase
+ } PrintStructureOption;
/*!
@brief Abstract base class defining the interface for an image. This is
diff --git a/src/actions.cpp b/src/actions.cpp
index 4195847..e1d0d38 100644
--- a/src/actions.cpp
+++ b/src/actions.cpp
@@ -949,6 +949,10 @@ namespace Action {
if (0 == rc && Params::instance().target_ & Params::ctXmp) {
rc = eraseXmpData(image.get());
}
+ if (0 == rc && Params::instance().target_ & Params::ctIptcRaw) {
+ rc = printStructure(std::cout,Exiv2::kpsIptcErase);
+ }
+
if (0 == rc) {
image->writeMetadata();
}
@@ -965,6 +969,19 @@ namespace Action {
return 1;
} // Erase::run
+ int Erase::printStructure(std::ostream& out, Exiv2::PrintStructureOption option)
+ {
+ if (!Exiv2::fileExists(path_, true)) {
+ std::cerr << path_ << ": "
+ << _("Failed to open the file
");
+ return -1;
+ }
+ Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
+ assert(image.get() != 0);
+ image->printStructure(out,option);
+ return 0;
+ }
+
int Erase::eraseThumbnail(Exiv2::Image* image) const
{
Exiv2::ExifThumb exifThumb(image->exifData());
@@ -1033,25 +1050,29 @@ namespace Action {
int Extract::run(const std::string& path)
try {
path_ = path;
- int rc = 0;
- if (Params::instance().target_ & Params::ctThumb) {
+ int rc = 0;
+
+ if (!rc && Params::instance().target_ & Params::ctThumb) {
rc = writeThumbnail();
}
- if (Params::instance().target_ & Params::ctXmpSidecar) {
- std::string xmpPath = newFilePath(path_, ".xmp");
+ if (!rc && Params::instance().target_ & Params::ctXmpSidecar) {
+ std::string xmpPath = Params::instance().target_ & Params::ctStdInOut
+ ? "-" : newFilePath(path_, ".xmp");
if (dontOverwrite(xmpPath)) return 0;
rc = metacopy(path_, xmpPath, Exiv2::ImageType::xmp, false);
}
- if (Params::instance().target_ & Params::ctPreview) {
+ if (!rc && Params::instance().target_ & Params::ctPreview) {
rc = writePreviews();
}
- if (Params::instance().target_ & Params::ctIccProfile) {
+ if (!rc && Params::instance().target_ & Params::ctIccProfile) {
rc = writeIccProfile();
}
- if ( !(Params::instance().target_ & Params::ctXmpSidecar)
+ if (!rc
+ && !(Params::instance().target_ & Params::ctXmpSidecar)
&& !(Params::instance().target_ & Params::ctThumb)
&& !(Params::instance().target_ & Params::ctPreview)) {
- std::string exvPath = newFilePath(path_, ".exv");
+ std::string exvPath = Params::instance().target_ & Params::ctStdInOut
+ ? "-" : newFilePath(path_, ".exv");
if (dontOverwrite(exvPath)) return 0;
rc = metacopy(path_, exvPath, Exiv2::ImageType::exv, false);
}
@@ -1220,7 +1241,8 @@ namespace Action {
&& ( Params::instance().target_ & Params::ctExif
|| Params::instance().target_ & Params::ctIptc
|| Params::instance().target_ & Params::ctComment
- || Params::instance().target_ & Params::ctXmp)) {
+ || Params::instance().target_ & Params::ctXmp
+ || Params::instance().target_ & Params::ctXmpRaw)) {
std::string suffix = Params::instance().suffix_;
if (suffix.empty()) suffix = ".exv";
if (Params::instance().target_ & Params::ctXmpSidecar) suffix = ".xmp";
@@ -1915,15 +1937,18 @@ namespace {
} // tm2Str
int metacopy(const std::string& source,
- const std::string& target,
+ const std::string& tgt,
int targetType,
bool preserve)
{
+ // read the source metadata
+ int rc = -1 ;
if (!Exiv2::fileExists(source, true)) {
std::cerr << source
<< ": " << _("Failed to open the file
");
- return -1;
+ return rc;
}
+
Exiv2::Image::AutoPtr sourceImage = Exiv2::ImageFactory::open(source);
assert(sourceImage.get() != 0);
sourceImage->readMetadata();
@@ -1931,6 +1956,12 @@ namespace {
// Apply any modification commands to the source image on-the-fly
Action::Modify::applyCommands(sourceImage.get());
+ // Open or create the target file
+ std::string target = tgt;
+ bool bTemporary = target == "-";
+ if ( bTemporary ) {
+ target = Exiv2::FileIo::temporaryPath();
+ }
Exiv2::Image::AutoPtr targetImage;
if (Exiv2::fileExists(target)) {
targetImage = Exiv2::ImageFactory::open(target);
@@ -1941,6 +1972,8 @@ namespace {
targetImage = Exiv2::ImageFactory::create(targetType, target);
assert(targetImage.get() != 0);
}
+
+ // Copy each type of metadata
if ( Params::instance().target_ & Params::ctExif
&& !sourceImage->exifData().empty()) {
if (Params::instance().verbose_) {
@@ -1957,24 +1990,28 @@ namespace {
}
targetImage->setIptcData(sourceImage->iptcData());
}
- if ( Params::instance().target_ & Params::ctXmp
+ if ( Params::instance().target_ & (Params::ctXmp|Params::ctXmpRaw)
&& !sourceImage->xmpData().empty()) {
if (Params::instance().verbose_) {
std::cout << _("Writing XMP data from") << " " << source
<< " " << _("to") << " " << target << std::endl;
}
- // #1148 use XMP packet if there are no XMP modification commands
- if ( Params::instance().modifyCmds_.size() == 0
- && Params::instance().target_ == (Params::ctXmp | Params::ctXmpSidecar) // option -eXx
- ) {
+ // #1148 use Raw XMP packet if there are no XMP modification commands
+ int tRawSidecar = Params::ctXmpSidecar | Params::ctXmpRaw; // option -eXX
+ // printTarget("in metacopy",Params::instance().target_,true);
+ if( Params::instance().modifyCmds_.size() == 0
+ && (Params::instance().target_ & tRawSidecar) == tRawSidecar
+ ){
+ // std::cout << "short cut" << std::endl;
// http://www.cplusplus.com/doc/tutorial/files/
std::ofstream os;
os.open(target.c_str());
sourceImage->printStructure(os,Exiv2::kpsXMP);
os.close();
- return 0;
+ rc = 0;
} else {
+ // std::cout << "long cut" << std::endl;
targetImage->setXmpData(sourceImage->xmpData());
}
}
@@ -1986,16 +2023,35 @@ namespace {
}
targetImage->setComment(sourceImage->comment());
}
- try {
+ if ( rc < 0 ) try {
targetImage->writeMetadata();
+ rc=0;
}
catch (const Exiv2::AnyError& e) {
std::cerr << target <<
": " << _("Could not write metadata to file") << ": " << e << "
";
- return 1;
+ rc=1;
+ }
+
+ // if we used a temporary target, copy it to stdout
+ if ( rc == 0 && bTemporary ) {
+ FILE* f = ::fopen(target.c_str(),"rb") ;
+ if ( f ) {
+ char buffer[8*1024];
+ int n = 1 ;
+ while ( !feof(f) && n > 0) {
+ n=fread(buffer,1,sizeof buffer,f);
+ fwrite(buffer,1,n,stdout);
+ }
+ fclose(f);
+ }
+ std::cout << std::endl;
}
- return 0;
+ // delete temporary target
+ if ( bTemporary ) std::remove(target.c_str());
+
+ return rc;
} // metacopy
// Defined outside of the function so that Exiv2::find() can see it
@@ -2113,6 +2169,8 @@ namespace {
int dontOverwrite(const std::string& path)
{
+ if ( path == "-" ) return 0;
+
if (!Params::instance().force_ && Exiv2::fileExists(path)) {
std::cout << Params::instance().progname()
<< ": " << _("Overwrite") << " `" << path << "'? ";
diff --git a/src/actions.hpp b/src/actions.hpp
index be2cab2..cfc1d3a 100644
--- a/src/actions.hpp
+++ b/src/actions.hpp
@@ -274,6 +274,11 @@ namespace Action {
@brief Erase XMP packet from the file.
*/
int eraseXmpData(Exiv2::Image* image) const;
+ /*!
+ @brief Print image Structure information (used by ctIptcRaw/kpsIptcErase)
+ */
+ int printStructure(std::ostream& out, Exiv2::PrintStructureOption option);
+
private:
virtual Erase* clone_() const;
diff --git a/src/exiv2.cpp b/src/exiv2.cpp
index 22f72dd..d1d0fc3 100644
--- a/src/exiv2.cpp
+++ b/src/exiv2.cpp
@@ -238,6 +238,25 @@ void Params::usage(std::ostream& os) const
<< _("Manipulate the Exif metadata of images.
");
}
+std::string Params::printTarget(std::string before,int target,bool bPrint,std::ostream& out)
+{
+ std::string t;
+ if ( target & Params::ctExif ) t+= 'e';
+ if ( target & Params::ctXmpSidecar ) t+= 'X';
+ if ( target & Params::ctXmpRaw ) t+= target & Params::ctXmpSidecar ? 'X' : 'R' ;
+ if ( target & Params::ctIptc ) t+= 'i';
+ if ( target & Params::ctIccProfile ) t+= 'C';
+ if ( target & Params::ctIptcRaw ) t+= 'I';
+ if ( target & Params::ctXmp ) t+= 'x';
+ if ( target & Params::ctComment ) t+= 'c';
+ if ( target & Params::ctThumb ) t+= 't';
+ if ( target & Params::ctPreview ) t+= 'p';
+ if ( target & Params::ctStdInOut ) t+= '-';
+
+ if ( bPrint ) out << before << " :" << t << std::endl;
+ return t;
+}
+
void Params::help(std::ostream& os) const
{
usage(os);
@@ -1028,7 +1047,7 @@ namespace {
int parseCommonTargets(const std::string& optarg,
const std::string& action)
{
- int rc = 0;
+ int rc = 0;
int target = 0;
for (size_t i = 0; rc == 0 && i < optarg.size(); ++i) {
switch (optarg[i]) {
@@ -1038,14 +1057,25 @@ namespace {
case 'c': target |= Params::ctComment; break;
case 't': target |= Params::ctThumb; break;
case 'C': target |= Params::ctIccProfile; break;
+ case 'I': target |= Params::ctIptcRaw;break;
+ case '-': target |= Params::ctStdInOut;break;
case 'a': target |= Params::ctExif
| Params::ctIptc
| Params::ctComment
| Params::ctXmp; break;
case 'X':
- target |= Params::ctXmpSidecar;
- if (optarg == "X") target |= Params::ctExif | Params::ctIptc | Params::ctXmp;
- break;
+ Params::printTarget("X before",target);
+ target |= Params::ctXmpSidecar|Params::ctExif | Params::ctIptc | Params::ctXmp ; // -eX
+ Params::printTarget("X after1",target);
+
+ if ( i ) { // -eXX
+ target |= Params::ctXmpRaw ;
+ Params::printTarget("X after2",target);
+ target ^= Params::ctExif|Params::ctIptc|Params::ctXmp ; // turn off those bits
+ }
+ Params::printTarget("X ending",target,false);
+ break;
+
case 'p':
{
if (strcmp(action.c_str(), "extract") == 0) {
diff --git a/src/exiv2app.hpp b/src/exiv2app.hpp
index 7dc9fef..a629c33 100644
--- a/src/exiv2app.hpp
+++ b/src/exiv2app.hpp
@@ -171,14 +171,17 @@ public:
//! Enumerates common targets, bitmap
enum CommonTarget {
- ctExif = 1,
- ctIptc = 2,
- ctComment = 4,
- ctThumb = 8,
- ctXmp = 16,
- ctXmpSidecar = 32,
- ctPreview = 64,
- ctIccProfile =128
+ ctExif = 1,
+ ctIptc = 2,
+ ctComment = 4,
+ ctThumb = 8,
+ ctXmp = 16,
+ ctXmpSidecar = 32,
+ ctPreview = 64,
+ ctIccProfile = 128,
+ ctXmpRaw = 256,
+ ctStdInOut = 512,
+ ctIptcRaw =1024
};
//! Enumerates the policies to handle existing files in rename action
@@ -314,6 +317,10 @@ public:
//! Print version information to an output stream.
void version(bool verbose =false, std::ostream& os =std::cout) const;
+
+ //! Print target_
+ static std::string printTarget(std::string before,int target,bool bPrint=false,std::ostream& os=std::cout);
+
}; // class Params
#endif // #ifndef EXIV2APP_HPP_
diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp
index 493ecd6..a7979ff 100644
--- a/src/jpgimage.cpp
+++ b/src/jpgimage.cpp
@@ -538,7 +538,10 @@ namespace Exiv2 {
throw Error(15);
}
- if ( option == kpsBasic || option == kpsXMP || option == kpsIccProfile || option == kpsRecursive) {
+ bool bPrint = option==kpsBasic || option==kpsRecursive;
+ Exiv2::Uint32Vector iptcDataSegs;
+
+ if ( bPrint || option == kpsXMP || option == kpsIccProfile || option == kpsIptcErase ) {
// nmonic for markers
std::string nm[256] ;
@@ -576,13 +579,13 @@ namespace Exiv2 {
bool first= true;
while (!done) {
// print marker bytes
- if ( first && (option == kpsBasic||option==kpsRecursive) ) {
+ if ( first && bPrint ) {
out << "STRUCTURE OF JPEG FILE: " << io_->path() << std::endl;
out << " address | marker | length | data" << std::endl ;
REPORT_MARKER;
}
first = false;
- bool bLF = option == kpsBasic||option == kpsRecursive;
+ bool bLF = bPrint;
// Read size and signature
std::memset(buf.pData_, 0x0, buf.size_);
@@ -602,17 +605,22 @@ namespace Exiv2 {
){
size = getUShort(buf.pData_, bigEndian);
}
- if ( option == kpsBasic||option==kpsRecursive ) out << Internal::stringFormat(" | %7d ", size);
+ if ( bPrint ) out << Internal::stringFormat(" | %7d ", size);
// only print the signature for appn
if (marker >= app0_ && marker <= (app0_ | 0x0F)) {
- char http[5];
- http[4]=0;
- memcpy(http,buf.pData_+2,4);
-
- if ( option == kpsXMP && std::strcmp(http,"http") == 0 ) {
+ // http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf p75
+ const char* signature = (const char*) buf.pData_+2;
+
+ // 728 rmills at rmillsmbp:~/gnu/exiv2/ttt $ exiv2 -pS test/data/exiv2-bug922.jpg
+ // STRUCTURE OF JPEG FILE: test/data/exiv2-bug922.jpg
+ // address | marker | length | data
+ // 2 | 0xd8 SOI | 0
+ // 4 | 0xe1 APP1 | 911 | Exif..MM.*.......%.........#....
+ // 917 | 0xe1 APP1 | 870 | http://ns.adobe.com/xap/1.0/.<x:
+ // 1789 | 0xe1 APP1 | 65460 | http://ns.adobe.com/xmp/extensio
+ if ( option == kpsXMP && std::string(signature).find("http://ns.adobe.com/x")== 0 ) {
// extract XMP
- // http://ns.adobe.com/xap/1.0/
if ( size > 0 ) {
io_->seek(-bufRead , BasicIo::cur);
byte* xmp = new byte[size+1];
@@ -622,7 +630,10 @@ namespace Exiv2 {
// http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf
// if we find HasExtendedXMP, set the flag and ignore this block
// the first extended block is a copy of the Standard block.
- // a robust implementation enables extended blocks to be out of sequence
+ // a robust implementation allows extended blocks to be out of sequence
+ // we could implement out of sequence with a dictionary of sequence/offset
+ // and dumping the XMP in a post read operation similar to kpsIptcErase
+ // for the moment, dumping 'on the fly' is working fine
if ( ! bExtXMP ) {
while (xmp[start]) start++; start++;
if ( ::strstr((char*)xmp+start,"HasExtendedXMP") ) {
@@ -634,11 +645,11 @@ namespace Exiv2 {
}
xmp[size]=0;
- out << xmp + start; // this is all we need to output without the blank line dance.
+ out << xmp + start;
delete [] xmp;
bufRead = size;
}
- } else if ( option == kpsIccProfile && std::strcmp(http,"ICC_") == 0 ) {
+ } else if ( option == kpsIccProfile && std::strcmp(signature,"ICC_PROFILE") == 0 ) {
// extract ICCProfile
if ( size > 0 ) {
io_->seek(-bufRead , BasicIo::cur);
@@ -649,15 +660,22 @@ namespace Exiv2 {
bufRead = size;
delete [] icc;
}
- } else if ( option == kpsBasic||option==kpsRecursive ) {
+ } else if ( option == kpsIptcErase && std::strcmp(signature,"Photoshop 3.0") == 0 ) {
+ // delete IPTC data segment from JPEG
+ if ( size > 0 ) {
+ io_->seek(-bufRead , BasicIo::cur);
+ iptcDataSegs.push_back(io_->tell());
+ iptcDataSegs.push_back(size);
+ }
+ } else if ( bPrint ) {
out << "| " << Internal::binaryToString(buf,size>32?32:size,size>0?2:0);
}
// for MPF: http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/MPF.html
// for FLIR: http://owl.phy.queensu.ca/~phil/exiftool/TagNames/FLIR.html
- bool bFlir = option == kpsRecursive && marker == (app0_+1) && std::strcmp(http,"FLIR")==0;
- bool bExif = option == kpsRecursive && marker == (app0_+1) && std::strcmp(http,"Exif")==0;
- bool bMPF = option == kpsRecursive && marker == (app0_+2) && std::strcmp(http,"MPF")==0;
+ bool bFlir = option == kpsRecursive && marker == (app0_+1) && std::strcmp(signature,"FLIR")==0;
+ bool bExif = option == kpsRecursive && marker == (app0_+1) && std::strcmp(signature,"Exif")==0;
+ bool bMPF = option == kpsRecursive && marker == (app0_+2) && std::strcmp(signature,"MPF")==0;
if( bFlir || bExif || bMPF ) {
// extract Exif data block which is tiff formatted
if ( size > 0 ) {
@@ -670,7 +688,7 @@ namespace Exiv2 {
// copy the data to memory
io_->seek(-bufRead , BasicIo::cur);
io_->read(exif,size);
- uint32_t start = std::strcmp(http,"Exif")==0 ? 8 : 6;
+ uint32_t start = std::strcmp(signature,"Exif")==0 ? 8 : 6;
uint32_t max = (uint32_t) size -1;
// is this an fff block?
@@ -730,6 +748,14 @@ namespace Exiv2 {
}
}
}
+ if ( option == kpsIptcErase ) {
+ std::cout << "iptc data blocks: " << (iptcDataSegs.size() ? "FOUND" : "none") << std::endl;
+ uint32_t toggle = 0 ;
+ for ( Uint32Vector_i it = iptcDataSegs.begin(); it != iptcDataSegs.end() ; it++ ) {
+ std::cout << *it ;
+ if ( toggle++ % 2 ) std::cout << std::endl; else std::cout << ' ' ;
+ }
+ }
}
void JpegBase::writeMetadata()
diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp
index 324266a..d41934b 100644
--- a/src/tiffimage.cpp
+++ b/src/tiffimage.cpp
@@ -480,22 +480,24 @@ namespace Exiv2 {
// buffer
const size_t dirSize = 32;
DataBuf dir(dirSize);
+ bool bPrint = option == kpsBasic || option == kpsRecursive;
+
do {
// Read top of directory
io.seek(start,BasicIo::beg);
io.read(dir.pData_, 2);
uint16_t dirLength = byteSwap2(dir,0,bSwap);
- bool tooBig = dirLength > 200 ;
- bool bPrint = option == kpsBasic || option == kpsRecursive;
+ bool tooBig = dirLength > 500;
if ( bFirst && bPrint ) {
out << indent(depth) << Internal::stringFormat("STRUCTURE OF TIFF FILE (%c%c): ",c,c) << io.path() << std::endl;
if ( tooBig ) out << indent(depth) << "dirLength = " << dirLength << std::endl;
}
+ if (tooBig) break;
// Read the dictionary
- for ( int i = 0 ; !tooBig && i < dirLength ; i ++ ) {
+ for ( int i = 0 ; i < dirLength ; i ++ ) {
if ( bFirst && bPrint ) {
out << indent(depth)
<< " address | tag | "
@@ -594,7 +596,7 @@ namespace Exiv2 {
out.flush();
} while (start) ;
- if ( option == kpsBasic || option == kpsRecursive ) {
+ if ( bPrint ) {
out << indent(depth) << "END " << io.path() << std::endl;
}
depth--;
--
exiv2 packaging
More information about the pkg-kde-commits
mailing list