/* /-------------------------------------------------------------------- | | $Id: plexif.h,v 1.5 2004/06/06 12:56:38 uzadow Exp $ | | Copyright (c) 1996-2003 Ulrich von Zadow | | Implementation of PLExif class by Mike Franklin | Much of the decoding code was adapted from code by Ken Reneris: | http://www.reneris.com/tools/exif.asp - | though it has been heavily modified! | | \-------------------------------------------------------------------- */ #ifndef INCL_PLEXIF #define INCL_PLEXIF #ifdef _MSC_VER // The microsoft compiler generates masses // of symbol too long #pragma warning(disable: 4786) // for debugger warnings for sets and maps #endif #include "plpaintlibdefs.h" #include "plcountedpointer.h" #include #include #include #include struct jpeg_decompress_struct; struct jpeg_compress_struct; // these structures are for internal use only struct _PLExifTranslator; struct _PLExifTagValues; struct _PLExifFormatter; class PLExifTag; typedef PLCountedPointer PLExifTagCPtr; // PLExifTag counted pointer typedef std::vector PLExifTagList; // vector of PLExifTag counted pointers typedef PLCountedArrayPointer PLByteCPtr; // utility typedef class PLExif { public: PLExif(); ~PLExif(); // default copying is safe // reset the internal data void Clear(); // Access the raw EXIF data (just a copy of the EXIF header held in memory) size_t GetRawDataSize() const; PLBYTE * GetRawData(); const PLBYTE * GetRawData() const; /* // These are not EXIF comments and should probably be moved to PLBmpInfo const std::string & GetComment() const; const char * GetCommmentCStr() const; void SetComment(const std::string &); void SetComment(const char *); */ // Access to the Main, Sub and Manufacturer tags // also a single list that contains them all const PLExifTagList & GetAllTags() const; const PLExifTagList & GetMainTags() const; const PLExifTagList & GetSubTags() const; const PLExifTagList & GetManufacturerTags() const; // As above but returning a traditional C style array pointer // instead of an STL vector // It is an array of pointers to PLExifTag const PLExifTagCPtr * GetAllTagsC(size_t & size) const; const PLExifTagCPtr * GetMainTagsC(size_t & size) const; const PLExifTagCPtr * GetSubTagsC(size_t & size) const; const PLExifTagCPtr * GetManufacturerTagsC(size_t & size) const; // All the following functions give access to a tag given a tag shortname // they almost all return a pointer to the whole tag but mostly this // will just be used to check whether the tag was found by testing for // a NULL pointer. The useful data - the tag value is generally returned // by reference. // // duplicate copies of the functions allow efficient use whether // the source tag string is a std::string or a char * // All forms return a pointer to the found tag, 0 if not found // Just return the tag pointer PLExifTag * GetTag(const char * TagShortName) const; PLExifTag * GetTag(const std::string & TagShortName) const { return GetTag(TagShortName.c_str()); } // place the tag value into the Value string, format is basic // as stored in the raw EXIF data eg f4.0 is likely to be 40/10 PLExifTag * GetTag(const char * TagShortName, std::string & Value) const; PLExifTag * GetTag(const std::string & TagShortName, std::string & Value) const { return GetTag(TagShortName.c_str(), Value); } // place the tag value in the Value string, format is common form // eg f4.0 is 4.0 rather than 40/10 PLExifTag * GetTagCommon(const char * TagShortName, std::string & Value) const; PLExifTag * GetTagCommon(const std::string & TagShortName, std::string & Value) const { return GetTagCommon(TagShortName.c_str(), Value); } // place the tag value in the Value double where appropriate // eg 1.234m focus PLExifTag * GetTag(const char * TagShortName, double & Value) const; PLExifTag * GetTag(const std::string & TagShortName, double & Value) const { return GetTag(TagShortName.c_str(), Value); } // return tag value as a string (empty string if not found), format is basic // as stored in the raw EXIF data eg f4.0 is likely to be 40/10 std::string & TagStr(const char * TagShortName) const; std::string & TagStr(const std::string & TagShortName) const { return TagStr(TagShortName.c_str()); } // return tag value as a string (empty string if not found) // format is common form eg f4.0 is 4.0 rather than 40/10 std::string & TagStrCommon(const char * TagShortName) const; std::string & TagStrCommon(const std::string & TagShortName) const { return TagStrCommon(TagShortName.c_str()); } // C string return versions of TagStr and TagStrCommon // return tag value as a string (empty string if not found), format is basic // as stored in the raw EXIF data eg f4.0 is likely to be 40/10 const char * TagCStr(const char * TagShortName) const; const char * TagCStr(const std::string & TagShortName) const { return TagCStr(TagShortName.c_str()); } // return tag value as a string (empty string if not found) // format is common form eg f4.0 is 4.0 rather than 40/10 const char * TagCStrCommon(const char * TagShortName) const; const char * TagCStrCommon(const std::string & TagShortName) const { return TagCStrCommon(TagShortName.c_str()); } // These two methods are primarily intended for use only by the Paintlib encoders and decoders // load data from cinfo - jpeg_save_markers must have been called first void ReadData(const jpeg_decompress_struct * pcinfo); // write data to cinfo - after jpeg_start_compress void WriteData(jpeg_compress_struct * pcinfo); private: void decode(); // do the actual decoding of the EXIF data void ReadIFD(const _PLExifTagValues * Tags, char * Prefix, PLExifTagList & sectionList); void ExpandBinaryTag(const std::string & Src, const _PLExifTagValues *Tags, PLUINT Type, PLExifTagList & sectionList); void DecodeCanCustomFncs(const PLExifTag & rootTag, const _PLExifTagValues *Tags, PLExifTagList & sectionList); void CopyTag(const char * Src, const char * Dst); void SetTag(const char * Dst, const char * Value); void SetTag(const char * Dst, const std::string & Value) { SetTag(Dst, Value.c_str()); } void AddTag(const char * Dst, const char * SrcTag, const char * Skip = NULL, const char * Sep = NULL); void AddStr(const char * Dst, const std::string & SrcStr, const char * Skip = NULL, const char * Sep = NULL); void FormatRange(double Low, double High, std::string & Str); // these functions were originally designed to read from a file // they have been kept but are now "reading" from the vector m_Data // I may remove at least the first couple later void SetPos(size_t Pos); size_t GetPos(); PLWORD GetU16(); PLLONG GetU32(); void Read(void * Buffer, size_t Size); private: PLByteCPtr m_Data; size_t m_DataSize; // this should probably be moved to PLBmpInfo // std::string m_Comment; // include comments even though they're not really EXIF size_t m_Pos; // offset into data (effectively index into m_Data size_t m_IdfOffset; bool m_Endian; PLExifTagList m_AllTags; // Tags in the order found PLExifTagList m_MainTags; PLExifTagList m_SubTags; PLExifTagList m_ManufacturerTags; typedef std::map TagMap; TagMap m_Tags; // tag look up for searching by short name }; class PLExifTag { public: // default copying is safe ~PLExifTag(); // C Interface - returning const char * const char * GetShortNameCStr() const; const char * GetDescriptionCStr() const; // Format is basic as stored in the raw EXIF data // eg f4.0 is likely to be 40/10 const char * GetValueCStr() const; // format is common form eg f4.0 is 4.0 rather than 40/10 const char * GetValueCommonCStr() const; // STL Interface - returning const string & const std::string & GetShortName() const; const std::string GetDescription() const; // Format is basic as stored in the raw EXIF data // eg f4.0 is likely to be 40/10 const std::string & GetValue() const; // format is common form eg f4.0 is 4.0 rather than 40/10 const std::string & GetValueCommon() const; private: // render functions to convert from raw memory data size_t RenDef(PLBYTE * & Buffer); size_t RenUDef(PLBYTE * & Buffer); size_t RenUndef(PLBYTE * & Buffer); size_t RenStr(PLBYTE * & Buffer); size_t RenURat(PLBYTE * & Buffer); size_t RenRat(PLBYTE * & Buffer); // conversion to common values void CnvRat(std::string & result); // evaluate nominator/denominator void CnvRatAp(std::string & result); // evaluate nominator/denominator for fstop void CnvFrac(std::string & result); // evaluate nominator/denominator if > than 1 void CnvApexShutter(std::string & result); void CnvApexAp(std::string & result); void CnvCompCfg(std::string & result); // component configuration void CnvCanINo(std::string & result); // decode canon image no void CnvCanSNo(std::string & result); // decode canon serial no void CnvCanFlash(std::string & result); // canon flash details void CnvCanAFPnt(std::string & result); // canon AF focus point used // friends to let them have access to the conversion and rendering // functions without having to make them public to the whole world friend struct _PLExifTagValues; friend struct _PLExifFormatter; private: PLExifTag(PLUINT TagNo, PLUINT Format, PLUINT NoComp); // only ever created by friend PLExif void CleanWorkingArea(); // call after all decoding done to free mem buffer void Swizzle(); void Render(); void DoTranslation(); void Value(size_t Index); double GetDouble(size_t Index); const _PLExifTagValues * m_Tag; // The tag for this item - pointer to static data so copy safe const _PLExifFormatter * m_Fmt; // The format type - pointer to static data so copy safe std::string m_ShortName; // Copy of the short name std::string m_Lookup; // Lowercase version of shortname size_t m_TagNo; // The tag no size_t m_Format; // Format of this item size_t m_NoComp; // Number of components size_t m_Size; // Total size of item PLByteCPtr m_Buffer; // Copy of the item's data size_t m_Pos; // Location of tag // The rendered value std::string m_Value; // In printable form std::string m_Common; // in printable common form PLLONG m_Num; // Numerator PLLONG m_Den; // Denominator PLLONG m_Int; // As int PLUINT m_UInt; // As unsigned int double m_Double; // As double private: // not too thrilled with this but I inherited it! // however it does avoid having to put stuff into // the public interface that only PLExif will need // and will not be needed by the library clients friend class PLExif; private: // these need to be static members to have access to conversion and render functions static _PLExifTagValues MainTags[]; static _PLExifTagValues SubTags[]; static _PLExifTagValues NikonTags[]; static _PLExifTagValues Nikon2Tags[]; static _PLExifTagValues OlympusTags[]; static _PLExifTagValues CanonTags[]; static _PLExifTagValues CanonSet1[]; static _PLExifTagValues CanonSet2[]; static _PLExifTagValues CanonCFn[]; static _PLExifTagValues FujifilmTags[]; static _PLExifTagValues CasioTags[]; static _PLExifFormatter rgExifFormat[]; }; #endif