ifdentry.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _OPENRAW_INTERNALS_IFDENTRY_H
00023 #define _OPENRAW_INTERNALS_IFDENTRY_H
00024
00025 #include <vector>
00026 #include <boost/shared_ptr.hpp>
00027 #include <libopenraw/types.h>
00028
00029 #include "exception.h"
00030 #include "endianutils.h"
00031 #include "rawcontainer.h"
00032 #include "ifd.h"
00033
00034 namespace OpenRaw {
00035 namespace Internals {
00036
00037 class IFDFileContainer;
00038
00039 class IFDEntry;
00040
00042 template <typename T>
00043 struct IFDTypeTrait
00044 {
00045 static const uint16_t type;
00046 static const size_t size;
00047 static T EL(const uint8_t* d);
00048 static T BE(const uint8_t* d);
00049 static T get(IFDEntry & e, uint32_t idx = 0, bool ignore_type = false)
00050 throw (BadTypeException, OutOfRangeException, TooBigException);
00051 };
00052
00053
00054 template <>
00055 inline uint8_t IFDTypeTrait<uint8_t>::EL(const uint8_t* b)
00056 {
00057 return *b;
00058 }
00059
00060 template <>
00061 inline uint8_t IFDTypeTrait<uint8_t>::BE(const uint8_t* b)
00062 {
00063 return *b;
00064 }
00065
00066
00067 template <>
00068 inline uint16_t IFDTypeTrait<uint16_t>::EL(const uint8_t* b)
00069 {
00070 return EL16(b);
00071 }
00072
00073 template <>
00074 inline uint16_t IFDTypeTrait<uint16_t>::BE(const uint8_t* b)
00075 {
00076 return BE16(b);
00077 }
00078
00079 template <>
00080 inline uint32_t IFDTypeTrait<uint32_t>::EL(const uint8_t* b)
00081 {
00082 return EL32(b);
00083 }
00084
00085 template <>
00086 inline uint32_t IFDTypeTrait<uint32_t>::BE(const uint8_t* b)
00087 {
00088 return BE32(b);
00089 }
00090
00091 template <>
00092 inline std::string IFDTypeTrait<std::string>::EL(const uint8_t* b)
00093 {
00094 return std::string((const char*)b);
00095 }
00096
00097 template <>
00098 inline std::string IFDTypeTrait<std::string>::BE(const uint8_t* b)
00099 {
00100 return std::string((const char*)b);
00101 }
00102
00103 #if defined(__APPLE_CC__)
00104
00105 template <>
00106 inline unsigned long IFDTypeTrait<unsigned long>::EL(const uint8_t* b)
00107 {
00108 return EL32(b);
00109 }
00110
00111 template <>
00112 inline unsigned long IFDTypeTrait<unsigned long>::BE(const uint8_t* b)
00113 {
00114 return BE32(b);
00115 }
00116 #endif
00117
00118 class IFDEntry
00119 {
00120 public:
00122 typedef boost::shared_ptr<IFDEntry> Ref;
00123
00124 IFDEntry(uint16_t _id, int16_t _type, int32_t _count,
00125 uint32_t _data,
00126 IFDFileContainer &_container);
00127 virtual ~IFDEntry();
00128
00129 int16_t type() const
00130 {
00131 return m_type;
00132 }
00133
00135 uint16_t count() const
00136 {
00137 return m_count;
00138 }
00139
00143 off_t offset()
00144 {
00145 if (endian() == RawContainer::ENDIAN_LITTLE) {
00146 return IFDTypeTrait<uint32_t>::EL((uint8_t*)&m_data);
00147 }
00148 return IFDTypeTrait<uint32_t>::BE((uint8_t*)&m_data);
00149 }
00150
00151 RawContainer::EndianType endian() const;
00152
00153 public:
00159 bool loadData(size_t unit_size);
00160
00161
00167 template <typename T>
00168 void getArray(std::vector<T> & array)
00169 {
00170 try {
00171 array.reserve(m_count);
00172 for (uint32_t i = 0; i < m_count; i++) {
00173 array.push_back(IFDTypeTrait<T>::get(*this, i));
00174 }
00175 }
00176 catch(std::exception & e)
00177 {
00178 throw e;
00179 }
00180 }
00181
00182
00183 private:
00184 uint16_t m_id;
00185 uint16_t m_type;
00186 uint32_t m_count;
00187 uint32_t m_data;
00188 bool m_loaded;
00189 uint8_t *m_dataptr;
00190 IFDFileContainer & m_container;
00191 template <typename T> friend struct IFDTypeTrait;
00192
00194 IFDEntry(const IFDEntry& f);
00196 IFDEntry & operator=(const IFDEntry&);
00197
00198 };
00199
00200
00201
00210 template <typename T>
00211 T IFDTypeTrait<T>::get(IFDEntry & e, uint32_t idx, bool ignore_type)
00212 throw (BadTypeException, OutOfRangeException, TooBigException)
00213 {
00214
00215 if(!ignore_type && (e.m_type != IFD::EXIF_FORMAT_UNDEFINED)) {
00216 if (e.m_type != IFDTypeTrait<T>::type) {
00217 throw BadTypeException();
00218 }
00219 }
00220 if (idx + 1 > e.m_count) {
00221 throw OutOfRangeException();
00222 }
00223 if (!e.m_loaded) {
00224 e.m_loaded = e.loadData(IFDTypeTrait<T>::size);
00225 if (!e.m_loaded) {
00226 throw TooBigException();
00227 }
00228 }
00229 uint8_t *data;
00230 if (e.m_dataptr == NULL) {
00231 data = (uint8_t*)&e.m_data;
00232 }
00233 else {
00234 data = e.m_dataptr;
00235 }
00236 data += (IFDTypeTrait<T>::size * idx);
00237 T val;
00238 if (e.endian() == RawContainer::ENDIAN_LITTLE) {
00239 val = IFDTypeTrait<T>::EL(data);
00240 }
00241 else {
00242 val = IFDTypeTrait<T>::BE(data);
00243 }
00244 return val;
00245 }
00246
00247 }
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 #endif
00261
00262