/* * This file is part of RawTherapee. * * Copyright (c) 2004-2010 Gabor Horvath * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ #ifndef _MEXIF3_ #define _MEXIF3_ #include #include #include #include #include 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}; struct TIFFHeader { unsigned short byteOrder; unsigned short fixed; unsigned int ifdOffset; }; class Tag; class Interpreter; // structure of informations describing an exif tag struct TagAttrib { int ignore; // =0: never ignore, =1: always ignore, =2: ignore if the subdir type is reduced image, =-1: end of table 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; const char* name; Interpreter* interpreter; }; // a directory of tags class TagDirectory { protected: std::vector tags; // tags in the directory const TagAttrib* attribs; // descriptor table to decode the tags ByteOrder order; // byte order TagDirectory* parent; // parent directory (NULL if root) public: TagDirectory (); TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border); TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border); ~TagDirectory (); inline ByteOrder getOrder () const { return order; } TagDirectory* getParent () { return parent; } 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); Tag* getTag (int ID); void addTag (Tag* a); void addTagFront (Tag* a); 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); void printAll () const; void sort (); }; // a class representing a single tag class Tag { protected: unsigned short tag; TagType type; unsigned int count; unsigned char* value; int valuesize; bool keep; const TagAttrib* attrib; TagDirectory* parent; TagDirectory** directory; MNKind makerNoteKind; 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, 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 initInt (int data, TagType t, int count=1); void initString (const char* text); void initSubDir (); void initMakerNote (MNKind mnk, const TagAttrib* ta); void initUndefArray (const char* data, int len); void initLongArray (const char* data, int len); void initRational (int num, int den); // get basic tag properties int getID () const { return tag; } int getCount () const { return count; } TagType getType () const { return type; } unsigned char* getValue () const { return value; } const TagAttrib* getAttrib () const { return attrib; } inline ByteOrder getOrder () const { return parent ? parent->getOrder() : INTEL; } inline TagDirectory* getParent () const { return parent; } int getValueSize () const { return valuesize; } // read/write value int toInt (int ofs=0, TagType astype=INVALID); void fromInt (int v); double toDouble (int ofs=0); void toRational (int& num, int& denom, int ofs=0); void toString (char* buffer, int ofs=0); void fromString (const char* v, int size=-1); void setInt (int v, int ofs=0, TagType astype=LONG); // additional getter/setter for more confortable use std::string valueToString (); std::string nameToString (int i=0); void valueFromString (const std::string& value); // functions for writing int calculateSize (); int write (int offs, int dataOffs, unsigned char* buffer); Tag* clone (TagDirectory* parent); // to control if the tag shall be written bool getKeep () { return keep; } void setKeep (bool k) { keep = k; } // get subdirectory (there can be several, the last is NULL) bool isDirectory () { return directory!=NULL; } TagDirectory* getDirectory (int i=0) { return directory[i]; } MNKind getMakerNoteFormat () { return makerNoteKind; } }; class ExifManager { static std::vector defTags; static Tag* saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name); public: static TagDirectory* parse (FILE*f, int base); static TagDirectory* parseJPEG (FILE*f); static TagDirectory* parseTIFF (FILE*f); static TagDirectory* parseCIFF (FILE* f, int base, int length); static void parseCIFF (FILE* f, int base, int length, TagDirectory* root); static const std::vector& getDefaultTIFFTags (TagDirectory* forthis); static int createJPEGMarker (const TagDirectory* root, const std::vector< std::pair >& changeList, int W, int H, unsigned char* buffer); static int createTIFFHeader (const TagDirectory* root, const std::vector< std::pair >& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char* buffer); }; class Interpreter { protected: char buffer[1024]; public: Interpreter () {} virtual std::string toString (Tag* t) { return ""; } virtual void fromString (Tag* t, const std::string& value) {} }; class StdInterpreter : public Interpreter { public: StdInterpreter () {} virtual std::string toString (Tag* t) { t->toString (buffer); std::string s(buffer); std::string::size_type p1 = s.find_first_not_of(' '); if( p1 == std::string::npos ) return s; else return s.substr(p1, s.find_last_not_of(' ')-p1+1); } virtual void fromString (Tag* t, const std::string& value) { if (t->getType()==SHORT || t->getType()==LONG) t->fromInt (atoi(value.c_str())); else t->fromString (value.c_str()); } }; extern StdInterpreter stdInterpreter; class ChoiceInterpreter : public Interpreter { protected: std::map choices; public: ChoiceInterpreter () {}; virtual std::string toString (Tag* t) { std::map::iterator r = choices.find (t->toInt()); if (r!=choices.end()) return r->second; else { t->toString (buffer); return std::string (buffer); } } }; 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); inline int get4 (FILE* f, ByteOrder order); inline void sset2 (unsigned short v, unsigned char *s, ByteOrder order); inline void sset4 (int v, unsigned char *s, ByteOrder order); inline float int_to_float (int i); inline short int int2_to_signed (short unsigned int i); bool extractLensInfo(std::string &fullname,double &minFocal, double &maxFocal, double &maxApertureAtMinFocal, double &maxApertureAtMaxFocal); extern const TagAttrib exifAttribs[]; extern const TagAttrib gpsAttribs[]; extern const TagAttrib iopAttribs[]; extern const TagAttrib ifdAttribs[]; extern const TagAttrib nikon2Attribs[]; extern const TagAttrib nikon3Attribs[]; extern const TagAttrib canonAttribs[]; extern const TagAttrib pentaxAttribs[]; extern const TagAttrib fujiAttribs[]; extern const TagAttrib minoltaAttribs[]; extern const TagAttrib sonyAttribs[]; extern const TagAttrib olympusAttribs[]; }; #endif