25 #include "ciffcontainer.hpp" 28 using namespace Debug;
38 auto file = container->file();
39 file->seek(offset, SEEK_SET);
42 if (result_u32.empty()) {
45 imageWidth = result_u32.unwrap();
47 if (result_u32.empty()) {
50 imageHeight = result_u32.unwrap();
52 if (result_u32.empty()) {
55 pixelAspectRatio = result_u32.unwrap();
56 auto result_32 = container->
readInt32(file);
57 if (result_32.empty()) {
60 rotationAngle = result_32.unwrap();
62 if (result_u32.empty()) {
65 componentBitDepth = result_u32.unwrap();
67 if (result_u32.empty()) {
70 colorBitDepth = result_u32.unwrap();
72 if (result_u32.empty()) {
75 colorBW = result_u32.unwrap();
79 int32_t ImageSpec::exifOrientation()
const 81 int32_t orientation = 0;
82 switch(rotationAngle) {
99 RecordEntry::RecordEntry()
100 : typeCode(0), length(0), offset(0)
106 auto file = container->file();
108 if (result_16.empty()) {
111 typeCode = result_16.unwrap();
113 if (result_32.empty()) {
116 length = result_32.unwrap();
118 if (result_32.empty()) {
121 offset = result_32.unwrap();
125 size_t RecordEntry::fetchData(
Heap* heap,
void* buf,
size_t size)
const 128 offset + heap->
offset(), size);
135 m_container(_container),
138 LOGDBG2(
"Heap @ %ld length = %ld\n", start, m_length);
141 std::vector<RecordEntry> & Heap::records()
143 if (m_records.size() == 0) {
150 bool Heap::_loadRecords()
152 auto file = m_container->file();
153 file->seek(m_start + m_length - 4, SEEK_SET);
155 auto result = m_container->
readInt32(file);
158 int32_t record_offset = result.unwrap();
161 file->seek(m_start + record_offset, SEEK_SET);
162 auto result16 = m_container->
readInt16(file);
163 if (result16.empty()) {
164 LOGDBG1(
"read numRecords failed\n");
167 int16_t numRecords = result16.unwrap();
168 LOGDBG2(
"numRecords %d\n", numRecords);
170 m_records.reserve(numRecords);
171 for (int16_t i = 0; i < numRecords; i++) {
173 m_records.back().readFrom(m_container);
191 endian = RawContainer::ENDIAN_NULL;
193 auto file = container->file();
194 int s = file->read(byteOrder, 2);
196 if((byteOrder[0] ==
'I') && (byteOrder[1] ==
'I')) {
199 else if((byteOrder[0] ==
'M') && (byteOrder[1] ==
'M')) {
202 container->setEndian(endian);
205 headerLength = result32.unwrap();
209 ret = (file->read(type, 4) == 4);
212 ret = (file->read(subType, 4) == 4);
217 version = result32.unwrap();
227 CIFFContainer::CIFFContainer(
const IO::Stream::Ptr &_file)
231 m_hasImageSpec(
false)
233 m_endian = _readHeader();
236 CIFFContainer::~CIFFContainer()
240 CIFF::Heap::Ref CIFFContainer::heap()
242 if (m_heap ==
nullptr) {
248 bool CIFFContainer::_loadHeap()
254 if (m_endian != ENDIAN_NULL) {
255 off_t heapLength = m_file->filesize() - m_hdr.headerLength;
257 LOGDBG1(
"heap len %ld\n", heapLength);
258 m_heap = std::make_shared<CIFF::Heap>(m_hdr.headerLength,
264 LOGDBG1(
"Unknown endian\n");
273 EndianType _endian = ENDIAN_NULL;
274 m_hdr.readFrom(
this);
275 if ((::strncmp(m_hdr.type,
"HEAP", 4) == 0)
276 && (::strncmp(m_hdr.subType,
"CCDR", 4) == 0)) {
277 _endian = m_hdr.endian;
282 CIFF::Heap::Ref CIFFContainer::getImageProps()
286 return CIFF::Heap::Ref();
289 auto & records = m_heap->records();
292 auto iter = std::find_if(records.cbegin(), records.cend(),
294 return e.isA(static_cast<uint16_t>(CIFF::TAG_IMAGEPROPS));
296 if (iter == records.end()) {
297 LOGERR(
"Couldn't find the image properties.\n");
298 return CIFF::Heap::Ref();
301 m_imageprops = std::make_shared<CIFF::Heap>(
302 iter->offset + m_heap->offset(), iter->length,
this);
309 if(!m_hasImageSpec) {
310 CIFF::Heap::Ref props = getImageProps();
315 auto & propsRecs = props->records();
316 auto iter = std::find_if(propsRecs.cbegin(), propsRecs.cend(),
318 return e.isA(static_cast<uint16_t>(CIFF::TAG_IMAGEINFO));
320 if (iter == propsRecs.end()) {
321 LOGERR(
"Couldn't find the image info.\n");
324 m_imagespec.readFrom(iter->offset + props->offset(),
this);
325 m_hasImageSpec =
true;
330 const CIFF::Heap::Ref CIFFContainer::getCameraProps()
333 CIFF::Heap::Ref props = getImageProps();
336 return CIFF::Heap::Ref();
338 auto & propsRecs = props->records();
339 auto iter = std::find_if(propsRecs.cbegin(), propsRecs.cend(),
341 return e.isA(static_cast<uint16_t>(CIFF::TAG_CAMERAOBJECT));
343 if (iter == propsRecs.end()) {
344 LOGERR(
"Couldn't find the camera props.\n");
345 return CIFF::Heap::Ref();
347 m_cameraprops = std::make_shared<CIFF::Heap>(
348 iter->offset + props->offset(), iter->length,
this);
350 return m_cameraprops;
358 auto & records = m_heap->records();
360 auto iter = std::find_if(records.cbegin(), records.cend(),
362 return e.isA(static_cast<uint16_t>(CIFF::TAG_RAWIMAGEDATA));
365 if (iter != records.end()) {
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.
Option< int16_t > readInt16(const IO::Stream::Ptr &f)
Option< uint32_t > readUInt32(const IO::Stream::Ptr &f)
Option< uint16_t > readUInt16(const IO::Stream::Ptr &f)
Option< int32_t > readInt32(const IO::Stream::Ptr &f)