#922. Added options -pS and -pX to exiv2(.exe). Still to deal with -dI

v0.27.3
Robin Mills 10 years ago
parent 00f2c6cebd
commit 6c113871ef

@ -178,6 +178,8 @@ namespace Action {
void printMetadatum(const Exiv2::Metadatum& md, const Exiv2::Image* image); void printMetadatum(const Exiv2::Metadatum& md, const Exiv2::Image* image);
//! Print the label for a summary line //! Print the label for a summary line
void printLabel(const std::string& label) const; void printLabel(const std::string& label) const;
//! Print image Structure information
int printStructure(std::ostream& out,Exiv2::printStructureOption_e option);
/*! /*!
@brief Print one summary line with a label (if provided) and requested @brief Print one summary line with a label (if provided) and requested
data. A line break is printed only if a label is provided. data. A line break is printed only if a label is provided.

@ -71,6 +71,11 @@ namespace Exiv2 {
//! List of native previews. This is meant to be used only by the PreviewManager. //! List of native previews. This is meant to be used only by the PreviewManager.
typedef std::vector<NativePreview> NativePreviewList; typedef std::vector<NativePreview> NativePreviewList;
/*!
@brief options for printStructure
*/
typedef enum { kpsNone, kpsBasic, kpsXMP } printStructureOption_e ;
/*! /*!
@brief Abstract base class defining the interface for an image. This is @brief Abstract base class defining the interface for an image. This is
the top-level interface to the Exiv2 library. the top-level interface to the Exiv2 library.
@ -107,7 +112,7 @@ namespace Exiv2 {
@throw Error if reading of the file fails or the image data is @throw Error if reading of the file fails or the image data is
not valid (does not look like data of the specific image type). not valid (does not look like data of the specific image type).
*/ */
virtual void printStructure(); virtual void printStructure(std::ostream& out,printStructureOption_e option=kpsNone);
/*! /*!
@brief Read all metadata supported by a specific image format from the @brief Read all metadata supported by a specific image format from the
image. Before this method is called, the image metadata will be image. Before this method is called, the image metadata will be

@ -150,7 +150,7 @@ namespace Exiv2 {
public: public:
//! @name Manipulators //! @name Manipulators
//@{ //@{
void printStructure(); void printStructure(std::ostream& out,printStructureOption_e option);
void readMetadata(); void readMetadata();
void writeMetadata(); void writeMetadata();
//@} //@}

@ -84,7 +84,7 @@ namespace Exiv2
//! @name Manipulators //! @name Manipulators
//@{ //@{
void printStructure(); void printStructure(std::ostream& out,printStructureOption_e option);
void readMetadata(); void readMetadata();
void writeMetadata(); void writeMetadata();
//@} //@}

@ -241,6 +241,8 @@ namespace Action {
case Params::pmList: rc = printList(); break; case Params::pmList: rc = printList(); break;
case Params::pmComment: rc = printComment(); break; case Params::pmComment: rc = printComment(); break;
case Params::pmPreview: rc = printPreviewList(); break; case Params::pmPreview: rc = printPreviewList(); break;
case Params::pmStructure: rc = printStructure(std::cout,Exiv2::kpsBasic); break;
case Params::pmXMP: rc = printStructure(std::cout,Exiv2::kpsXMP); break;
} }
return rc; return rc;
} }
@ -250,6 +252,19 @@ namespace Action {
return 1; return 1;
} // Print::run } // Print::run
int Print::printStructure(std::ostream& out,Exiv2::printStructureOption_e option)
{
if (!Exiv2::fileExists(path_, true)) {
std::cerr << path_ << ": "
<< _("Failed to open the file\n");
return -1;
}
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
assert(image.get() != 0);
image->printStructure(out,option);
return 0;
}
int Print::printSummary() int Print::printSummary()
{ {
if (!Exiv2::fileExists(path_, true)) { if (!Exiv2::fileExists(path_, true)) {

@ -3,7 +3,7 @@
.\" First parameter, NAME, should be all caps .\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1) .\" other parameters are allowed: see man(7), man(1)
.TH EXIV2 1 "Mar 11, 2015" .TH EXIV2 1 "Mar 27, 2015"
.\" Please adjust this date whenever revising the manpage. .\" Please adjust this date whenever revising the manpage.
.\" .\"
.\" Some roff macros, for reference: .\" Some roff macros, for reference:
@ -231,6 +231,10 @@ x : XMP properties (\-PXkyct)
c : JPEG comment c : JPEG comment
.br .br
p : list available image previews, sorted by preview image size in pixels p : list available image previews, sorted by preview image size in pixels
.br
S : print image structure information (jpg and png only)
.br
X : print "raw" XMP (jpg and png only)
.TP .TP
.B \-P \fIflgs\fP .B \-P \fIflgs\fP
Print flags for fine control of the tag list ('print' action). Allows Print flags for fine control of the tag list ('print' action). Allows

@ -296,6 +296,8 @@ void Params::help(std::ostream& os) const
<< _(" x : XMP properties (-PXkyct)\n") << _(" x : XMP properties (-PXkyct)\n")
<< _(" c : JPEG comment\n") << _(" c : JPEG comment\n")
<< _(" p : list available previews\n") << _(" p : list available previews\n")
<< _(" S : print structure of image\n")
<< _(" X : extract XMP from image\n")
<< _(" -P flgs Print flags for fine control of tag lists ('print' action):\n") << _(" -P flgs Print flags for fine control of tag lists ('print' action):\n")
<< _(" E : include Exif tags in the list\n") << _(" E : include Exif tags in the list\n")
<< _(" I : IPTC datasets\n") << _(" I : IPTC datasets\n")
@ -555,8 +557,10 @@ int Params::evalPrint(const std::string& optarg)
case 'h': rc = evalPrintFlags("Exgnycsh"); break; case 'h': rc = evalPrintFlags("Exgnycsh"); break;
case 'i': rc = evalPrintFlags("Ikyct"); break; case 'i': rc = evalPrintFlags("Ikyct"); break;
case 'x': rc = evalPrintFlags("Xkyct"); break; case 'x': rc = evalPrintFlags("Xkyct"); break;
case 'c': action_ = Action::print; printMode_ = pmComment; break; case 'c': action_ = Action::print; printMode_ = pmComment ; break;
case 'p': action_ = Action::print; printMode_ = pmPreview; break; case 'p': action_ = Action::print; printMode_ = pmPreview ; break;
case 'S': action_ = Action::print; printMode_ = pmStructure; break;
case 'X': action_ = Action::print; printMode_ = pmXMP ; break;
default: default:
std::cerr << progname() << ": " << _("Unrecognized print mode") << " `" std::cerr << progname() << ": " << _("Unrecognized print mode") << " `"
<< optarg << "'\n"; << optarg << "'\n";

@ -144,7 +144,9 @@ public:
pmSummary, pmSummary,
pmList, pmList,
pmComment, pmComment,
pmPreview pmPreview,
pmStructure,
pmXMP
}; };
//! Individual items to print, bitmap //! Individual items to print, bitmap

@ -68,6 +68,8 @@ EXIV2_RCSID("@(#) $Id$")
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
#include <iostream>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifdef _MSC_VER #ifdef _MSC_VER
@ -160,7 +162,7 @@ namespace Exiv2 {
Image::~Image() Image::~Image()
{ {
} }
void Image::printStructure() void Image::printStructure(std::ostream&, printStructureOption_e)
{ {
} }

@ -507,7 +507,7 @@ namespace Exiv2 {
} }
} // JpegBase::readMetadata } // JpegBase::readMetadata
void JpegBase::printStructure() void JpegBase::printStructure(std::ostream& out,printStructureOption_e option)
{ {
if (io_->open() != 0) throw Error(9, io_->path(), strError()); if (io_->open() != 0) throw Error(9, io_->path(), strError());
// Ensure that this is the correct image type // Ensure that this is the correct image type
@ -516,6 +516,9 @@ namespace Exiv2 {
throw Error(15); throw Error(15);
} }
if ( option == kpsBasic || option == kpsXMP ) {
char sbuff[80];
// nemonic for markers // nemonic for markers
std::string nm[256] ; std::string nm[256] ;
nm[0xd8]="SOI" ; nm[0xd8]="SOI" ;
@ -547,11 +550,12 @@ namespace Exiv2 {
int marker = advanceToMarker(); int marker = advanceToMarker();
if (marker < 0) throw Error(15); if (marker < 0) throw Error(15);
printf("STRUCTURE OF FILE:\n"); if ( option == kpsBasic ) out << " offset | marker | length | signature" << std::endl ;
printf(" offset | marker | size | signature\n");
while (1) { while (1) {
// print marker bytes // print marker bytes
printf("%8ld %#02x %-5s",io_->tell(), marker,nm[marker].c_str()); sprintf(sbuff,"%8ld %#02x %-5s",io_->tell(), marker,nm[marker].c_str());
if ( option == kpsBasic ) out << sbuff;
if ( marker == eoi_ ) break ; if ( marker == eoi_ ) break ;
// Read size and signature // Read size and signature
@ -560,6 +564,7 @@ namespace Exiv2 {
if (io_->error()) throw Error(14); if (io_->error()) throw Error(14);
if (bufRead < 2) throw Error(15); if (bufRead < 2) throw Error(15);
uint16_t size = 0; uint16_t size = 0;
sbuff[0]=0;
// not all markers have size field. // not all markers have size field.
if( ( marker >= sof0_ && marker <= sof15_) if( ( marker >= sof0_ && marker <= sof15_)
@ -571,34 +576,55 @@ namespace Exiv2 {
|| marker == sos_ || marker == sos_
){ ){
size = getUShort(buf.pData_, bigEndian); size = getUShort(buf.pData_, bigEndian);
printf("%7d ", size); sprintf(sbuff,"%7d ", size);
} else { } else {
printf(" "); sprintf(sbuff," ");
} }
if ( option == kpsBasic ) out << sbuff ;
// only print the signature for appn // only print the signature for appn
if (marker >= app0_ && marker <= (app0_ | 0x0F)) { if (marker >= app0_ && marker <= (app0_ | 0x0F)) {
char http[5];
http[4]=0;
memcpy(http,buf.pData_+2,4);
if ( option == kpsXMP && strncmp(http,"http",4) == 0 ) {
// http://ns.adobe.com/xap/1.0/
if ( size > 0 ) {
io_->seek(-bufRead , BasicIo::cur);
byte* xmp = new byte[size+1];
io_->read(xmp,size);
int start = 0 ;
while (xmp[start]) start++; start++;
xmp[size]=0;
out << xmp + start << std::endl;
delete [] xmp;
bufRead = size;
}
} else if ( option == kpsBasic ) {
startSig = size>0?2:0; startSig = size>0?2:0;
int endSig = size?size:bufRead; int endSig = size?size:bufRead;
if (endSig > 32) endSig = 32 ; if (endSig > 32) endSig = 32 ;
while (startSig++ < endSig ) { while (startSig++ < endSig ) {
int c = buf.pData_[startSig-1] ; byte c = buf.pData_[startSig-1] ;
printf("%c", (' '<=c && c<128) ? c : '.' ); c = (' '<=c && c<128) ? c : '.' ;
out << (char) c ;
// else endSig = startSig; // else endSig = startSig;
} }
} }
}
// Skip the segment if the size is known // Skip the segment if the size is known
if (io_->seek(size - bufRead, BasicIo::cur)) throw Error(14); if (io_->seek(size - bufRead, BasicIo::cur)) throw Error(14);
printf("\n"); if ( option == kpsBasic ) out << std::endl;
// sos_ is immediately followed by entropy-coded data & eoi_ // sos_ is immediately followed by entropy-coded data & eoi_
if (marker == sos_) break; if (marker == sos_) break;
// Read the beginning of the next segment // Read the beginning of the next segment
marker = advanceToMarker(); marker = advanceToMarker();
} }
printf("-----------------\n"); }
} }
void JpegBase::writeMetadata() void JpegBase::writeMetadata()

@ -91,7 +91,7 @@ namespace Exiv2 {
return "image/png"; return "image/png";
} }
void PngImage::printStructure() void PngImage::printStructure(std::ostream& out,printStructureOption_e option)
{ {
if (io_->open() != 0) { if (io_->open() != 0) {
throw Error(9, io_->path(), strError()); throw Error(9, io_->path(), strError());
@ -103,12 +103,19 @@ namespace Exiv2 {
throw Error(3, "PNG"); throw Error(3, "PNG");
} }
printf("index | chunk_type | chunk_size\n"); char chType[5];
long index = 0, i = 0; chType[0]=0;
chType[4]=0;
if ( option == kpsBasic || option == kpsXMP ) {
if ( option == kpsBasic ) out << "index | chunk_type | length | data" << std::endl;
long index = 0;
const long imgSize = io_->size(); const long imgSize = io_->size();
DataBuf cheaderBuf(8); DataBuf cheaderBuf(8);
while(!io_->eof()) { while( !io_->eof() && ::strcmp(chType,"IEND") ) {
std::memset(cheaderBuf.pData_, 0x0, cheaderBuf.size_); std::memset(cheaderBuf.pData_, 0x0, cheaderBuf.size_);
long bufRead = io_->read(cheaderBuf.pData_, cheaderBuf.size_); long bufRead = io_->read(cheaderBuf.pData_, cheaderBuf.size_);
if (io_->error()) throw Error(14); if (io_->error()) throw Error(14);
@ -121,16 +128,50 @@ namespace Exiv2 {
|| dataOffset > uint32_t(0x7FFFFFFF) || dataOffset > uint32_t(0x7FFFFFFF)
|| static_cast<long>(dataOffset) > imgSize - pos) throw Exiv2::Error(14); || static_cast<long>(dataOffset) > imgSize - pos) throw Exiv2::Error(14);
printf("%5ld ", index); for (int i = 4; i < 8; i++) {
for (i = 4; i < 8; i++) chType[i-4]=cheaderBuf.pData_[i];
printf("%c", cheaderBuf.pData_[i]); }
printf(" %u\n", dataOffset);
byte buff[32];
size_t blen = sizeof(buff)-1;
buff [blen] = 0;
buff [ 0] = 0;
index++; size_t dOff = dataOffset;
io_->seek(dataOffset + 4 , BasicIo::cur);
if (io_->error() || io_->eof()) throw Error(14); if ( dataOffset > blen ) {
io_->read(buff,blen);
dataOffset -= blen ;
for ( size_t i = 0 ; i < blen ; i++ ) {
int c = buff[i] ;
buff[i] = (' '<=c && c<128) ? c : '.' ;
}
}
char sbuff[80];
sprintf(sbuff,"%5ld %12s %8lu %s\n", index++,chType,dOff,buff);
if ( option == kpsBasic ) out << sbuff;
// for XMP, back up and read the whole block
const char* key = "XML:com.adobe.xmp" ;
int start = ::strlen(key);
buff[start] = 0;
if ( option == kpsXMP && ::strcmp((const char*)buff,key) == 0 ) {
io_->seek(-blen , BasicIo::cur);
dataOffset = dOff ;
byte* xmp = new byte[dataOffset+5];
io_->read(xmp,dataOffset+4);
xmp[dataOffset]=0;
while ( xmp[start] == 0 ) start++;
out << xmp+start << std::endl;
delete [] xmp;
dataOffset = 0;
} }
if ( dataOffset ) io_->seek(dataOffset + 4 , BasicIo::cur);
if (io_->error()) throw Error(14);
}
}
} }
void PngImage::readMetadata() void PngImage::readMetadata()

Loading…
Cancel
Save