RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
MrwDecoder.cpp
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5 Copyright (C) 2014-2015 Pedro CĂ´rte-Real
6 Copyright (C) 2017 Roman Lebedev
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21*/
22
23#include "decoders/MrwDecoder.h"
24#include "adt/Point.h"
26#include "common/RawImage.h"
29#include "io/Buffer.h"
30#include "io/ByteStream.h"
31#include "io/Endianness.h"
32#include "metadata/Camera.h"
33#include "parsers/TiffParser.h"
34#include "tiff/TiffIFD.h"
35#include <array>
36#include <cassert>
37#include <cstdint>
38#include <cstring>
39#include <memory>
40
41namespace rawspeed {
42
43class CameraMetaData;
44
46
48 static const std::array<char, 4> magic = {{0x00, 'M', 'R', 'M'}};
49 const Buffer data = input.getSubView(0, magic.size());
50 return 0 == memcmp(data.begin(), magic.data(), magic.size());
51}
52
54 if (!isMRW(mFile))
55 ThrowRDE("This isn't actually a MRW file, why are you calling me?");
56
58 ByteStream bs(db);
59
60 // magic
61 bs.skipBytes(4);
62
63 // the size of the rest of the header, up to the image data
64 const auto headerSize = bs.getU32();
65 (void)bs.check(headerSize);
66
67 // ... and offset to the image data at the same time
68 const auto dataOffset = bs.getPosition() + headerSize;
69 assert(bs.getPosition() == 8);
70
71 // now, let's parse rest of the header.
72 bs = bs.getSubStream(0, dataOffset);
73 bs.skipBytes(8);
74
75 bool foundPRD = false;
76 while (bs.getRemainSize() > 0) {
77 uint32_t tag = bs.getU32();
78 uint32_t len = bs.getU32();
79 (void)bs.check(len);
80 if (!len)
81 ThrowRDE("Found entry of zero length, MRW is corrupt.");
82
83 const auto origPos = bs.getPosition();
84
85 switch (tag) {
86 case 0x505244: { // PRD
87 foundPRD = true;
88 bs.skipBytes(8); // Version Number
89 raw_height = bs.getU16(); // CCD Size Y
90 raw_width = bs.getU16(); // CCD Size X
91
92 if (!raw_width || !raw_height || raw_width > 3280 || raw_height > 2456) {
93 ThrowRDE("Unexpected image dimensions found: (%u; %u)", raw_width,
95 }
96
97 bs.skipBytes(2); // Image Size Y
98 bs.skipBytes(2); // Image Size X
99
100 bpp = bs.getByte(); // DataSize
101 if (12 != bpp && 16 != bpp)
102 ThrowRDE("Unknown data size");
103
104 if ((raw_height * raw_width * bpp) % 8 != 0)
105 ThrowRDE("Bad combination of image size and raw dimensions.");
106
107 if (12 != bs.getByte()) // PixelSize
108 ThrowRDE("Unexpected pixel size");
109
110 const auto SM = bs.getByte(); // StorageMethod
111 if (0x52 != SM && 0x59 != SM)
112 ThrowRDE("Unknown storage method");
113 packed = (0x59 == SM);
114
115 if ((12 == bpp) != packed)
116 ThrowRDE("Packed/BPP sanity check failed!");
117
118 bs.skipBytes(1); // Unknown1
119 bs.skipBytes(2); // Unknown2
120 bs.skipBytes(2); // BayerPattern
121 break;
122 }
123 case 0x545457: // TTW
124 // Base value for offsets needs to be at the beginning of the TIFF block,
125 // not the file
126 rootIFD = TiffParser::parse(nullptr, bs.getBuffer(len));
127 break;
128 case 0x574247: // WBG
129 bs.skipBytes(4); // 4 factors
130 std::array<float, 4> wbCoeffs;
131 wbCoeffs = {};
132 for (auto& wb_coeff : wbCoeffs)
133 wb_coeff = static_cast<float>(bs.getU16()); // gain
134 wb_coeffs = wbCoeffs;
135
136 // FIXME?
137 // Gf = Gr / 2^(6+F)
138 break;
139 default:
140 // unknown block, let's just ignore
141 break;
142 }
143
144 bs.setPosition(origPos + len);
145 }
146
147 if (!foundPRD)
148 ThrowRDE("Did not find PRD tag. Image corrupt.");
149
150 // processed all of the header. the image data is directly next
151
152 const auto imageBits = raw_height * raw_width * bpp;
153 assert(imageBits > 0);
154 assert(imageBits % 8 == 0);
155
156 imageData = db.getSubView(bs.getPosition(), imageBits / 8);
157}
158
161
163 ByteStream bs(db);
164
165 if (packed) {
168 12 * raw_width / 8, 12, BitOrder::MSB);
169 mRaw->createData();
170 u.readUncompressedRaw();
171 } else {
174 2 * raw_width, 16, BitOrder::MSB);
175 mRaw->createData();
176 u.readUncompressedRaw();
177 }
178
179 return mRaw;
180}
181
183 if (!rootIFD)
184 ThrowRDE("Couldn't find make and model");
185
186 auto id = rootIFD->getID();
187 this->checkCameraSupported(meta, id.make, id.model, "");
188}
189
191 // Default
192 int iso = 0;
193
194 if (!rootIFD)
195 ThrowRDE("Couldn't find make and model");
196
197 auto id = rootIFD->getID();
198 setMetaData(meta, id.make, id.model, "", iso);
199
200 if (wb_coeffs) {
201 if (hints.contains("swapped_wb")) {
202 std::array<float, 4> wbCoeffs = {};
203 wbCoeffs[0] = (*wb_coeffs)[2];
204 wbCoeffs[1] = (*wb_coeffs)[0];
205 wbCoeffs[2] = (*wb_coeffs)[1];
206 mRaw->metadata.wbCoeffs = wbCoeffs;
207 } else {
208 std::array<float, 4> wbCoeffs = {};
209 wbCoeffs[0] = (*wb_coeffs)[0];
210 wbCoeffs[1] = (*wb_coeffs)[1];
211 wbCoeffs[2] = (*wb_coeffs)[3];
212 mRaw->metadata.wbCoeffs = wbCoeffs;
213 }
214 }
215}
216
217} // namespace rawspeed
#define ThrowRDE(...)
assert(dim.area() >=area)
Buffer getSubView(size_type offset, size_type size_) const
Definition Buffer.h:78
const uint8_t * begin() const
Definition Buffer.h:99
size_type check(size_type bytes) const
Definition ByteStream.h:63
size_type RAWSPEED_READONLY getRemainSize() const
Definition ByteStream.h:87
void setPosition(size_type newPos)
Definition ByteStream.h:83
Buffer getBuffer(size_type size_)
Definition ByteStream.h:103
ByteStream getSubStream(size_type offset, size_type size_) const
Definition ByteStream.h:54
void skipBytes(size_type nbytes)
Definition ByteStream.h:130
size_type getPosition() const
Definition ByteStream.h:78
void decodeMetaDataInternal(const CameraMetaData *meta) override
RawImage decodeRawInternal() override
static int isMRW(Buffer input)
TiffRootIFDOwner rootIFD
Definition MrwDecoder.h:38
Optional< std::array< float, 4 > > wb_coeffs
Definition MrwDecoder.h:45
void checkSupportInternal(const CameraMetaData *meta) override
MrwDecoder(Buffer file)
virtual void setMetaData(const CameraMetaData *meta, const std::string &make, const std::string &model, const std::string &mode, int iso_speed=0)
RawDecoder(Buffer file)
bool checkCameraSupported(const CameraMetaData *meta, const std::string &make, const std::string &model, const std::string &mode)
static TiffRootIFDOwner parse(TiffIFD *parent, Buffer data)