libopenraw  0.3.7
ciffcontainer.cpp
1 /*
2  * libopenraw - ciffcontainer.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 #include <fcntl.h>
22 #include <algorithm>
23 #include <cstring>
24 
25 #include "ciffcontainer.hpp"
26 #include "trace.hpp"
27 
28 using namespace Debug;
29 
30 namespace OpenRaw {
31 namespace Internals {
32 
33 namespace CIFF {
34 
35 
36 bool ImageSpec::readFrom(off_t offset, CIFFContainer *container)
37 {
38  auto file = container->file();
39  auto endian = container->endian();
40  file->seek(offset, SEEK_SET);
41 
42  auto result_u32 = container->readUInt32(file, endian);
43  if (result_u32.empty()) {
44  return false;
45  }
46  imageWidth = result_u32.value();
47  result_u32 = container->readUInt32(file, endian);
48  if (result_u32.empty()) {
49  return false;
50  }
51  imageHeight = result_u32.value();
52  result_u32 = container->readUInt32(file, endian);
53  if (result_u32.empty()) {
54  return false;
55  }
56  pixelAspectRatio = result_u32.value();
57  auto result_32 = container->readInt32(file, endian);
58  if (result_32.empty()) {
59  return false;
60  }
61  rotationAngle = result_32.value();
62  result_u32 = container->readUInt32(file, endian);
63  if (result_u32.empty()) {
64  return false;
65  }
66  componentBitDepth = result_u32.value();
67  result_u32 = container->readUInt32(file, endian);
68  if (result_u32.empty()) {
69  return false;
70  }
71  colorBitDepth = result_u32.value();
72  result_u32 = container->readUInt32(file, endian);
73  if (result_u32.empty()) {
74  return false;
75  }
76  colorBW = result_u32.value();
77  return true;
78 }
79 
80 int32_t ImageSpec::exifOrientation() const
81 {
82  int32_t orientation = 0;
83  switch(rotationAngle) {
84  case 0:
85  orientation = 1;
86  break;
87  case 90:
88  orientation = 6;
89  break;
90  case 180:
91  orientation = 3;
92  break;
93  case 270:
94  orientation = 8;
95  break;
96  }
97  return orientation;
98 }
99 
100 
101 #if 0
102 class OffsetTable {
103  uint16_t numRecords;/* the number tblArray elements */
104  RecordEntry tblArray[1];/* Array of the record entries */
105 };
106 #endif
107 
108 }
109 
110 CIFFContainer::CIFFContainer(const IO::Stream::Ptr &_file)
111  : RawContainer(_file, 0),
112  m_hdr(),
113  m_heap(nullptr),
114  m_hasImageSpec(false)
115 {
116  m_endian = _readHeader();
117 }
118 
119 CIFFContainer::~CIFFContainer()
120 {
121 }
122 
123 CIFF::HeapRef CIFFContainer::heap()
124 {
125  if (m_heap == nullptr) {
126  _loadHeap();
127  }
128  return m_heap;
129 }
130 
131 bool CIFFContainer::_loadHeap()
132 {
133  bool ret = false;
134  if (m_heap) {
135  return false;
136  }
137  if (m_endian != ENDIAN_NULL) {
138  off_t heapLength = m_file->filesize() - m_hdr.headerLength;
139 
140  LOGDBG1("heap len %lld\n", (long long int)heapLength);
141  m_heap = std::make_shared<CIFF::Heap>(m_hdr.headerLength,
142  heapLength, this);
143 
144  ret = true;
145  }
146  else {
147  LOGDBG1("Unknown endian\n");
148  }
149 
150  return ret;
151 }
152 
153 
154 RawContainer::EndianType CIFFContainer::_readHeader()
155 {
156  EndianType _endian = ENDIAN_NULL;
157  m_hdr.readFrom(this);
158  if ((::strncmp(m_hdr.type, "HEAP", 4) == 0)
159  && (::strncmp(m_hdr.subType, "CCDR", 4) == 0)) {
160  _endian = m_hdr.endian;
161  }
162  return _endian;
163 }
164 
165 CIFF::HeapRef CIFFContainer::getImageProps()
166 {
167  if(!m_imageprops) {
168  if(!heap()) {
169  return CIFF::HeapRef();
170  }
171 
172  auto & records = m_heap->records();
173 
174  // locate the properties
175  auto iter = records.find(CIFF::TAG_IMAGEPROPS);
176  if (iter == records.end()) {
177  LOGERR("Couldn't find the image properties.\n");
178  return CIFF::HeapRef();
179  }
180 
181  m_imageprops = std::make_shared<CIFF::Heap>(
182  iter->second.offset() + m_heap->offset(), iter->second.length(), this);
183  }
184  return m_imageprops;
185 }
186 
187 const CIFF::ImageSpec * CIFFContainer::getImageSpec()
188 {
189  if(!m_hasImageSpec) {
190  CIFF::HeapRef props = getImageProps();
191 
192  if(!props) {
193  return nullptr;
194  }
195  auto & propsRecs = props->records();
196  auto iter = propsRecs.find(CIFF::TAG_IMAGEINFO);
197  if (iter == propsRecs.end()) {
198  LOGERR("Couldn't find the image info.\n");
199  return nullptr;
200  }
201  m_imagespec.readFrom(iter->second.offset() + props->offset(), this);
202  m_hasImageSpec = true;
203  }
204  return &m_imagespec;
205 }
206 
207 CIFF::HeapRef CIFFContainer::getCameraProps()
208 {
209  if(!m_cameraprops) {
210  CIFF::HeapRef props = getImageProps();
211 
212  if(!props) {
213  return CIFF::HeapRef();
214  }
215  auto & propsRecs = props->records();
216  auto iter = propsRecs.find(CIFF::TAG_CAMERAOBJECT);
217  if (iter == propsRecs.end()) {
218  LOGERR("Couldn't find the camera props.\n");
219  return CIFF::HeapRef();
220  }
221  m_cameraprops = std::make_shared<CIFF::Heap>(
222  iter->second.offset() + props->offset(), iter->second.length(), this);
223  }
224  return m_cameraprops;
225 }
226 
227 CIFF::HeapRef CIFFContainer::getExifInfo()
228 {
229  if (!m_exifinfo) {
230  CIFF::HeapRef props = getImageProps();
231 
232  if (!props) {
233  return CIFF::HeapRef();
234  }
235  auto& propsRecs = props->records();
236  auto iter = propsRecs.find(CIFF::TAG_EXIFINFORMATION);
237  if (iter == propsRecs.end()) {
238  LOGERR("Couldn't find the Exif information.\n");
239  return CIFF::HeapRef();
240  }
241  m_exifinfo = std::make_shared<CIFF::Heap>(
242  iter->second.offset() + props->offset(), iter->second.length(), this);
243  }
244 
245  return m_exifinfo;
246 }
247 
248 CIFF::CameraSettings CIFFContainer::getCameraSettings()
249 {
250  auto exifInfo = getExifInfo();
251  auto& propsRecs = exifInfo->records();
252  auto iter = propsRecs.find(CIFF::TAG_CAMERASETTINGS);
253  if (iter == propsRecs.end()) {
254  LOGERR("Couldn't find the camera settings.\n");
255  return CIFF::CameraSettings();
256  }
257  auto count = iter->second.count();
258  CIFF::CameraSettings settings;
259  file()->seek(exifInfo->offset() + iter->second.offset(), SEEK_SET);
260  size_t countRead = readUInt16Array(file(), settings, count);
261  if (count != countRead) {
262  LOGERR("Not enough data for camera settings\n");
263  }
264 
265  return settings;
266 }
267 
268 const CIFF::RecordEntry * CIFFContainer::getRawDataRecord() const
269 {
270  if(!m_heap) {
271  return nullptr;
272  }
273  auto & records = m_heap->records();
274  // locate the RAW data
275  auto iter = records.find(CIFF::TAG_RAWIMAGEDATA);
276  if (iter != records.end()) {
277  return &(iter->second);
278  }
279  return nullptr;
280 }
281 
282 }
283 }
284 /*
285  Local Variables:
286  mode:c++
287  c-file-style:"stroustrup"
288  c-file-offsets:((innamespace . 0))
289  indent-tabs-mode:nil
290  fill-column:80
291  End:
292 */
std::shared_ptr< Stream > Ptr
Definition: stream.hpp:47
A record entry from a CIFF Heap.
Definition: recordentry.hpp:69
Option< uint32_t > readUInt32(const IO::Stream::Ptr &f, EndianType endian) const
Read an uint32 following the m_endian set.
EndianType
Define the endian of the container.
Option< int32_t > readInt32(const IO::Stream::Ptr &f, EndianType endian) const
Read an int32 following the m_endian set.
std::shared_ptr< Heap > HeapRef
Shared ptr to Heap.
Definition: heap.hpp:38
std::vector< uint16_t > CameraSettings
Camera settings are stored as array of 16-bits int.
Global namespace for libopenraw.
Definition: arwfile.cpp:29