libopenraw
rafcontainer.cpp
1 /* -*- tab-width:4; c-basic-offset:4 indent-tabs-mode:t -*- */
2 /*
3  * libopenraw - rafcontainer.cpp
4  *
5  * Copyright (C) 2011-2016 Hubert Figuiere
6  *
7  * This library is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation, either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library. If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <fcntl.h>
23 #include <string.h>
24 #include <memory>
25 
26 #include "rafcontainer.hpp"
27 #include "raffile.hpp"
28 #include "jfifcontainer.hpp"
29 #include "ifdfilecontainer.hpp"
30 #include "rafmetacontainer.hpp"
31 #include "io/stream.hpp"
32 #include "io/streamclone.hpp"
33 
34 namespace OpenRaw {
35 namespace Internals {
36 
37 RafContainer::RafContainer(const IO::Stream::Ptr &_file)
38  : RawContainer(_file, 0)
39  , m_read(false)
40  , m_version(0)
41  , m_jpegPreview(nullptr)
42  , m_cfaContainer(nullptr)
43  , m_metaContainer(nullptr)
44 {
45  memset((void*)&m_offsetDirectory, 0, sizeof(m_offsetDirectory));
46 }
47 
49 {
50  delete m_jpegPreview;
51  delete m_cfaContainer;
52  delete m_metaContainer;
53 }
54 
55 const std::string & RafContainer::getModel()
56 {
57  if(!m_read) {
58  _readHeader();
59  }
60  return m_model;
61 }
62 
63 IfdFileContainer * RafContainer::getCfaContainer()
64 {
65  if(!m_cfaContainer) {
66  if(!m_read) {
67  _readHeader();
68  }
69  if(m_offsetDirectory.cfaOffset && m_offsetDirectory.cfaLength) {
70  m_cfaContainer = new IfdFileContainer(
71  std::make_shared<IO::StreamClone>(
72  m_file, m_offsetDirectory.cfaOffset), 0);
73  }
74  }
75  return m_cfaContainer;
76 }
77 
78 JfifContainer * RafContainer::getJpegPreview()
79 {
80  if(!m_jpegPreview) {
81  if(!m_read) {
82  _readHeader();
83  }
84  if(m_offsetDirectory.jpegOffset && m_offsetDirectory.jpegLength) {
85  m_jpegPreview = new JfifContainer(
86  std::make_shared<IO::StreamClone>(
87  m_file, m_offsetDirectory.jpegOffset), 0);
88  }
89  }
90  return m_jpegPreview;
91 }
92 
93 RafMetaContainer * RafContainer::getMetaContainer()
94 {
95  if(!m_metaContainer) {
96  if(!m_read) {
97  _readHeader();
98  }
99  if(m_offsetDirectory.metaOffset && m_offsetDirectory.metaLength) {
100  m_metaContainer = new RafMetaContainer(
101  std::make_shared<IO::StreamClone>(
102  m_file, m_offsetDirectory.metaOffset));
103  }
104  }
105  return m_metaContainer;
106 }
107 
108 bool RafContainer::_readHeader()
109 {
110  char magic[29];
111  char model[33];
112  magic[28] = 0;
113  model[32] = 0;
114  m_read = true;
115 
116  m_file->read(magic, 28);
117 
118  if(strncmp(magic, RAF_MAGIC, RAF_MAGIC_LEN) != 0) {
119  // not a RAF file
120  return false;
121  }
122 
123  setEndian(ENDIAN_BIG);
124 
125  m_file->read(model, 32);
126  m_model = model;
127  auto result = readUInt32(m_file);
128  if (result.empty()) {
129  return false;
130  }
131  m_version = result.unwrap();
132 
133  m_file->seek(20, SEEK_CUR);
134 
135  result = readUInt32(m_file);
136  if (result.empty()) {
137  return false;
138  }
139  m_offsetDirectory.jpegOffset = result.unwrap();
140  result = readUInt32(m_file);
141  if (result.empty()) {
142  return false;
143  }
144  m_offsetDirectory.jpegLength = result.unwrap();
145  result = readUInt32(m_file);
146  if (result.empty()) {
147  return false;
148  }
149  m_offsetDirectory.metaOffset = result.unwrap();
150  result = readUInt32(m_file);
151  if (result.empty()) {
152  return false;
153  }
154  m_offsetDirectory.metaLength = result.unwrap();
155  result = readUInt32(m_file);
156  if (result.empty()) {
157  return false;
158  }
159  m_offsetDirectory.cfaOffset = result.unwrap();
160  result = readUInt32(m_file);
161  if (result.empty()) {
162  return false;
163  }
164  m_offsetDirectory.cfaLength = result.unwrap();
165 
166  return true;
167 }
168 
169 }
170 }
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