libopenraw  0.3.7
ifdentry.cpp
1 /*
2  * libopenraw - ifdentry.cpp
3  *
4  * Copyright (C) 2006-2020 Hubert Figuière
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 
24 #include <cstdint>
25 #include <string>
26 
27 #include <libopenraw/debug.h>
28 
29 #include "trace.hpp"
30 #include "ifdfilecontainer.hpp"
31 #include "ifdentry.hpp"
32 #include "ifd.hpp"
33 
34 using namespace Debug;
35 
36 namespace OpenRaw {
37 namespace Internals {
38 
39 
40 IfdEntry::IfdEntry(uint16_t _id, int16_t _type,
41  int32_t _count, uint32_t _data,
42  const IfdDir& _dir, bool synthetic)
43  : m_id(_id), m_type(_type),
44  m_count(_count), m_data(_data),
45  m_loaded(false), m_dataptr(NULL),
46  m_dir(_dir)
47 {
48  if (!synthetic) {
49  auto container_size = m_dir.container().size();
50  auto unit_size = typeUnitSize(static_cast<IFD::ExifTagType>(m_type));
51  if ((m_count * unit_size) > static_cast<size_t>(container_size)) {
52  LOGERR("Trying to have %u items in a container of %lld bytes\n",
53  m_count, (long long int)container_size);
54  m_count = container_size / unit_size;
55  }
56  }
57 }
58 
59 
60 IfdEntry::~IfdEntry()
61 {
62  if (m_dataptr) {
63  free(m_dataptr);
64  }
65 }
66 
67 size_t IfdEntry::typeUnitSize(IFD::ExifTagType _type)
68 {
69  switch(_type) {
70  case IFD::EXIF_FORMAT_BYTE:
71  case IFD::EXIF_FORMAT_SBYTE:
72  case IFD::EXIF_FORMAT_ASCII:
73  case IFD::EXIF_FORMAT_UNDEFINED:
74  return 1;
75  case IFD::EXIF_FORMAT_SHORT:
76  case IFD::EXIF_FORMAT_SSHORT:
77  return 2;
78  case IFD::EXIF_FORMAT_LONG:
79  case IFD::EXIF_FORMAT_SLONG:
80  case IFD::EXIF_FORMAT_FLOAT:
81  return 4;
82  case IFD::EXIF_FORMAT_RATIONAL:
83  case IFD::EXIF_FORMAT_SRATIONAL:
84  case IFD::EXIF_FORMAT_DOUBLE:
85  return 8;
86  default:
87  return 0;
88  }
89 }
90 
91 RawContainer::EndianType IfdEntry::endian() const
92 {
93  return m_dir.endian();
94 }
95 
96 size_t IfdEntry::loadDataInto(uint8_t* dataptr, size_t data_size, off_t offset) const
97 {
98  off_t _offset;
99  if (endian() == RawContainer::ENDIAN_LITTLE) {
100  _offset = IfdTypeTrait<uint32_t>::EL((uint8_t*)&m_data, sizeof(uint32_t));
101  } else {
102  _offset = IfdTypeTrait<uint32_t>::BE((uint8_t*)&m_data, sizeof(uint32_t));
103  }
104  _offset += m_dir.container().exifOffsetCorrection() + offset;
105  LOGDBG1("loadData: offset %lld\n", (LOFFSET)_offset);
106  return m_dir.container().fetchData(dataptr, _offset, data_size);
107 }
108 
109 bool IfdEntry::loadData(size_t unit_size, off_t offset)
110 {
111  if (!m_loaded) {
112  size_t data_size = unit_size * m_count;
113  if (data_size <= 4) {
114  m_dataptr = NULL;
115  m_loaded = true;
116  } else {
117  m_dataptr = (uint8_t*)realloc(m_dataptr, data_size);
118  m_loaded = loadDataInto(m_dataptr, data_size, offset) == data_size;
119  }
120  }
121  return m_loaded;
122 }
123 
124 void IfdEntry::setData(const uint8_t* dataptr, size_t data_size)
125 {
126  if (!m_loaded) {
127  m_dataptr = (uint8_t*)realloc(m_dataptr, data_size);
128  memcpy(m_dataptr, dataptr, data_size);
129  m_loaded = true;
130  }
131 }
132 
133 template <>
134 const uint16_t IfdTypeTrait<uint8_t>::type = IFD::EXIF_FORMAT_BYTE;
135 template <>
136 const size_t IfdTypeTrait<uint8_t>::size = 1;
137 
138 template <>
139 const uint16_t IfdTypeTrait<uint16_t>::type = IFD::EXIF_FORMAT_SHORT;
140 template <>
141 const size_t IfdTypeTrait<uint16_t>::size = 2;
142 
143 template <>
144 const uint16_t IfdTypeTrait<int8_t>::type = IFD::EXIF_FORMAT_SBYTE;
145 template <>
146 const size_t IfdTypeTrait<int8_t>::size = 1;
147 
148 template <>
149 const uint16_t IfdTypeTrait<int16_t>::type = IFD::EXIF_FORMAT_SSHORT;
150 template <>
151 const size_t IfdTypeTrait<int16_t>::size = 2;
152 
153 template <>
154 const uint16_t IfdTypeTrait<IFD::ORRational>::type = IFD::EXIF_FORMAT_RATIONAL;
155 template <>
156 const size_t IfdTypeTrait<IFD::ORRational>::size = 8;
157 
158 template <>
159 const uint16_t IfdTypeTrait<IFD::ORSRational>::type = IFD::EXIF_FORMAT_SRATIONAL;
160 template <>
161 const size_t IfdTypeTrait<IFD::ORSRational>::size = 8;
162 
163 template <>
164 const uint16_t IfdTypeTrait<uint32_t>::type = IFD::EXIF_FORMAT_LONG;
165 template <>
166 const size_t IfdTypeTrait<uint32_t>::size = 4;
167 
168 template <>
169 const uint16_t IfdTypeTrait<int32_t>::type = IFD::EXIF_FORMAT_SLONG;
170 template <>
171 const size_t IfdTypeTrait<int32_t>::size = 4;
172 
173 template <>
174 const uint16_t IfdTypeTrait<std::string>::type = IFD::EXIF_FORMAT_ASCII;
175 template <>
176 const size_t IfdTypeTrait<std::string>::size = 1;
177 
178 }
179 }
180 /*
181  Local Variables:
182  mode:c++
183  c-file-style:"stroustrup"
184  c-file-offsets:((innamespace . 0))
185  tab-width:4
186  c-basic-offset:4
187  indent-tabs-mode:t
188  fill-column:80
189  End:
190 */
EndianType
Define the endian of the container.
ExifTagType
Definition: exif.h:271
Global namespace for libopenraw.
Definition: arwfile.cpp:29
Describe an IFD type.
Definition: ifdentry.hpp:55