libopenraw
|
00001 /* 00002 * libopenraw - ifdentry.h 00003 * 00004 * Copyright (C) 2006-2008 Hubert Figuiere 00005 * 00006 * This library is free software: you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public License 00008 * as published by the Free Software Foundation, either version 3 of 00009 * the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library. If not, see 00018 * <http://www.gnu.org/licenses/>. 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 // Apple broken C++ needs this 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 /* format undefined means that we don't check the type */ 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 Local Variables: 00253 mode:c++ 00254 c-file-style:"stroustrup" 00255 c-file-offsets:((innamespace . 0)) 00256 indent-tabs-mode:nil 00257 fill-column:80 00258 End: 00259 */ 00260 #endif 00261 00262