Pentax and Sony EXIF Tags decoding
New class TagDirectoryTable to support array of tags class Tag has a property allocOwnMemory to reference external memory (saved by parent directory) Pentax LensID support deconding of compatible lens with same number, by guessing. Exifpanel add array of tags as SYSTEM. Reordered stdattribs by tagID.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
310
rtexif/rtexif.cc
310
rtexif/rtexif.cc
@@ -99,6 +99,11 @@ void TagDirectory::sort () {
|
||||
for (int j=0; tags[i]->getDirectory(j); j++)
|
||||
tags[i]->getDirectory(j)->sort ();
|
||||
}
|
||||
TagDirectory* TagDirectory::getRoot()
|
||||
{
|
||||
if(parent) return parent->getRoot();
|
||||
else return this;
|
||||
}
|
||||
|
||||
const TagAttrib* TagDirectory::getAttrib (int id) {
|
||||
|
||||
@@ -185,6 +190,24 @@ Tag* TagDirectory::getTag (const char* name) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Tag* TagDirectory::findTag (const char* name) const {
|
||||
if (attribs) {
|
||||
for (int i=0; attribs[i].ignore!=-1; i++)
|
||||
if (!strcmp (attribs[i].name, name)){
|
||||
Tag* t= getTag (attribs[i].ID);
|
||||
if(t) return t;
|
||||
else break;
|
||||
}
|
||||
}
|
||||
for (int i=0; i<tags.size(); i++)
|
||||
if(tags[i]->isDirectory()){
|
||||
TagDirectory *dir = tags[i]->getDirectory();
|
||||
Tag* t=dir->findTag(name);
|
||||
if(t) return t;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int TagDirectory::calculateSize () {
|
||||
|
||||
int size = 2; // space to store the number of tags
|
||||
@@ -310,12 +333,63 @@ void TagDirectory::applyChange (std::string name, std::string value) {
|
||||
}
|
||||
}
|
||||
|
||||
TagDirectoryTable::TagDirectoryTable ()
|
||||
:valuesSize(0),zeroOffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
TagDirectoryTable::TagDirectoryTable (TagDirectory* p, unsigned char *v,int memsize,int offs, TagType type, const TagAttrib* ta, ByteOrder border)
|
||||
:TagDirectory(p,ta,border),valuesSize(memsize),zeroOffset(offs),defaultType( type )
|
||||
{
|
||||
values = new unsigned char[valuesSize];
|
||||
memcpy(values,v,valuesSize);
|
||||
for( const TagAttrib* tattr = ta; tattr->ignore != -1; tattr++){
|
||||
Tag* newTag = new Tag (this, tattr, (values + zeroOffset+ tattr->ID*getTypeSize(type)),type);
|
||||
tags.push_back(newTag); // Here we can insert more tag in the same offset because of bitfield meaning
|
||||
}
|
||||
}
|
||||
|
||||
TagDirectoryTable::TagDirectoryTable (TagDirectory* p, FILE* f, int memsize,int offs, TagType type, const TagAttrib* ta, ByteOrder border)
|
||||
:TagDirectory(p,ta,border),valuesSize(memsize),zeroOffset(offs),defaultType( type )
|
||||
{
|
||||
values = new unsigned char[valuesSize];
|
||||
fread (values, 1, valuesSize, f);
|
||||
|
||||
for( const TagAttrib* tattr = ta; tattr->ignore != -1; tattr++){
|
||||
Tag* newTag = new Tag (this, tattr, (values + zeroOffset+ tattr->ID*getTypeSize(type)),type);
|
||||
tags.push_back(newTag); // Here we can insert more tag in the same offset because of bitfield meaning
|
||||
}
|
||||
}
|
||||
TagDirectory* TagDirectoryTable::clone (TagDirectory* parent) {
|
||||
|
||||
TagDirectory* td = new TagDirectoryTable (parent,values,valuesSize,zeroOffset,defaultType, attribs, order);
|
||||
return td;
|
||||
}
|
||||
|
||||
TagDirectoryTable::~TagDirectoryTable()
|
||||
{
|
||||
if(values)
|
||||
delete [] values;
|
||||
}
|
||||
int TagDirectoryTable::calculateSize ()
|
||||
{
|
||||
return valuesSize;
|
||||
}
|
||||
|
||||
int TagDirectoryTable::write (int start, unsigned char* buffer) {
|
||||
if( values && valuesSize){
|
||||
memcpy(buffer+start,values,valuesSize);
|
||||
return start+valuesSize;
|
||||
}else
|
||||
return start;
|
||||
}
|
||||
|
||||
//--------------- class Tag ---------------------------------------------------
|
||||
// this class represents a tag stored in the directory
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Tag::Tag (TagDirectory* p, FILE* f, int base)
|
||||
: parent(p), value(NULL), directory(NULL), count(0), attrib(NULL), type(INVALID) {
|
||||
: parent(p), value(NULL), directory(NULL), count(0), attrib(NULL), type(INVALID),allocOwnMemory(true) {
|
||||
|
||||
tag = get2 (f, getOrder());
|
||||
type = (TagType)get2 (f, getOrder());
|
||||
@@ -334,7 +408,7 @@ Tag::Tag (TagDirectory* p, FILE* f, int base)
|
||||
int save = ftell(f) + 4;
|
||||
|
||||
// load value field (possibly seek before)
|
||||
valuesize = count * ("11124811248484"[type<14?type:0]-'0');
|
||||
valuesize = count * getTypeSize(type);
|
||||
|
||||
if (valuesize > 4)
|
||||
fseek (f, get4(f, getOrder()) + base, SEEK_SET);
|
||||
@@ -453,44 +527,103 @@ Tag::Tag (TagDirectory* p, FILE* f, int base)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (type==UNDEFINED && attrib && attrib->subdirAttribs) {
|
||||
count = 1;
|
||||
type = LONG;
|
||||
directory = new TagDirectory*[2];
|
||||
directory[0] = new TagDirectory (parent, f, base, attrib->subdirAttribs, getOrder());
|
||||
directory[1] = NULL;
|
||||
else if (attrib && attrib->subdirAttribs) {
|
||||
// Some subdirs are specific of maker and model
|
||||
char make[128], model[128];
|
||||
Tag* tmake = parent->getRoot()->getTag ("Make");
|
||||
if (tmake) tmake->toString (make);
|
||||
else make[0] = 0;
|
||||
Tag* tmodel = parent->getRoot()->getTag ("Model");
|
||||
if (tmodel) tmodel->toString (model);
|
||||
else model[0] = 0;
|
||||
|
||||
|
||||
if (!strncmp(make, "SONY", 4)) {
|
||||
switch( tag ){
|
||||
case 0x0114:
|
||||
{
|
||||
directory = new TagDirectory*[2];
|
||||
directory[1] = NULL;
|
||||
if( strstr(model, "A330") || strstr(model, "A380") )
|
||||
directory[0] = new TagDirectoryTable (parent, f, valuesize*2,0,SHORT , sonyCameraSettingsAttribs2, MOTOROLA);
|
||||
else
|
||||
directory[0] = new TagDirectoryTable (parent, f, valuesize*2,0,SHORT , sonyCameraSettingsAttribs, MOTOROLA);
|
||||
makerNoteKind = TABLESUBDIR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto defsubdirs;
|
||||
}
|
||||
}else if (!strncmp(make, "PENTAX", 6)) {
|
||||
switch( tag ){
|
||||
case 0x005c:
|
||||
case 0x0205:
|
||||
case 0x0206:
|
||||
case 0x0208:
|
||||
case 0x0216:
|
||||
directory = new TagDirectory*[2];
|
||||
directory[1] = NULL;
|
||||
directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , attrib->subdirAttribs, getOrder());
|
||||
makerNoteKind = TABLESUBDIR;
|
||||
break;
|
||||
case 0x0207:
|
||||
{ // There are 2 format pentaxLensDataAttribs
|
||||
int offsetFirst = 4;
|
||||
if( strstr(model, "*ist") || strstr(model, "GX-1") || strstr(model, "K100D") || strstr(model, "K110D") )
|
||||
offsetFirst = 3;
|
||||
directory = new TagDirectory*[2];
|
||||
directory[1] = NULL;
|
||||
directory[0] = new TagDirectoryTable (parent, f, valuesize,offsetFirst,BYTE , attrib->subdirAttribs, getOrder());
|
||||
makerNoteKind = TABLESUBDIR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto defsubdirs;
|
||||
}
|
||||
}else if(type==UNDEFINED){
|
||||
count = 1;
|
||||
type = LONG;
|
||||
directory[0] = new TagDirectory (parent, f, base, attrib->subdirAttribs, getOrder());
|
||||
}else
|
||||
goto defsubdirs;
|
||||
}
|
||||
else {
|
||||
// read value
|
||||
value = new unsigned char [valuesize];
|
||||
fread (value, 1, valuesize, f);
|
||||
|
||||
// if it is a subdirectory, load it (there may be several directories if count>1)
|
||||
if (attrib && attrib->subdirAttribs) {
|
||||
int pos = ftell (f);
|
||||
// count the number of valid subdirs
|
||||
int sdcount = count;
|
||||
if (sdcount>0) {
|
||||
if (parent->getAttribTable()==olympusAttribs)
|
||||
sdcount = 1;
|
||||
// allocate space
|
||||
directory = new TagDirectory*[sdcount+1];
|
||||
// load directories
|
||||
for (int j=0,i=0; j<count; j++,i++) {
|
||||
int newpos = base + toInt(j*4, LONG);
|
||||
fseek (f, newpos, SEEK_SET);
|
||||
directory[i] = new TagDirectory (parent, f, base, attrib->subdirAttribs, getOrder());
|
||||
fseek (f, pos, SEEK_SET);
|
||||
}
|
||||
// set the terminating NULL
|
||||
directory[sdcount] = NULL;
|
||||
}
|
||||
else
|
||||
type = INVALID;
|
||||
}
|
||||
}
|
||||
// seek back to the saved position
|
||||
fseek (f, save, SEEK_SET);
|
||||
return;
|
||||
defsubdirs:
|
||||
// read value
|
||||
value = new unsigned char [valuesize];
|
||||
fread (value, 1, valuesize, f);
|
||||
int pos = ftell (f);
|
||||
// count the number of valid subdirs
|
||||
int sdcount = count;
|
||||
if (sdcount>0) {
|
||||
if (parent->getAttribTable()==olympusAttribs)
|
||||
sdcount = 1;
|
||||
// allocate space
|
||||
directory = new TagDirectory*[sdcount+1];
|
||||
// load directories
|
||||
for (int j=0,i=0; j<count; j++,i++) {
|
||||
int newpos = base + toInt(j*4, LONG);
|
||||
fseek (f, newpos, SEEK_SET);
|
||||
directory[i] = new TagDirectory (parent, f, base, attrib->subdirAttribs, getOrder());
|
||||
fseek (f, pos, SEEK_SET);
|
||||
}
|
||||
// set the terminating NULL
|
||||
directory[sdcount] = NULL;
|
||||
}
|
||||
else
|
||||
type = INVALID;
|
||||
|
||||
// seek back to the saved position
|
||||
fseek (f, save, SEEK_SET);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
Tag* Tag::clone (TagDirectory* parent) {
|
||||
@@ -525,7 +658,7 @@ Tag* Tag::clone (TagDirectory* parent) {
|
||||
Tag::~Tag () {
|
||||
|
||||
// delete value
|
||||
if (value)
|
||||
if (value && allocOwnMemory)
|
||||
delete [] value;
|
||||
|
||||
// if there are directories behind the tag, delete them
|
||||
@@ -559,13 +692,15 @@ void Tag::fromInt (int v) {
|
||||
|
||||
void Tag::fromString (const char* v, int size) {
|
||||
|
||||
delete value;
|
||||
if( value && allocOwnMemory)
|
||||
delete [] value;
|
||||
if (size<0)
|
||||
valuesize = strlen (v) + 1;
|
||||
else
|
||||
valuesize = size;
|
||||
count = valuesize;
|
||||
value = new unsigned char [valuesize];
|
||||
if( allocOwnMemory )
|
||||
value = new unsigned char [valuesize];
|
||||
memcpy ((char*)value, v, valuesize);
|
||||
}
|
||||
|
||||
@@ -720,7 +855,6 @@ int Tag::calculateSize () {
|
||||
size += valuesize;
|
||||
else if (makerNoteKind==HEADERIFD)
|
||||
size += valuesize;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -770,6 +904,11 @@ int Tag::write (int offs, int dataOffs, unsigned char* buffer) {
|
||||
dataOffs += directory[0]->write (dataOffs, buffer);
|
||||
return dataOffs;
|
||||
}
|
||||
else if( makerNoteKind==TABLESUBDIR){
|
||||
sset4 (dataOffs, buffer+offs, parent->getOrder());
|
||||
dataOffs = directory[0]->write (dataOffs, buffer);
|
||||
return dataOffs;
|
||||
}
|
||||
else if (!directory[1]) {
|
||||
sset4 (dataOffs, buffer+offs, parent->getOrder());
|
||||
return directory[0]->write (dataOffs, buffer);
|
||||
@@ -790,21 +929,37 @@ int Tag::write (int offs, int dataOffs, unsigned char* buffer) {
|
||||
}
|
||||
|
||||
Tag::Tag (TagDirectory* p, const TagAttrib* attr)
|
||||
: parent(p), attrib(attr), makerNoteKind (NOMK), directory(NULL), keep(true), tag(attr ? attr->ID : -1), count(0), valuesize(0), value(NULL), type(INVALID) {
|
||||
: parent(p), attrib(attr), makerNoteKind (NOMK), directory(NULL), keep(true), tag(attr ? attr->ID : -1), count(0), valuesize(0), value(NULL), type(INVALID),allocOwnMemory(true) {
|
||||
}
|
||||
|
||||
Tag::Tag (TagDirectory* p, const TagAttrib* attr, int data, TagType t)
|
||||
: parent(p), attrib(attr), makerNoteKind (NOMK), directory(NULL), keep(true), tag(attr ? attr->ID : -1), count(1), valuesize(0), value(NULL), type(t) {
|
||||
: parent(p), attrib(attr), makerNoteKind (NOMK), directory(NULL), keep(true), tag(attr ? attr->ID : -1), count(1), valuesize(0), value(NULL), type(t),allocOwnMemory(true) {
|
||||
|
||||
initInt (data, t);
|
||||
}
|
||||
|
||||
Tag::Tag (TagDirectory* p, const TagAttrib* attr, unsigned char *data, TagType t)
|
||||
: parent(p), attrib(attr), makerNoteKind (NOMK), directory(NULL), keep(true), tag(attr ? attr->ID : -1), count(1), valuesize(0), value(NULL), type(t),allocOwnMemory(false) {
|
||||
|
||||
initType (data, t);
|
||||
}
|
||||
|
||||
Tag::Tag (TagDirectory* p, const TagAttrib* attr, const char* text)
|
||||
: parent(p), attrib(attr), makerNoteKind (NOMK), directory(NULL), keep(true), tag(attr ? attr->ID : -1), count(1), valuesize(0), value(NULL), type(ASCII) {
|
||||
: parent(p), attrib(attr), makerNoteKind (NOMK), directory(NULL), keep(true), tag(attr ? attr->ID : -1), count(1), valuesize(0), value(NULL), type(ASCII),allocOwnMemory(true) {
|
||||
|
||||
initString (text);
|
||||
}
|
||||
|
||||
void Tag::initType (unsigned char *data, TagType type)
|
||||
{
|
||||
valuesize = getTypeSize(type);
|
||||
if( allocOwnMemory ){
|
||||
value = new unsigned char[valuesize];
|
||||
memcpy ((char*)value, data, valuesize);
|
||||
}else
|
||||
value = data;
|
||||
}
|
||||
|
||||
void Tag::initInt (int data, TagType t, int cnt) {
|
||||
|
||||
type = t;
|
||||
@@ -1382,6 +1537,13 @@ short int int2_to_signed (short unsigned int i) {
|
||||
return u.s;
|
||||
}
|
||||
|
||||
int getTypeSize( TagType type ){
|
||||
return ("11124811248484"[type<14?type:0]-'0');
|
||||
}
|
||||
|
||||
#undef ABS
|
||||
#define ABS(a) (((a) < 0) ? -(a) : (a))
|
||||
|
||||
/* Function to parse and extract focal length and aperture information from description
|
||||
* @fullname must conform to the following formats
|
||||
* <focal>mm f/<aperture>
|
||||
@@ -1430,5 +1592,75 @@ bool extractLensInfo(std::string &fullname,double &minFocal, double &maxFocal, d
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::string IntLensInterpreter< T >::guess( const T lensID, double focalLength, double maxApertureAtFocal )
|
||||
{
|
||||
it_t r;
|
||||
size_t nFound = choices.count( lensID );
|
||||
|
||||
switch( nFound )
|
||||
{
|
||||
case 0: // lens Unknown
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << lensID;
|
||||
return s.str();
|
||||
}
|
||||
case 1: // lens found
|
||||
r = choices.find ( lensID );
|
||||
return r->second;
|
||||
default:
|
||||
// More than one hit: we must guess
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
double deltaMin = 1000.;
|
||||
|
||||
/* Choose the best match: thanks to exiftool by Phil Harvey
|
||||
* first throws for "out of focal range" and lower or upper aperture of the lens compared to MaxApertureAtFocal
|
||||
* if the lens is not constant aperture, calculate aprox. aperture of the lens at focalLength
|
||||
* and compare with actual aperture.
|
||||
*/
|
||||
std::string bestMatch("Unknown");
|
||||
std::ostringstream candidates;
|
||||
for ( r = choices.lower_bound( lensID ); r != choices.upper_bound(lensID); r++ ){
|
||||
double a1,a2,f1,f2,lensAperture,dif;
|
||||
|
||||
if( !extractLensInfo( r->second ,f1,f2,a1,a2) )
|
||||
continue;
|
||||
if( f1 == 0. || a1 == 0.)
|
||||
continue;
|
||||
|
||||
if( focalLength < f1 - .5 || focalLength > f2 + 0.5 )
|
||||
continue;
|
||||
if( maxApertureAtFocal > 0.1){
|
||||
if( maxApertureAtFocal < a1 - 0.15 || maxApertureAtFocal > a2 +0.15)
|
||||
continue;
|
||||
|
||||
if( a1 == a2 || f1 == f2)
|
||||
lensAperture = a1;
|
||||
else
|
||||
lensAperture = exp( log(a1)+(log(a2)-log(a1))/(log(f2)-log(f1))*(log(focalLength)-log(f1)) );
|
||||
|
||||
dif = ABS(lensAperture - maxApertureAtFocal);
|
||||
}else
|
||||
dif = 0;
|
||||
if( dif < deltaMin ){
|
||||
deltaMin = dif;
|
||||
bestMatch = r->second;
|
||||
}
|
||||
if( dif < 0.15){
|
||||
if( candidates.tellp() )
|
||||
candidates << "\n or " << r->second;
|
||||
else
|
||||
candidates << r->second;
|
||||
}
|
||||
|
||||
}
|
||||
if( !candidates.tellp() )
|
||||
return bestMatch;
|
||||
else
|
||||
return candidates.str();
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace rtexif {
|
||||
@@ -30,7 +31,7 @@ namespace rtexif {
|
||||
enum TagType {INVALID=0, BYTE=1, ASCII=2, SHORT=3, LONG=4, RATIONAL=5, UNDEFINED=7, SSHORT=8, SLONG=9, SRATIONAL=10, FLOAT=11, DOUBLE=12, OLYUNDEF=13, SUBDIR=99};
|
||||
enum ActionCode {DONTWRITE=0, WRITE=1, SYSTEM=2};
|
||||
enum ByteOrder {INTEL=0x4949, MOTOROLA=0x4D4D};
|
||||
enum MNKind {NOMK, IFD, HEADERIFD, NIKON3, OLYMPUS2, FUJI};
|
||||
enum MNKind {NOMK, IFD, HEADERIFD, NIKON3, OLYMPUS2, FUJI,TABLESUBDIR};
|
||||
|
||||
struct TIFFHeader {
|
||||
|
||||
@@ -48,7 +49,7 @@ struct TagAttrib {
|
||||
int action; //=0: dont write it to the output, =1: write it to the output, =2: dont write, dont show, =3: write, dont show
|
||||
int editable;
|
||||
const TagAttrib* subdirAttribs; // =0 ->not subdir
|
||||
unsigned short ID;
|
||||
unsigned short ID; // Numeric identifier of tag (or index inside DirectoryTable)
|
||||
const char* name;
|
||||
Interpreter* interpreter;
|
||||
};
|
||||
@@ -66,29 +67,48 @@ class TagDirectory {
|
||||
TagDirectory ();
|
||||
TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border);
|
||||
TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border);
|
||||
~TagDirectory ();
|
||||
virtual ~TagDirectory ();
|
||||
|
||||
inline ByteOrder getOrder () const { return order; }
|
||||
TagDirectory* getParent () { return parent; }
|
||||
TagDirectory* getRoot ();
|
||||
inline int getCount () const { return tags.size (); }
|
||||
const TagAttrib* getAttrib (int id);
|
||||
const TagAttrib* getAttrib (const char* name);
|
||||
const TagAttrib* getAttribTable() { return attribs; }
|
||||
Tag* getTag (const char* name) const;
|
||||
Tag* getTag (int ID) const;
|
||||
void addTag (Tag* a);
|
||||
void addTagFront (Tag* a);
|
||||
void replaceTag (Tag* a);
|
||||
virtual Tag* getTag (const char* name) const;
|
||||
virtual Tag* getTag (int ID) const;
|
||||
virtual Tag* findTag (const char* name) const;
|
||||
virtual void addTag (Tag* a);
|
||||
virtual void addTagFront (Tag* a);
|
||||
virtual void replaceTag (Tag* a);
|
||||
inline Tag* getTagByIndex (int ix) { return tags[ix]; }
|
||||
inline void setOrder (ByteOrder bo) { order = bo; }
|
||||
|
||||
int calculateSize ();
|
||||
int write (int start, unsigned char* buffer);
|
||||
TagDirectory* clone (TagDirectory* parent);
|
||||
void applyChange (std::string field, std::string value);
|
||||
virtual int calculateSize ();
|
||||
virtual int write (int start, unsigned char* buffer);
|
||||
virtual TagDirectory* clone (TagDirectory* parent);
|
||||
virtual void applyChange (std::string field, std::string value);
|
||||
|
||||
void printAll () const;
|
||||
void sort ();
|
||||
virtual void printAll () const;
|
||||
virtual void sort ();
|
||||
};
|
||||
|
||||
// a table of tags: id are offset from beginning and not identifiers
|
||||
class TagDirectoryTable: public TagDirectory {
|
||||
protected:
|
||||
unsigned char *values; // Tags values are saved internally here
|
||||
long zeroOffset; // Offset 0 (index 0) could be at an offset from values
|
||||
long valuesSize; // Size of allocated memory
|
||||
TagType defaultType; // Default type of all tags in this directory
|
||||
public:
|
||||
TagDirectoryTable();
|
||||
TagDirectoryTable (TagDirectory* p, unsigned char *v,int memsize,int offs, TagType type, const TagAttrib* ta, ByteOrder border);
|
||||
TagDirectoryTable (TagDirectory* p, FILE* f, int memsize,int offset, TagType type, const TagAttrib* ta, ByteOrder border);
|
||||
virtual ~TagDirectoryTable();
|
||||
virtual int calculateSize ();
|
||||
virtual int write (int start, unsigned char* buffer);
|
||||
virtual TagDirectory* clone (TagDirectory* parent);
|
||||
};
|
||||
|
||||
// a class representing a single tag
|
||||
@@ -101,6 +121,7 @@ class Tag {
|
||||
unsigned char* value;
|
||||
int valuesize;
|
||||
bool keep;
|
||||
bool allocOwnMemory;
|
||||
|
||||
const TagAttrib* attrib;
|
||||
TagDirectory* parent;
|
||||
@@ -110,9 +131,11 @@ class Tag {
|
||||
public:
|
||||
Tag (TagDirectory* parent, FILE* f, int base); // parse next tag from the file
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr);
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr, unsigned char *data, TagType t);
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr, int data, TagType t); // create a new tag from array (used
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr, const char* data); // create a new tag from array (used
|
||||
~Tag ();
|
||||
void initType (unsigned char *data, TagType type);
|
||||
void initInt (int data, TagType t, int count=1);
|
||||
void initString (const char* text);
|
||||
void initSubDir ();
|
||||
@@ -130,6 +153,7 @@ class Tag {
|
||||
inline ByteOrder getOrder () const { return parent ? parent->getOrder() : INTEL; }
|
||||
inline TagDirectory* getParent () const { return parent; }
|
||||
int getValueSize () const { return valuesize; }
|
||||
bool getOwnMemory() const { return allocOwnMemory; }
|
||||
|
||||
// read/write value
|
||||
int toInt (int ofs=0, TagType astype=INVALID);
|
||||
@@ -223,6 +247,20 @@ class ChoiceInterpreter : public Interpreter {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< class T >
|
||||
class IntLensInterpreter : public Interpreter {
|
||||
protected:
|
||||
typedef std::multimap< T, std::string> container_t;
|
||||
typedef typename std::multimap< T, std::string>::iterator it_t;
|
||||
typedef std::pair< T, std::string> p_t;
|
||||
container_t choices;
|
||||
|
||||
virtual std::string guess(const T lensID, double focalLength, double maxApertureAtFocal );
|
||||
};
|
||||
|
||||
template class IntLensInterpreter< int >;
|
||||
inline int getTypeSize( TagType type );
|
||||
inline unsigned short sget2 (unsigned char *s, ByteOrder order);
|
||||
inline int sget4 (unsigned char *s, ByteOrder order);
|
||||
inline unsigned short get2 (FILE* f, ByteOrder order);
|
||||
@@ -241,9 +279,17 @@ extern const TagAttrib nikon2Attribs[];
|
||||
extern const TagAttrib nikon3Attribs[];
|
||||
extern const TagAttrib canonAttribs[];
|
||||
extern const TagAttrib pentaxAttribs[];
|
||||
extern const TagAttrib pentaxLensDataAttribs[];
|
||||
extern const TagAttrib pentaxAEInfoAttribs[];
|
||||
extern const TagAttrib pentaxCameraSettingsAttribs[];
|
||||
extern const TagAttrib pentaxFlashInfoAttribs[];
|
||||
extern const TagAttrib pentaxSRInfoAttribs[];
|
||||
extern const TagAttrib pentaxBatteryInfoAttribs[];
|
||||
extern const TagAttrib fujiAttribs[];
|
||||
extern const TagAttrib minoltaAttribs[];
|
||||
extern const TagAttrib sonyAttribs[];
|
||||
extern const TagAttrib sonyCameraSettingsAttribs[];
|
||||
extern const TagAttrib sonyCameraSettingsAttribs2[];
|
||||
extern const TagAttrib olympusAttribs[];
|
||||
};
|
||||
#endif
|
||||
|
@@ -21,13 +21,9 @@
|
||||
|
||||
#include <rtexif.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <math.h>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#undef ABS
|
||||
#define ABS(a) (((a) < 0) ? -(a) : (a))
|
||||
|
||||
namespace rtexif {
|
||||
|
||||
@@ -41,6 +37,22 @@ class SAOnOffInterpreter : public ChoiceInterpreter {
|
||||
};
|
||||
SAOnOffInterpreter saOnOffInterpreter;
|
||||
|
||||
class SAWhiteBalanceInterpreter: public ChoiceInterpreter {
|
||||
public:
|
||||
SAWhiteBalanceInterpreter(){
|
||||
choices[ 0x0] = "Auto";
|
||||
choices[ 0x1] = "Color Temperature/Color Filter";
|
||||
choices[0x10] = "Daylight";
|
||||
choices[0x20] = "Cloudy";
|
||||
choices[0x30] = "Shade";
|
||||
choices[0x40] = "Tungsten";
|
||||
choices[0x50] = "Flash";
|
||||
choices[0x60] = "Fluorescent";
|
||||
choices[0x70] = "Custom";
|
||||
}
|
||||
};
|
||||
SAWhiteBalanceInterpreter saWhiteBalanceInterpreter;
|
||||
|
||||
class SASceneModeInterpreter : public ChoiceInterpreter {
|
||||
public:
|
||||
SASceneModeInterpreter () {
|
||||
@@ -144,11 +156,7 @@ class SAAntiBlurInterpreter : public ChoiceInterpreter {
|
||||
};
|
||||
SAAntiBlurInterpreter saAntiBlurInterpreter;
|
||||
|
||||
class SALensIDInterpreter : public Interpreter {
|
||||
typedef std::multimap<int, std::string> container_t;
|
||||
typedef std::pair<int,std::string> p_t;
|
||||
protected:
|
||||
container_t choices;
|
||||
class SALensIDInterpreter : public IntLensInterpreter< int > {
|
||||
public:
|
||||
SALensIDInterpreter () {
|
||||
choices.insert(p_t(0, "Minolta AF 28-85mm f/3.5-4.5"));
|
||||
@@ -457,71 +465,13 @@ class SALensIDInterpreter : public Interpreter {
|
||||
choices.insert(p_t(65535, "Helios 44-2 58mm f/2"));
|
||||
}
|
||||
|
||||
|
||||
virtual std::string toString (Tag* t)
|
||||
{
|
||||
int lensID = t->toInt();
|
||||
size_t nFound = choices.count( lensID );
|
||||
container_t::iterator r;
|
||||
switch( nFound )
|
||||
{
|
||||
case 0: // lens Unknown
|
||||
t->toString (buffer);
|
||||
return std::string (buffer);
|
||||
case 1: // lens found
|
||||
r = choices.find ( lensID );
|
||||
return r->second;
|
||||
default:
|
||||
// More than one hit: we must guess
|
||||
break;
|
||||
}
|
||||
|
||||
double maxApertureAtFocal = pow(2.0, t->getParent()->getParent()->getTag(0x9205)->toDouble()/2.0); // MaxApertureValue at focal Length
|
||||
double focalLength = t->getParent()->getParent()->getTag(0x920A)->toDouble(); // Focal Length
|
||||
double deltaMin = 1000.;
|
||||
|
||||
/* Choose the best match: thanks to exiftool by Phil Harvey
|
||||
* first throws for "out of focal range" and lower or upper aperture of the lens compared to MaxApertureAtFocal
|
||||
* if the lens is not constant aperture, calculate aprox. aperture of the lens at focalLength
|
||||
* and compare with actual aperture.
|
||||
*/
|
||||
std::string bestMatch("Unknown");
|
||||
std::ostringstream candidates;
|
||||
for ( r = choices.lower_bound( lensID ); r != choices.upper_bound(lensID); r++ ){
|
||||
double a1,a2,f1,f2,lensAperture,dif;
|
||||
|
||||
if( !extractLensInfo( r->second ,f1,f2,a1,a2) )
|
||||
continue;
|
||||
if( f1 == 0. || a1 == 0.)
|
||||
continue;
|
||||
|
||||
if( focalLength < f1 - .5 || focalLength > f2 + 0.5 )
|
||||
continue;
|
||||
if( maxApertureAtFocal < a1 - 0.15 || maxApertureAtFocal > a2 +0.15)
|
||||
continue;
|
||||
|
||||
if( a1 == a2 || f1 == f2)
|
||||
lensAperture = a1;
|
||||
else
|
||||
lensAperture = exp( log(a1)+(log(a2)-log(a1))/(log(f2)-log(f1))*(log(focalLength)-log(f1)) );
|
||||
|
||||
dif = ABS(lensAperture - maxApertureAtFocal);
|
||||
if( dif < deltaMin ){
|
||||
deltaMin = dif;
|
||||
bestMatch = r->second;
|
||||
}
|
||||
if( dif < 0.15){
|
||||
if( candidates.tellp() )
|
||||
candidates << "\n or " << r->second;
|
||||
else
|
||||
candidates << r->second;
|
||||
}
|
||||
}
|
||||
if( !candidates.tellp() )
|
||||
return bestMatch;
|
||||
else
|
||||
return candidates.str();
|
||||
}
|
||||
double maxApertureAtFocal = pow(2.0, t->getParent()->getParent()->getTag(0x9205)->toDouble()/2.0); // MaxApertureValue at focal Length
|
||||
double focalLength = t->getParent()->getParent()->getTag(0x920A)->toDouble(); // Focal Length
|
||||
return guess( lensID, focalLength, maxApertureAtFocal );
|
||||
}
|
||||
};
|
||||
SALensIDInterpreter saLensIDInterpreter;
|
||||
|
||||
@@ -566,6 +516,240 @@ class MAImageSizeInterpreter : public ChoiceInterpreter {
|
||||
};
|
||||
MAImageSizeInterpreter maImageSizeInterpreter;
|
||||
|
||||
class SAQualityInterpreter2 : public ChoiceInterpreter {
|
||||
public:
|
||||
SAQualityInterpreter2 () {
|
||||
choices[0] = "Raw";
|
||||
choices[2] = "cRAW";
|
||||
choices[16] = "Extra fine";
|
||||
choices[32] = "Fine";
|
||||
choices[34] = "RAW + JPEG";
|
||||
choices[35] = "cRAW + JPEG";
|
||||
choices[48] = "Standard";
|
||||
}
|
||||
};
|
||||
SAQualityInterpreter2 saQualityInterpreter2;
|
||||
|
||||
class SADriveMode : public ChoiceInterpreter {
|
||||
public:
|
||||
SADriveMode () {
|
||||
choices[0] = "Single Frame";
|
||||
choices[1] = "Continuous High";
|
||||
choices[4] = "Self-timer 10 sec";
|
||||
choices[5] = "Self-timer 2 sec";
|
||||
choices[7] = "Continuous Bracketing";
|
||||
choices[12] = "Continuous Low";
|
||||
choices[18] = "White Balance Bracketing Low";
|
||||
choices[19] = "D-Range Optimizer Bracketing Low";
|
||||
}
|
||||
};
|
||||
SADriveMode saDriveMode;
|
||||
|
||||
class SAFocusMode: public ChoiceInterpreter {
|
||||
public:
|
||||
SAFocusMode () {
|
||||
choices[0] = "Manual";
|
||||
choices[1] = "AF-S";
|
||||
choices[2] = "AF-C";
|
||||
choices[3] = "AF-A";
|
||||
choices[4] = "Permanent-AF";
|
||||
choices[65535] = "n/a";
|
||||
}
|
||||
};
|
||||
SAFocusMode saFocusMode;
|
||||
|
||||
class SAAFMode: public ChoiceInterpreter {
|
||||
public:
|
||||
SAAFMode(){
|
||||
choices[0] = "Default";
|
||||
choices[1] = "Multi AF";
|
||||
choices[2] = "Center AF";
|
||||
choices[3] = "Spot AF";
|
||||
choices[4] = "Flexible Spot AF";
|
||||
choices[6] = "Touch AF";
|
||||
choices[14] = "Manual Focus";
|
||||
choices[15] = "Face Detected";
|
||||
choices[65535] = "n/a";
|
||||
}
|
||||
};
|
||||
SAAFMode saAFMode;
|
||||
|
||||
class SAAFAreaMode: public ChoiceInterpreter {
|
||||
public:
|
||||
SAAFAreaMode () {
|
||||
choices[0] = "Wide";
|
||||
choices[1] = "Local";
|
||||
choices[2] = "Spot";
|
||||
}
|
||||
};
|
||||
SAAFAreaMode saAFAreaMode;
|
||||
|
||||
class SALocalAFAreaPoint: public ChoiceInterpreter {
|
||||
public:
|
||||
SALocalAFAreaPoint () {
|
||||
choices[1] = "Center";
|
||||
choices[2] = "Top";
|
||||
choices[3] = "Top-Right";
|
||||
choices[4] = "Right";
|
||||
choices[5] = "Bottom-Right";
|
||||
choices[6] = "Bottom";
|
||||
choices[7] = "Bottom-Left";
|
||||
choices[8] = "Left";
|
||||
choices[9] = "Top-Left";
|
||||
choices[10] = "Far Right";
|
||||
choices[11] = "Far Left";
|
||||
}
|
||||
};
|
||||
SALocalAFAreaPoint saLocalAFAreaPoint;
|
||||
|
||||
class SAMeteringMode: public ChoiceInterpreter {
|
||||
public:
|
||||
SAMeteringMode () {
|
||||
choices[1] = "Multi-segment";
|
||||
choices[2] = "Center-weighted Average";
|
||||
choices[4] = "Spot";
|
||||
}
|
||||
};
|
||||
SAMeteringMode saMeteringMode;
|
||||
|
||||
class SADynamicRangeOptimizerMode: public ChoiceInterpreter {
|
||||
public:
|
||||
SADynamicRangeOptimizerMode () {
|
||||
choices[0] = "Off";
|
||||
choices[1] = "Standard";
|
||||
choices[2] = "Advanced Auto";
|
||||
choices[3] = "Advanced Level";
|
||||
choices[4097] = "Auto";
|
||||
}
|
||||
};
|
||||
SADynamicRangeOptimizerMode saDynamicRangeOptimizerMode;
|
||||
|
||||
class SACreativeStyle: public ChoiceInterpreter {
|
||||
public:
|
||||
SACreativeStyle () {
|
||||
choices[1] = "Standard";
|
||||
choices[2] = "Vivid";
|
||||
choices[3] = "Portrait";
|
||||
choices[4] = "Landscape";
|
||||
choices[5] = "Sunset";
|
||||
choices[6] = "Night View/Portrait";
|
||||
choices[8] = "B&W";
|
||||
choices[9] = "Adobe RGB";
|
||||
choices[11] = "Neutral";
|
||||
choices[12] = "Clear";
|
||||
choices[13] = "Deep";
|
||||
choices[14] = "Light";
|
||||
choices[15] = "Autumn";
|
||||
choices[16] = "Sepia";
|
||||
}
|
||||
};
|
||||
SACreativeStyle saCreativeStyle;
|
||||
|
||||
class SAFlashMode: public ChoiceInterpreter {
|
||||
public:
|
||||
SAFlashMode () {
|
||||
choices[0] = "ADI";
|
||||
choices[1] = "TTL";
|
||||
}
|
||||
};
|
||||
SAFlashMode saFlashMode;
|
||||
|
||||
class SAExposureProgram: public ChoiceInterpreter {
|
||||
public:
|
||||
SAExposureProgram () {
|
||||
choices[0] = "Auto";
|
||||
choices[1] = "Manual";
|
||||
choices[2] = "Program AE";
|
||||
choices[3] = "Aperture-priority AE";
|
||||
choices[4] = "Shutter speed priority AE";
|
||||
choices[8] = "Program Shift A";
|
||||
choices[9] = "Program Shift S";
|
||||
choices[16] = "Portrait";
|
||||
choices[17] = "Sports";
|
||||
choices[18] = "Sunset";
|
||||
choices[19] = "Night Portrait";
|
||||
choices[20] = "Landscape";
|
||||
choices[21] = "Macro";
|
||||
choices[35] = "Auto No Flash";
|
||||
}
|
||||
};
|
||||
SAExposureProgram saExposureProgram;
|
||||
|
||||
class SARotation: public ChoiceInterpreter {
|
||||
public:
|
||||
SARotation () {
|
||||
choices[0] = "Horizontal";
|
||||
choices[1] = "Rotate 90 CW";
|
||||
choices[2] = "Rotate 270 CW";
|
||||
choices[3] = "None";
|
||||
}
|
||||
};
|
||||
SARotation saRotation;
|
||||
|
||||
class SASonyImageSize: public ChoiceInterpreter {
|
||||
public:
|
||||
SASonyImageSize () {
|
||||
choices[1] = "Large";
|
||||
choices[2] = "Medium ";
|
||||
choices[3] = "Small";
|
||||
}
|
||||
};
|
||||
SASonyImageSize saSonyImageSize;
|
||||
|
||||
class SAAspectRatio: public ChoiceInterpreter {
|
||||
public:
|
||||
SAAspectRatio () {
|
||||
choices[1] = "3:2";
|
||||
choices[2] = "16:9";
|
||||
}
|
||||
};
|
||||
SAAspectRatio saAspectRatio;
|
||||
|
||||
class SAExposureLevelIncrements: public ChoiceInterpreter {
|
||||
public:
|
||||
SAExposureLevelIncrements () {
|
||||
choices[33] = "1/3 EV";
|
||||
choices[50] = "1/2 EV";
|
||||
}
|
||||
};
|
||||
SAExposureLevelIncrements saExposureLevelIncrements;
|
||||
|
||||
class SAAFIlluminator: public ChoiceInterpreter {
|
||||
public:
|
||||
SAAFIlluminator () {
|
||||
choices[0] = "Off";
|
||||
choices[1] = "Auto";
|
||||
choices[65535]="n/a";
|
||||
}
|
||||
};
|
||||
SAAFIlluminator saAFIlluminator;
|
||||
|
||||
class SAReleaseModeInterpreter: public ChoiceInterpreter {
|
||||
public:
|
||||
SAReleaseModeInterpreter () {
|
||||
choices[0] = "Normal";
|
||||
choices[2] = "Burst";
|
||||
choices[5] = "Exposure Bracketing";
|
||||
choices[6] = "White Balance Bracketing";
|
||||
choices[65535]="n/a";
|
||||
}
|
||||
};
|
||||
SAReleaseModeInterpreter saReleaseModeInterpreter;
|
||||
|
||||
class SAImageStyleInterpreter: public ChoiceInterpreter {
|
||||
public:
|
||||
SAImageStyleInterpreter () {
|
||||
choices[1] = "Standard";
|
||||
choices[2] = "Vivid";
|
||||
choices[9] = "Adobe RGB";
|
||||
choices[11] = "Neutral";
|
||||
choices[129]="StyleBox1";
|
||||
choices[130]="StyleBox2";
|
||||
choices[131]="StyleBox3";
|
||||
}
|
||||
};
|
||||
SAImageStyleInterpreter saImageStyleInterpreter;
|
||||
|
||||
const TagAttrib minoltaAttribs[] = {
|
||||
0, 1, 0, 0, 0x0000, "MakerNoteVersion", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x0001, "MinoltaCameraSettingsOld", &stdInterpreter,
|
||||
@@ -593,8 +777,14 @@ const TagAttrib minoltaAttribs[] = {
|
||||
-1, 0, 0, 0, 0, "", NULL};
|
||||
|
||||
const TagAttrib sonyAttribs[] = {
|
||||
0, 1, 0, 0, 0x0102, "Quality", &maQualityInterpreter,
|
||||
0, 1, 0, 0, 0x0104, "FlashExposureComp",&stdInterpreter,
|
||||
0, 1, 0, 0, 0x0106, "TeleConverter", &maTeleconverterInterpreter,
|
||||
0, 1, 0, sonyCameraSettingsAttribs, 0x0114, "SonyCameraSettings",&stdInterpreter,
|
||||
0, 1, 0, 0, 0x0115, "WhiteBalance",&saWhiteBalanceInterpreter,
|
||||
1, 1, 0, 0, 0x0e00, "PrintIM", &stdInterpreter,
|
||||
1, 1, 0, 0, 0x2001, "PreviewImage", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x200a, "AutoHDR", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xb020, "ColorReproduction", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xb021, "ColorTemperature", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xb023, "SceneMode", &saSceneModeInterpreter,
|
||||
@@ -606,11 +796,66 @@ const TagAttrib sonyAttribs[] = {
|
||||
0, 1, 0, 0, 0xb029, "ColorMode", &saColorModeInterpreter,
|
||||
0, 1, 0, 0, 0xb040, "Macro", &saOnOffInterpreter,
|
||||
0, 1, 0, 0, 0xb041, "ExposureMode", &saExposureModeInterpreter,
|
||||
0, 1, 0, 0, 0xb042, "FocusMode", &saFocusMode,
|
||||
0, 1, 0, 0, 0xb043, "AFMode", &saAFMode,
|
||||
0, 1, 0, 0, 0xb044, "AFIlluminator", &saAFIlluminator,
|
||||
0, 1, 0, 0, 0xb047, "Quality", &saQualityInterpreter,
|
||||
0, 1, 0, 0, 0xb049, "ReleaseMode",&saReleaseModeInterpreter,
|
||||
0, 1, 0, 0, 0xb04b, "AntiBlur", &saAntiBlurInterpreter,
|
||||
0, 1, 0, 0, 0xb04e, "LongExposureNoiseReduction", &saOnOffInterpreter,
|
||||
-1, 0, 0, 0, 0, "", NULL};
|
||||
|
||||
const TagAttrib sonyCameraSettingsAttribs[]={
|
||||
0, 1, 0, 0, 4, "DriveMode", &saDriveMode,
|
||||
0, 1, 0, 0, 6, "WhiteBalanceFineTune",&stdInterpreter,
|
||||
0, 1, 0, 0, 16, "FocusMode",&saFocusMode,
|
||||
0, 1, 0, 0, 17, "AFAreaMode",&saAFAreaMode,
|
||||
0, 1, 0, 0, 18, "LocalAFAreaPoint", &saLocalAFAreaPoint,
|
||||
0, 1, 0, 0, 21, "MeteringMode",&saMeteringMode,
|
||||
0, 1, 0, 0, 22, "ISOSetting",&stdInterpreter,
|
||||
0, 1, 0, 0, 24, "DynamicRangeOptimizerMode", &saDynamicRangeOptimizerMode,
|
||||
0, 1, 0, 0, 25, "DynamicRangeOptimizerLevel",&stdInterpreter,
|
||||
0, 1, 0, 0, 26, "CreativeStyle",&saCreativeStyle,
|
||||
0, 1, 0, 0, 28, "Sharpness",&stdInterpreter,
|
||||
0, 1, 0, 0, 29, "Contrast",&stdInterpreter,
|
||||
0, 1, 0, 0, 30, "Saturation",&stdInterpreter,
|
||||
0, 1, 0, 0, 31, "ZoneMatchingValue",&stdInterpreter,
|
||||
0, 1, 0, 0, 34, "Brightness",&stdInterpreter,
|
||||
0, 1, 0, 0, 35, "FlashMode",&saFlashMode,
|
||||
0, 1, 0, 0, 40, "PrioritySetupShutterRelease",&stdInterpreter,
|
||||
0, 1, 0, 0, 41, "AFIlluminator",&saAFIlluminator,
|
||||
0, 1, 0, 0, 42, "AFWithShutter",&saOnOffInterpreter,
|
||||
0, 1, 0, 0, 43, "LongExposureNoiseReduction",&saOnOffInterpreter,
|
||||
0, 1, 0, 0, 44, "HighISONoiseReduction",&stdInterpreter,
|
||||
0, 1, 0, 0, 45, "ImageStyle",&saImageStyleInterpreter,
|
||||
0, 1, 0, 0, 60, "ExposureProgram",&saExposureProgram,
|
||||
0, 1, 0, 0, 61, "ImageStabilization",&saOnOffInterpreter,
|
||||
0, 1, 0, 0, 63, "Rotation",&saRotation,
|
||||
0, 1, 0, 0, 84, "SonyImageSize",&saSonyImageSize,
|
||||
0, 1, 0, 0, 85, "AspectRatio",&saAspectRatio,
|
||||
0, 1, 0, 0, 86, "Quality",&saQualityInterpreter2,
|
||||
0, 1, 0, 0, 88, "ExposureLevelIncrements",&saExposureLevelIncrements,
|
||||
-1, 0, 0, 0, 0, "", NULL};
|
||||
|
||||
const TagAttrib sonyCameraSettingsAttribs2[]={
|
||||
0, 1, 0, 0, 16, "FocusMode",&saFocusMode,
|
||||
0, 1, 0, 0, 17, "AFAreaMode",&saAFAreaMode,
|
||||
0, 1, 0, 0, 18, "LocalAFAreaPoint",&saLocalAFAreaPoint,
|
||||
0, 1, 0, 0, 19, "MeteringMode",&saMeteringMode,
|
||||
0, 1, 0, 0, 20, "ISOSetting",&stdInterpreter,
|
||||
0, 1, 0, 0, 22, "DynamicRangeOptimizerMode",&saDynamicRangeOptimizerMode,
|
||||
0, 1, 0, 0, 23, "DynamicRangeOptimizerLevel",&stdInterpreter,
|
||||
0, 1, 0, 0, 24, "CreativeStyle",&saCreativeStyle,
|
||||
0, 1, 0, 0, 25, "Sharpness",&stdInterpreter,
|
||||
0, 1, 0, 0, 26, "Contrast",&stdInterpreter,
|
||||
0, 1, 0, 0, 27, "Saturation",&stdInterpreter,
|
||||
0, 1, 0, 0, 35, "FlashMode",&saFlashMode,
|
||||
0, 1, 0, 0, 60, "ExposureProgram",&saExposureProgram,
|
||||
0, 1, 0, 0, 63, "Rotation",&saRotation,
|
||||
0, 1, 0, 0, 84, "SonyImageSize",&saSonyImageSize,
|
||||
-1, 0, 0, 0, 0, "", NULL};
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
@@ -32,6 +32,7 @@ class ColorSpaceInterpreter : public ChoiceInterpreter {
|
||||
public:
|
||||
ColorSpaceInterpreter () {
|
||||
choices[1] = "sRGB";
|
||||
choices[2] = "Adobe RGB";
|
||||
choices[0xffff] = "Uncalibrated";
|
||||
}
|
||||
};
|
||||
@@ -324,30 +325,64 @@ class UserCommentInterpreter : public Interpreter {
|
||||
};
|
||||
UserCommentInterpreter userCommentInterpreter;
|
||||
|
||||
class CFAInterpreter : public Interpreter {
|
||||
public:
|
||||
CFAInterpreter(){}
|
||||
virtual std::string toString (Tag* t) {
|
||||
char colors[]="RGB";
|
||||
for( int i=0; i< t->getCount();i++){
|
||||
unsigned char c = t->toInt(i,BYTE);
|
||||
buffer[i]= c<3 ?colors[c]:' ';
|
||||
}
|
||||
buffer[t->getCount()]=0;
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
CFAInterpreter cfaInterpreter;
|
||||
|
||||
class OrientationInterpreter : public ChoiceInterpreter {
|
||||
public:
|
||||
OrientationInterpreter (){
|
||||
choices[1] = "Horizontal (normal)";
|
||||
choices[2] = "Mirror horizontal ";
|
||||
choices[3] = "Rotate 180";
|
||||
choices[4] = "Mirror vertical";
|
||||
choices[5] = "Mirror horizontal and rotate 270 CW";
|
||||
choices[6] = "Rotate 90 CW";
|
||||
choices[7] = "Mirror horizontal and rotate 90 CW";
|
||||
choices[8] = "Rotate 270 CW";
|
||||
}
|
||||
};
|
||||
OrientationInterpreter orientationInterpreter;
|
||||
|
||||
class UnitsInterpreter : public ChoiceInterpreter {
|
||||
public:
|
||||
UnitsInterpreter(){
|
||||
choices[0] = "Unknown";
|
||||
choices[1] = "inches";
|
||||
choices[2] = "cm";
|
||||
}
|
||||
};
|
||||
UnitsInterpreter unitsInterpreter;
|
||||
|
||||
const TagAttrib exifAttribs[] = {
|
||||
0, 2, 0, 0, 0x0100, "ImageWidth", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0101, "ImageHeight", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0102, "BitsPerSample", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0103, "Compression", &compressionInterpreter,
|
||||
0, 2, 0, 0, 0xA000, "FlashpixVersion", &stdInterpreter,
|
||||
0, 2, 0, 0, 0xA001, "ColorSpace", &colorSpaceInterpreter,
|
||||
0, 1, 0, 0, 0x9000, "ExifVersion", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9003, "DateTimeOriginal", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9004, "DateTimeDigitized", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x9101, "ComponentsConfiguration", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x9102, "CompressedBitsPerPixel", &stdInterpreter,
|
||||
0, 2, 0, 0, 0xA002, "PixelXDimension", &stdInterpreter,
|
||||
0, 2, 0, 0, 0xA003, "PixelYDimension", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x927C, "MakerNote", &stdInterpreter,
|
||||
0, 1, 1, 0, 0x9286, "UserComment", &userCommentInterpreter,
|
||||
1, 0, 0, 0, 0xA004, "RelatedSoundFile", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9290, "SubSecTime", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9291, "SubSecTimeOriginal", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9292, "SubSecTimeDigitized", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xA420, "ImageUniqueID", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x828d, "CFAPatternDim", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x828e, "CFAPattern", &cfaInterpreter,
|
||||
0, 1, 0, 0, 0x829A, "ExposureTime", &exposureTimeInterpreter,
|
||||
0, 1, 0, 0, 0x829D, "FNumber", &fNumberInterpreter,
|
||||
0, 1, 0, 0, 0x8822, "ExposureProgram", &exposureProgramInterpreter,
|
||||
0, 1, 0, 0, 0x8824, "SpectralSensitivity", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x8827, "ISOSpeedRatings", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x8828, "OECF", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9000, "ExifVersion", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9003, "DateTimeOriginal", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9004, "DateTimeDigitized", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x9101, "ComponentsConfiguration", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x9102, "CompressedBitsPerPixel", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9201, "ShutterSpeedValue", &shutterSpeedInterpreter,
|
||||
0, 1, 0, 0, 0x9202, "ApertureValue", &apertureInterpreter,
|
||||
0, 1, 0, 0, 0x9203, "BrightnessValue", &stdInterpreter,
|
||||
@@ -361,6 +396,17 @@ const TagAttrib exifAttribs[] = {
|
||||
0, 1, 0, 0, 0x9214, "SubjectArea", &stdInterpreter,
|
||||
0, 0, 0, 0, 0x9216, "TIFFEPSStandardID", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9217, "SensingMethod", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x927C, "MakerNote", &stdInterpreter,
|
||||
0, 1, 1, 0, 0x9286, "UserComment", &userCommentInterpreter,
|
||||
0, 1, 0, 0, 0x9290, "SubSecTime", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9291, "SubSecTimeOriginal", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9292, "SubSecTimeDigitized", &stdInterpreter,
|
||||
0, 2, 0, 0, 0xA000, "FlashpixVersion", &stdInterpreter,
|
||||
0, 0, 0, 0, 0xA001, "ColorSpace", &colorSpaceInterpreter,
|
||||
0, 2, 0, 0, 0xA002, "PixelXDimension", &stdInterpreter,
|
||||
0, 2, 0, 0, 0xA003, "PixelYDimension", &stdInterpreter,
|
||||
1, 0, 0, 0, 0xA004, "RelatedSoundFile", &stdInterpreter,
|
||||
0, 1, 0, iopAttribs, 0xA005, "Interoperability", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xA20B, "FlashEnergy", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xA20C, "SpatialFrequencyResponse", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xA20E, "FocalPlaneXResolution", &stdInterpreter,
|
||||
@@ -371,7 +417,7 @@ const TagAttrib exifAttribs[] = {
|
||||
0, 1, 0, 0, 0xA217, "SensingMethod", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xA300, "FileSource", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xA301, "SceneType", &stdInterpreter,
|
||||
0, 0, 0, 0, 0xA302, "CFAPattern", &stdInterpreter,
|
||||
0, 0, 0, 0, 0xA302, "CFAPattern", &cfaInterpreter,
|
||||
0, 1, 0, 0, 0xA401, "CustomRendered", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xA402, "ExposureMode", &exposureModeInterpreter,
|
||||
0, 1, 0, 0, 0xA403, "WhiteBalance", &whiteBalanceInterpreter,
|
||||
@@ -384,10 +430,9 @@ const TagAttrib exifAttribs[] = {
|
||||
0, 1, 0, 0, 0xA40A, "Sharpness", &sharpnessInterpreter,
|
||||
0, 1, 0, 0, 0xA40B, "DeviceSettingDescription", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xA40C, "SubjectDistanceRange", &stdInterpreter,
|
||||
0, 0, 0, 0, 0x828d, "CFAPattern", &stdInterpreter,
|
||||
0, 0, 0, 0, 0x828e, "CFARepeatPatternDim", &stdInterpreter,
|
||||
0, 1, 0, 0, 0xA420, "ImageUniqueID", &stdInterpreter,
|
||||
-1, 0, 0, 0, 0, "", NULL };
|
||||
// 0, 0xA005, LONG, 1, "Interoperability tag", "Interoperability IFD Pointer"};
|
||||
|
||||
|
||||
const TagAttrib gpsAttribs[] = {
|
||||
0, 1, 0, 0, 0x0000, "GPSVersionID", &stdInterpreter,
|
||||
@@ -423,8 +468,6 @@ const TagAttrib gpsAttribs[] = {
|
||||
0, 1, 0, 0, 0x001e, "GPSDifferential", &stdInterpreter,
|
||||
-1, 0, 0, 0, 0, "", NULL };
|
||||
|
||||
|
||||
|
||||
const TagAttrib iopAttribs[] = {
|
||||
0, 1, 0, 0, 0x0001, "InteroperabilityIndex", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x0002, "InteroperabilityVersion", &stdInterpreter,
|
||||
@@ -437,30 +480,35 @@ const TagAttrib iopAttribs[] = {
|
||||
0, 2, 0, 0, 0x0102, "BitsPerSample", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0103, "Compression", &compressionInterpreter,
|
||||
0, 2, 0, 0, 0x0106, "PhotometricInterpretation", &photometricInterpreter,
|
||||
0, 2, 0, 0, 0x0112, "Orientation", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0115, "SamplesPerPixel", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x011C, "PlanarConfiguration", &planarConfigInterpreter,
|
||||
0, 2, 0, 0, 0x0212, "YCbCrSubSampling", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0213, "YCbCrPositioning", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x011A, "XResolution", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x011B, "YResolution", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0128, "ResolutionUnit", &stdInterpreter,
|
||||
1, 0, 0, 0, 0x0111, "StripOffsets", &stdInterpreter,
|
||||
1, 0, 0, 0, 0x0116, "RowsPerStrip", &stdInterpreter,
|
||||
1, 0, 0, 0, 0x0117, "StripByteCounts", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0201, "JPEGInterchangeFormat", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0202, "JPEGInterchangeFormatLength", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x012D, "TransferFunction", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x013E, "WhitePoint", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x013F, "PriomaryChromaticities", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0211, "YCbCrCoefficients", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0214, "ReferenceBlackWhite", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x0132, "DateTime", &stdInterpreter,
|
||||
0, 1, 1, 0, 0x010E, "ImageDescription", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x010F, "Make", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x0110, "Model", &stdInterpreter,
|
||||
1, 0, 0, 0, 0x0111, "StripOffsets", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0112, "Orientation", &orientationInterpreter,
|
||||
0, 2, 0, 0, 0x0115, "SamplesPerPixel", &stdInterpreter,
|
||||
1, 0, 0, 0, 0x0116, "RowsPerStrip", &stdInterpreter,
|
||||
1, 0, 0, 0, 0x0117, "StripByteCounts", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x011A, "XResolution", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x011B, "YResolution", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x011C, "PlanarConfiguration", &planarConfigInterpreter,
|
||||
0, 2, 0, 0, 0x0128, "ResolutionUnit", &unitsInterpreter,
|
||||
0, 2, 0, 0, 0x012D, "TransferFunction", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0131, "Software", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x0132, "DateTime", &stdInterpreter,
|
||||
0, 1, 1, 0, 0x013B, "Artist", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x013E, "WhitePoint", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x013F, "PriomaryChromaticities", &stdInterpreter,
|
||||
0, 1, 0, ifdAttribs, 0x014A, "SubIFD", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0201, "JPEGInterchangeFormat", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0202, "JPEGInterchangeFormatLength", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0211, "YCbCrCoefficients", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0212, "YCbCrSubSampling", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0213, "YCbCrPositioning", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x0214, "ReferenceBlackWhite", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x4746, "Rating",&stdInterpreter,
|
||||
0, 1, 0, 0, 0x4749, "RatingPercent",&stdInterpreter,
|
||||
0, 1, 0, 0, 0x828d, "CFAPatternDim", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x828e, "CFAPattern", &cfaInterpreter,
|
||||
0, 1, 1, 0, 0x8298, "Copyright", &stdInterpreter,
|
||||
0, 1, 0, exifAttribs, 0x8769, "Exif", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x8773, "ICCProfile", &stdInterpreter,
|
||||
@@ -469,7 +517,6 @@ const TagAttrib iopAttribs[] = {
|
||||
0, 1, 0, 0, 0x9003, "DateTimeOriginal", &stdInterpreter,
|
||||
0, 1, 0, 0, 0x9004, "DateTimeDigitized", &stdInterpreter,
|
||||
0, 1, 0, iopAttribs, 0xA005, "Interoperability", &stdInterpreter,
|
||||
1, 2, 0, ifdAttribs, 0x014A, "SubIFD", &stdInterpreter,
|
||||
0, 0, 0, 0, 0xC4A5, "PrintIMInformation", &stdInterpreter,
|
||||
0, 2, 0, 0, 0x00fe, "NewSubFileType", &stdInterpreter,
|
||||
-1, 0, 0, 0, 0, "", NULL};
|
||||
|
@@ -205,7 +205,7 @@ void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children
|
||||
addDirectory (t->getDirectory(j), ch);
|
||||
}
|
||||
else
|
||||
addTag (root, t->nameToString (), t->valueToString (), t->getAttrib() ? t->getAttrib()->action : 0, t->getAttrib() && t->getAttrib()->editable);
|
||||
addTag (root, t->nameToString (), t->valueToString (), t->getAttrib() ? (t->getOwnMemory()?t->getAttrib()->action:SYSTEM) : 0, t->getAttrib() && t->getAttrib()->editable);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user