25#include "ciffcontainer.hpp"
38 auto file = container->file();
39 file->seek(offset, SEEK_SET);
42 if (result_u32.empty()) {
45 imageWidth = result_u32.value();
47 if (result_u32.empty()) {
50 imageHeight = result_u32.value();
52 if (result_u32.empty()) {
55 pixelAspectRatio = result_u32.value();
56 auto result_32 = container->
readInt32(file);
57 if (result_32.empty()) {
60 rotationAngle = result_32.value();
62 if (result_u32.empty()) {
65 componentBitDepth = result_u32.value();
67 if (result_u32.empty()) {
70 colorBitDepth = result_u32.value();
72 if (result_u32.empty()) {
75 colorBW = result_u32.value();
79int32_t ImageSpec::exifOrientation()
const
81 int32_t orientation = 0;
82 switch(rotationAngle) {
99RecordEntry::RecordEntry()
100 : typeCode(0), length(0), offset(0)
106 auto file = container->file();
108 if (result_16.empty()) {
111 typeCode = result_16.value();
113 if (result_32.empty()) {
116 length = result_32.value();
118 if (result_32.empty()) {
121 offset = result_32.value();
128 offset + heap->
offset(), size);
135 m_container(_container),
138 LOGDBG2(
"Heap @ %lld length = %lld\n", (
long long int)start, (
long long int)m_length);
141std::vector<RecordEntry> & Heap::records()
143 if (m_records.size() == 0) {
150bool 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.value();
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.value();
168 LOGDBG2(
"numRecords %d\n", numRecords);
170 m_records.reserve(numRecords);
171 for (int16_t i = 0; i < numRecords; i++) {
172 m_records.push_back(RecordEntry());
173 m_records.back().readFrom(m_container);
184 RecordEntry tblArray[1];
189bool HeapFileHeader::readFrom(CIFFContainer *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);
203 auto result32 = container->readUInt32(file);
205 headerLength = result32.value();
209 ret = (file->read(type, 4) == 4);
212 ret = (file->read(subType, 4) == 4);
215 result32 = container->readUInt32(file);
217 version = result32.value();
227CIFFContainer::CIFFContainer(
const IO::Stream::Ptr &_file)
228 : RawContainer(_file, 0),
231 m_hasImageSpec(false)
233 m_endian = _readHeader();
236CIFFContainer::~CIFFContainer()
240CIFF::Heap::Ref CIFFContainer::heap()
242 if (m_heap ==
nullptr) {
248bool CIFFContainer::_loadHeap()
254 if (m_endian != ENDIAN_NULL) {
255 off_t heapLength = m_file->filesize() - m_hdr.headerLength;
257 LOGDBG1(
"heap len %lld\n", (
long long int)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;
282CIFF::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(),
293 [](
const CIFF::RecordEntry& e) {
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);
307const CIFF::ImageSpec * CIFFContainer::getImageSpec()
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(),
317 [] (
const CIFF::RecordEntry &e) {
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;
330const 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(),
340 [] (
const CIFF::RecordEntry & e) {
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;
353const CIFF::RecordEntry * CIFFContainer::getRawDataRecord()
const
358 auto & records = m_heap->records();
360 auto iter = std::find_if(records.cbegin(), records.cend(),
361 [] (
const CIFF::RecordEntry &e) {
362 return e.isA(static_cast<uint16_t>(CIFF::TAG_RAWIMAGEDATA));
365 if (iter != records.end()) {
Heap(off_t start, off_t length, CIFFContainer *container)
bool readFrom(off_t offset, CIFFContainer *container)
bool readFrom(CIFFContainer *container)
size_t fetchData(Heap *heap, void *buf, size_t size) const
Option< int16_t > readInt16(const IO::Stream::Ptr &f)
size_t fetchData(void *buf, off_t offset, size_t buf_size)
Option< uint16_t > readUInt16(const IO::Stream::Ptr &f)
Option< uint32_t > readUInt32(const IO::Stream::Ptr &f)
Option< int32_t > readInt32(const IO::Stream::Ptr &f)
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard....