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 <boost/shared_ptr.hpp>
00026 #include <libopenraw/types.h>
00027
00028 #include "exception.h"
00029 #include "endianutils.h"
00030 #include "rawcontainer.h"
00031 #include "ifd.h"
00032
00033 namespace OpenRaw {
00034 namespace Internals {
00035
00036 class IFDFileContainer;
00037
00038 class IFDEntry;
00039
00041 template <typename T>
00042 struct IFDTypeTrait
00043 {
00044 static const uint16_t type;
00045 static const size_t size;
00046 static T EL(const uint8_t* d);
00047 static T BE(const uint8_t* d);
00048 static T get(IFDEntry & e, uint32_t idx = 0, bool ignore_type = false)
00049 throw (BadTypeException, OutOfRangeException, TooBigException);
00050 };
00051
00052
00053 template <>
00054 inline uint8_t IFDTypeTrait<uint8_t>::EL(const uint8_t* b)
00055 {
00056 return *b;
00057 }
00058
00059 template <>
00060 inline uint8_t IFDTypeTrait<uint8_t>::BE(const uint8_t* b)
00061 {
00062 return *b;
00063 }
00064
00065
00066 template <>
00067 inline uint16_t IFDTypeTrait<uint16_t>::EL(const uint8_t* b)
00068 {
00069 return EL16(b);
00070 }
00071
00072 template <>
00073 inline uint16_t IFDTypeTrait<uint16_t>::BE(const uint8_t* b)
00074 {
00075 return BE16(b);
00076 }
00077
00078 template <>
00079 inline uint32_t IFDTypeTrait<uint32_t>::EL(const uint8_t* b)
00080 {
00081 return EL32(b);
00082 }
00083
00084 template <>
00085 inline uint32_t IFDTypeTrait<uint32_t>::BE(const uint8_t* b)
00086 {
00087 return BE32(b);
00088 }
00089
00090 #if defined(__APPLE_CC__)
00091
00092 template <>
00093 inline unsigned long IFDTypeTrait<unsigned long>::EL(const uint8_t* b)
00094 {
00095 return EL32(b);
00096 }
00097
00098 template <>
00099 inline unsigned long IFDTypeTrait<unsigned long>::BE(const uint8_t* b)
00100 {
00101 return BE32(b);
00102 }
00103 #endif
00104
00105 class IFDEntry
00106 {
00107 public:
00109 typedef boost::shared_ptr<IFDEntry> Ref;
00110
00111 IFDEntry(uint16_t _id, int16_t _type, int32_t _count,
00112 uint32_t _data,
00113 IFDFileContainer &_container);
00114 virtual ~IFDEntry();
00115
00116 int16_t type() const
00117 {
00118 return m_type;
00119 }
00120
00122 uint16_t count() const
00123 {
00124 return m_count;
00125 }
00126
00130 off_t offset()
00131 {
00132 if (endian() == RawContainer::ENDIAN_LITTLE) {
00133 return IFDTypeTrait<uint32_t>::EL((uint8_t*)&m_data);
00134 }
00135 return IFDTypeTrait<uint32_t>::BE((uint8_t*)&m_data);
00136 }
00137
00138 RawContainer::EndianType endian() const;
00139
00140 public:
00146 bool loadData(size_t unit_size);
00147
00148
00154 template <typename T>
00155 void getArray(std::vector<T> & array)
00156 {
00157 try {
00158 array.reserve(m_count);
00159 for (uint32_t i = 0; i < m_count; i++) {
00160 array.push_back(IFDTypeTrait<T>::get(*this, i));
00161 }
00162 }
00163 catch(std::exception & e)
00164 {
00165 throw e;
00166 }
00167 }
00168
00169
00170 private:
00171 uint16_t m_id;
00172 uint16_t m_type;
00173 uint32_t m_count;
00174 uint32_t m_data;
00175 bool m_loaded;
00176 uint8_t *m_dataptr;
00177 IFDFileContainer & m_container;
00178 template <typename T> friend struct IFDTypeTrait;
00179
00181 IFDEntry(const IFDEntry& f);
00183 IFDEntry & operator=(const IFDEntry&);
00184
00185 };
00186
00187
00188
00197 template <typename T>
00198 T IFDTypeTrait<T>::get(IFDEntry & e, uint32_t idx, bool ignore_type)
00199 throw (BadTypeException, OutOfRangeException, TooBigException)
00200 {
00201
00202 if(!ignore_type && (e.m_type != IFD::EXIF_FORMAT_UNDEFINED)) {
00203 if (e.m_type != IFDTypeTrait<T>::type) {
00204 throw BadTypeException();
00205 }
00206 }
00207 if (idx + 1 > e.m_count) {
00208 throw OutOfRangeException();
00209 }
00210 if (!e.m_loaded) {
00211 e.m_loaded = e.loadData(IFDTypeTrait<T>::size);
00212 if (!e.m_loaded) {
00213 throw TooBigException();
00214 }
00215 }
00216 uint8_t *data;
00217 if (e.m_dataptr == NULL) {
00218 data = (uint8_t*)&e.m_data;
00219 }
00220 else {
00221 data = e.m_dataptr;
00222 }
00223 data += (IFDTypeTrait<T>::size * idx);
00224 T val;
00225 if (e.endian() == RawContainer::ENDIAN_LITTLE) {
00226 val = IFDTypeTrait<T>::EL(data);
00227 }
00228 else {
00229 val = IFDTypeTrait<T>::BE(data);
00230 }
00231 return val;
00232 }
00233
00234 }
00235 }
00236
00237
00238 #endif
00239
00240