libopenraw
ifdentry.cpp
1 /*
2  * libopenraw - ifdentry.cpp
3  *
4  * Copyright (C) 2006-2016 Hubert Figuiere
5  *
6  * This library is free software: you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation, either version 3 of
9  * the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 
22 #include <stdlib.h>
23 #include <math.h>
24 
25 #include <cstdint>
26 #include <string>
27 
28 #include <libopenraw/debug.h>
29 
30 #include "metavalue.hpp"
31 #include "trace.hpp"
32 #include "ifdfilecontainer.hpp"
33 #include "ifdentry.hpp"
34 #include "ifd.hpp"
35 
36 using namespace Debug;
37 
38 namespace OpenRaw {
39 namespace Internals {
40 
41 
42 IfdEntry::IfdEntry(uint16_t _id, int16_t _type,
43  int32_t _count, uint32_t _data,
44  IfdFileContainer &_container)
45  : m_id(_id), m_type(_type),
46  m_count(_count), m_data(_data),
47  m_loaded(false), m_dataptr(NULL),
48  m_container(_container)
49 {
50 }
51 
52 
53 IfdEntry::~IfdEntry()
54 {
55  if (m_dataptr) {
56  free(m_dataptr);
57  }
58 }
59 
60 namespace {
61 
62 template <class T>
63 void convert(Internals::IfdEntry* e, std::vector<MetaValue::value_t> & values)
64 {
65  std::vector<T> v;
66  e->getArray(v);
67  values.insert(values.end(), v.cbegin(), v.cend());
68 }
69 
70 // T is the Ifd primitive type. T2 is the target MetaValue type.
71 template <class T, class T2>
72 void convert(Internals::IfdEntry* e, std::vector<MetaValue::value_t> & values)
73 {
74  std::vector<T> v;
75  e->getArray(v);
76  for(const auto & elem : v) {
77  values.push_back(T2(elem));
78  }
79 }
80 
81 }
82 
83 MetaValue* IfdEntry::make_meta_value()
84 {
85  std::vector<MetaValue::value_t> values;
86 
87  switch(type()) {
88  case Internals::IFD::EXIF_FORMAT_BYTE:
89  {
90  convert<uint8_t, uint32_t>(this, values);
91  break;
92  }
93  case Internals::IFD::EXIF_FORMAT_ASCII:
94  {
95  convert<std::string>(this, values);
96  break;
97  }
98  case Internals::IFD::EXIF_FORMAT_SHORT:
99  {
100  convert<uint16_t, uint32_t>(this, values);
101  break;
102  }
103  case Internals::IFD::EXIF_FORMAT_LONG:
104  {
105  convert<uint32_t>(this, values);
106  break;
107  }
108  case Internals::IFD::EXIF_FORMAT_SRATIONAL:
109  {
110  convert<Internals::IFD::SRational, double>(this, values);
111  break;
112  }
113  default:
114  Trace(DEBUG1) << "unhandled type " << type() << "\n";
115  return NULL;
116  }
117  return new MetaValue(values);
118 }
119 
120 RawContainer::EndianType IfdEntry::endian() const
121 {
122  return m_container.endian();
123 }
124 
125 
126 bool IfdEntry::loadData(size_t unit_size)
127 {
128  bool success = false;
129  size_t data_size = unit_size * m_count;
130  if (data_size <= 4) {
131  m_dataptr = NULL;
132  success = true;
133  }
134  else {
135  off_t _offset;
136  if (endian() == RawContainer::ENDIAN_LITTLE) {
137  _offset = IfdTypeTrait<uint32_t>::EL((uint8_t*)&m_data);
138  }
139  else {
140  _offset = IfdTypeTrait<uint32_t>::BE((uint8_t*)&m_data);
141  }
142  _offset += m_container.exifOffsetCorrection();
143  m_dataptr = (uint8_t*)realloc(m_dataptr, data_size);
144  success = (m_container.fetchData(m_dataptr,
145  _offset,
146  data_size) == data_size);
147  }
148  return success;
149 }
150 
151 uint32_t IfdEntry::getIntegerArrayItem(int idx)
152 {
153  uint32_t v = 0;
154 
155  try {
156  switch(type())
157  {
158  case IFD::EXIF_FORMAT_LONG:
159  v = IfdTypeTrait<uint32_t>::get(*this, idx);
160  break;
161  case IFD::EXIF_FORMAT_SHORT:
162  v = IfdTypeTrait<uint16_t>::get(*this, idx);
163  break;
164  case IFD::EXIF_FORMAT_RATIONAL:
165  {
167  if(r.denom == 0) {
168  v = 0;
169  }
170  else {
171  v = r.num / r.denom;
172  }
173  break;
174  }
175  default:
176  break;
177  }
178  }
179  catch(const std::exception & ex) {
180  Debug::Trace(ERROR) << "Exception raised " << ex.what()
181  << " fetch integer value for " << m_id << "\n";
182  }
183 
184  return v;
185 }
186 
187 
188 namespace IFD {
189 
190 Rational::operator double() const
191 {
192  if(denom == 0) {
193  return INFINITY;
194  }
195  return (double)num / (double)denom;
196 }
197 
198 SRational::operator double() const
199 {
200  if(denom == 0) {
201  return INFINITY;
202  }
203  return (double)num / (double)denom;
204 }
205 
206 }
207 
208 template <>
209 const uint16_t IfdTypeTrait<uint8_t>::type = IFD::EXIF_FORMAT_BYTE;
210 template <>
211 const size_t IfdTypeTrait<uint8_t>::size = 1;
212 
213 template <>
214 const uint16_t IfdTypeTrait<uint16_t>::type = IFD::EXIF_FORMAT_SHORT;
215 template <>
216 const size_t IfdTypeTrait<uint16_t>::size = 2;
217 
218 template <>
219 const uint16_t IfdTypeTrait<IFD::Rational>::type = IFD::EXIF_FORMAT_RATIONAL;
220 template <>
221 const size_t IfdTypeTrait<IFD::Rational>::size = 8;
222 
223 template <>
224 const uint16_t IfdTypeTrait<IFD::SRational>::type = IFD::EXIF_FORMAT_SRATIONAL;
225 template <>
226 const size_t IfdTypeTrait<IFD::SRational>::size = 8;
227 
228 
229 #if defined(__APPLE_CC__)
230 // Apple broken g++ version or linker seems to choke.
231 template <>
232 const uint16_t IfdTypeTrait<unsigned long>::type = IFD::EXIF_FORMAT_LONG;
233 template <>
234 const size_t IfdTypeTrait<unsigned long>::size = 4;
235 #endif
236 template <>
237 const uint16_t IfdTypeTrait<uint32_t>::type = IFD::EXIF_FORMAT_LONG;
238 template <>
239 const size_t IfdTypeTrait<uint32_t>::size = 4;
240 
241 template <>
242 const uint16_t IfdTypeTrait<std::string>::type = IFD::EXIF_FORMAT_ASCII;
243 template <>
244 const size_t IfdTypeTrait<std::string>::size = 1;
245 }
246 }
247 /*
248  Local Variables:
249  mode:c++
250  c-file-style:"stroustrup"
251  c-file-offsets:((innamespace . 0))
252  indent-tabs-mode:nil
253  fill-column:80
254  End:
255 */
size_t fetchData(void *buf, off_t offset, size_t buf_size)
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard. I guess it failed.
Definition: arwfile.cpp:30
static T get(IfdEntry &e, uint32_t idx=0, bool ignore_type=false) noexcept(false)
Definition: ifdentry.hpp:269
Definition: trace.cpp:30
bool loadData(size_t unit_size)
Definition: ifdentry.cpp:126