RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
NefDecoder.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) 2015 Pedro CĂ´rte-Real
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
9 License as published by the Free Software Foundation; either
10 version 2 of 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, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20*/
21
22#include "decoders/NefDecoder.h"
23#include "adt/Array1DRef.h"
24#include "adt/Array2DRef.h"
25#include "adt/Bit.h"
26#include "adt/Casts.h"
27#include "adt/Point.h"
30#include "common/Common.h"
31#include "common/RawImage.h"
35#include "io/Buffer.h"
36#include "io/ByteStream.h"
37#include "io/Endianness.h"
38#include "io/IOException.h"
39#include "metadata/Camera.h"
42#include "tiff/TiffEntry.h"
43#include "tiff/TiffIFD.h"
44#include "tiff/TiffTag.h"
45#include <algorithm>
46#include <array>
47#include <cassert>
48#include <cmath>
49#include <cstddef>
50#include <cstdint>
51#include <memory>
52#include <sstream>
53#include <string>
54#include <vector>
55
56using std::vector;
57
58using std::min;
59using std::ostringstream;
60
61namespace rawspeed {
62
64 [[maybe_unused]] Buffer file) {
65 const auto id = rootIFD->getID();
66 const std::string& make = id.make;
67
68 // FIXME: magic
69
70 return make == "NIKON CORPORATION" || make == "NIKON";
71}
72
74 const auto* raw = mRootIFD->getIFDWithTag(TiffTag::CFAPATTERN);
75 auto compression = raw->getEntry(TiffTag::COMPRESSION)->getU32();
76
77 const TiffEntry* offsets = raw->getEntry(TiffTag::STRIPOFFSETS);
78 const TiffEntry* counts = raw->getEntry(TiffTag::STRIPBYTECOUNTS);
79
80 if (mRootIFD->getEntryRecursive(TiffTag::MODEL)->getString() ==
81 "NIKON D100 ") {
82 if (!mFile.isValid(offsets->getU32()))
83 ThrowRDE("Image data outside of file.");
84 if (!D100IsCompressed(offsets->getU32())) {
86 return mRaw;
87 }
88 }
89
90 if (compression == 1 || (hints.contains("force_uncompressed")) ||
91 NEFIsUncompressed(raw)) {
93 return mRaw;
94 }
95
96 if (NEFIsUncompressedRGB(raw)) {
98 return mRaw;
99 }
100
101 if (offsets->count != 1) {
102 ThrowRDE("Multiple Strips found: %u", offsets->count);
103 }
104 if (counts->count != offsets->count) {
105 ThrowRDE(
106 "Byte count number does not match strip size: count:%u, strips:%u ",
107 counts->count, offsets->count);
108 }
109 if (!mFile.isValid(offsets->getU32(), counts->getU32()))
110 ThrowRDE("Invalid strip byte count. File probably truncated.");
111
112 if (34713 != compression)
113 ThrowRDE("Unsupported compression");
114
115 uint32_t width = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32();
116 uint32_t height = raw->getEntry(TiffTag::IMAGELENGTH)->getU32();
117 uint32_t bitPerPixel = raw->getEntry(TiffTag::BITSPERSAMPLE)->getU32();
118
119 mRaw->dim = iPoint2D(width, height);
120
121 const TiffEntry* meta =
122 mRootIFD->getEntryRecursive(static_cast<TiffTag>(0x96));
123 if (!meta) {
124 meta = mRootIFD->getEntryRecursive(static_cast<TiffTag>(0x8c)); // Fall back
125 if (!meta) {
126 ThrowRDE("Missing linearization table.");
127 }
128 }
129
130 const auto input =
131 mFile.getSubView(offsets->getU32(), counts->getU32()).getAsArray1DRef();
132
133 NikonDecompressor n(mRaw, meta->getData(), bitPerPixel);
134 mRaw->createData();
136
137 return mRaw;
138}
139
140/*
141Figure out if a NEF file is compressed. These fancy heuristics
142are only needed for the D100, thanks to a bug in some cameras
143that tags all images as "compressed".
144*/
146 const auto test = mFile.getSubView(offset, 256);
147 for (int i = 15; i < 256; i += 16)
148 if (test[i])
149 return true;
150
151 return false;
152}
153
154/* At least the D810 has a broken firmware that tags uncompressed images
155 as if they were compressed. For those cases we set uncompressed mode
156 by figuring out that the image is the size of uncompressed packing */
158 const TiffEntry* counts = raw->getEntry(TiffTag::STRIPBYTECOUNTS);
161 uint32_t bitPerPixel = raw->getEntry(TiffTag::BITSPERSAMPLE)->getU32();
162
163 if (!width || !height || !bitPerPixel)
164 return false;
165
166 const auto avaliableInputBytes = counts->getU32(0);
167 const auto requiredPixels = iPoint2D(width, height).area();
168
169 // Now, there can be three situations.
170
171 // We might have not enough input to produce the requested image size.
172 const uint64_t avaliableInputBits = uint64_t(8) * avaliableInputBytes;
173 const auto avaliablePixels = avaliableInputBits / bitPerPixel; // round down!
174 if (avaliablePixels < requiredPixels)
175 return false;
176
177 // We might have exactly enough input with no padding whatsoever.
178 if (avaliablePixels == requiredPixels)
179 return true;
180
181 // Or, we might have too much input. And sadly this is the worst case.
182 // We can't just accept this. Some *compressed* NEF's also pass this check :(
183 // Thus, let's accept *some* *small* padding.
184 const auto requiredInputBits = bitPerPixel * requiredPixels;
185 const auto requiredInputBytes = roundUpDivisionSafe(requiredInputBits, 8);
186 // While we might have more *pixels* than needed, it does not nessesairly mean
187 // that we have more input *bytes*. We might be off by a few pixels, and with
188 // small image dimensions and bpp, we might still be in the same byte.
189 assert(avaliableInputBytes >= requiredInputBytes);
190 const auto totalPadding = avaliableInputBytes - requiredInputBytes;
191 if (totalPadding % height != 0)
192 return false; // Inconsistent padding makes no sense here.
193 const auto perRowPadding = totalPadding / height;
194 return perRowPadding < 16;
195}
196
197/* At least the D810 has a broken firmware that tags uncompressed images
198 as if they were compressed. For those cases we set uncompressed mode
199 by figuring out that the image is the size of uncompressed packing */
201 uint32_t byteCount = raw->getEntry(TiffTag::STRIPBYTECOUNTS)->getU32(0);
204
205 if (byteCount % 3 != 0)
206 return false;
207
208 return byteCount / 3 == iPoint2D(width, height).area();
209}
210
213 const TiffEntry* offsets = raw->getEntry(TiffTag::STRIPOFFSETS);
214 const TiffEntry* counts = raw->getEntry(TiffTag::STRIPBYTECOUNTS);
215 uint32_t yPerSlice = raw->getEntry(TiffTag::ROWSPERSTRIP)->getU32();
216 uint32_t width = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32();
217 uint32_t height = raw->getEntry(TiffTag::IMAGELENGTH)->getU32();
218 uint32_t bitPerPixel = raw->getEntry(TiffTag::BITSPERSAMPLE)->getU32();
219
220 mRaw->dim = iPoint2D(width, height);
221
222 if (width == 0 || height == 0 || width > 8288 || height > 5520)
223 ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
224
225 if (counts->count != offsets->count) {
226 ThrowRDE("Byte count number does not match strip size: "
227 "count:%u, stips:%u ",
228 counts->count, offsets->count);
229 }
230
231 if (yPerSlice == 0 || yPerSlice > static_cast<uint32_t>(mRaw->dim.y) ||
232 roundUpDivisionSafe(mRaw->dim.y, yPerSlice) != counts->count) {
233 ThrowRDE("Invalid y per slice %u or strip count %u (height = %i)",
234 yPerSlice, counts->count, mRaw->dim.y);
235 }
236
237 vector<NefSlice> slices;
238 slices.reserve(counts->count);
239 uint32_t offY = 0;
240
241 for (uint32_t s = 0; s < counts->count; s++) {
242 NefSlice slice;
243 slice.offset = offsets->getU32(s);
244 slice.count = counts->getU32(s);
245
246 if (slice.count < 1)
247 ThrowRDE("Slice %u is empty", s);
248
249 if (offY + yPerSlice > height)
250 slice.h = height - offY;
251 else
252 slice.h = yPerSlice;
253
254 offY = min(height, offY + yPerSlice);
255
256 if (!mFile.isValid(slice.offset, slice.count))
257 ThrowRDE("Slice offset/count invalid");
258
259 slices.push_back(slice);
260 }
261
262 if (slices.empty())
263 ThrowRDE("No valid slices found. File probably truncated.");
264
265 assert(height == offY);
266 assert(slices.size() == counts->count);
267
268 if (bitPerPixel == 14 && width * slices[0].h * 2 == slices[0].count)
269 bitPerPixel = 16; // D3 & D810
270
271 mRaw->createData();
272 bitPerPixel = hints.get("real_bpp", bitPerPixel);
273
274 switch (bitPerPixel) {
275 case 12:
276 case 14:
277 case 16:
278 break;
279 default:
280 ThrowRDE("Invalid bpp found: %u", bitPerPixel);
281 }
282
283 offY = 0;
284 for (const NefSlice& slice : slices) {
285 ByteStream in(DataBuffer(mFile.getSubView(slice.offset, slice.count),
287 iPoint2D size(width, slice.h);
288 iPoint2D pos(0, offY);
289
290 if (hints.contains("coolpixmangled")) {
292 width * bitPerPixel / 8, 12, BitOrder::MSB32);
293 u.readUncompressedRaw();
294 } else {
295 if (hints.contains("coolpixsplit")) {
296 readCoolpixSplitRaw(in, size, pos, width * bitPerPixel / 8);
297 } else {
298 if (in.getSize() % size.y != 0)
299 ThrowRDE("Inconsistent row size");
300 const auto inputPitchBytes = in.getSize() / size.y;
301 BitOrder bo = (mRootIFD->rootBuffer.getByteOrder() == Endianness::big) ^
302 hints.contains("msb_override")
306 inputPitchBytes, bitPerPixel, bo);
307 u.readUncompressedRaw();
308 }
309 }
310
311 offY += slice.h;
312 }
313}
314
316 const iPoint2D& offset,
317 int inputPitch) const {
318 const Array2DRef<uint16_t> img(mRaw->getU16DataAsUncroppedArray2DRef());
319
320 if (size.y % 2 != 0)
321 ThrowRDE("Odd number of rows");
322 if (size.x % 8 != 0)
323 ThrowRDE("Column count isn't multiple of 8");
324 if (inputPitch != ((3 * size.x) / 2))
325 ThrowRDE("Unexpected input pitch");
326
327 // BitStreamerMSB loads exactly 4 bytes at once, and we squeeze 12 bits each
328 // time. We produce 2 pixels per 3 bytes (24 bits). If we want to be smart and
329 // to know where the first input bit for first odd row is, the input slice
330 // width must be a multiple of 8 pixels.
331
332 if (offset.x > mRaw->dim.x || offset.y > mRaw->dim.y)
333 ThrowRDE("All pixels outside of image");
334 if (offset.x + size.x > mRaw->dim.x || offset.y + size.y > mRaw->dim.y)
335 ThrowRDE("Output is partailly out of image");
336
337 // The input bytes are laid out in the memory in the following way:
338 // First, all even (0-2-4-) rows, and then all odd (1-3-5-) rows.
339 const auto evenLinesInput = input.getStream(size.y / 2, inputPitch)
342 const auto oddLinesInput = input.getStream(size.y / 2, inputPitch)
345
346 BitStreamerMSB even(evenLinesInput);
347 BitStreamerMSB odd(oddLinesInput);
348 for (int row = offset.y; row < size.y;) {
349 for (int col = offset.x; col < size.x; ++col)
350 img(row, col) = implicit_cast<uint16_t>(even.getBits(12));
351 ++row;
352 for (int col = offset.x; col < size.x; ++col)
353 img(row, col) = implicit_cast<uint16_t>(odd.getBits(12));
354 ++row;
355 }
356 assert(even.getRemainingSize() == 0 && odd.getRemainingSize() == 0 &&
357 "Should have run out of input");
358}
359
361 const auto* ifd = mRootIFD->getIFDWithTag(TiffTag::STRIPOFFSETS, 1);
362
363 uint32_t offset = ifd->getEntry(TiffTag::STRIPOFFSETS)->getU32();
364 // Hardcode the sizes as at least the width is not correctly reported
365 uint32_t width = 3040;
366 uint32_t height = 2024;
367
368 mRaw->dim = iPoint2D(width, height);
369
370 if (ByteStream bs(DataBuffer(mFile.getSubView(offset), Endianness::little));
371 bs.getRemainSize() == 0)
372 ThrowRDE("No input to decode!");
373
375 ByteStream(DataBuffer(mFile.getSubView(offset), Endianness::little)),
376 mRaw, iRectangle2D({0, 0}, iPoint2D(width, height)),
377 (12 * width / 8) + ((width + 2) / 10), 12, BitOrder::MSB);
378 mRaw->createData();
379
380 u.decode12BitRawWithControl<Endianness::big>();
381}
382
385 uint32_t offset = raw->getEntry(TiffTag::STRIPOFFSETS)->getU32();
386 uint32_t width = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32();
387 uint32_t height = raw->getEntry(TiffTag::IMAGELENGTH)->getU32();
388
389 if (width == 0 || height == 0 || width % 2 != 0 || width > 3680 ||
390 height > 2456)
391 ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
392
393 mRaw->dim = iPoint2D(width, height);
394 mRaw->setCpp(3);
395 mRaw->isCFA = false;
396 mRaw->createData();
397
398 ByteStream in(DataBuffer(mFile.getSubView(offset), Endianness::little));
399 DecodeNikonSNef(in);
400}
401
403 auto id = mRootIFD->getID();
404 std::string mode = getMode();
405 std::string extended_mode = getExtendedMode(mode);
406
407 if (meta->hasCamera(id.make, id.model, extended_mode))
408 checkCameraSupported(meta, id, extended_mode);
409 else
410 checkCameraSupported(meta, id, mode);
411}
412
415 return raw->getEntry(TiffTag::BITSPERSAMPLE)->getU32();
416}
417
418std::string NefDecoder::getMode() const {
419 ostringstream mode;
421 int compression = raw->getEntry(TiffTag::COMPRESSION)->getU32();
422 uint32_t bitPerPixel = raw->getEntry(TiffTag::BITSPERSAMPLE)->getU32();
423
424 if (NEFIsUncompressedRGB(raw))
425 mode << "sNEF-uncompressed";
426 else {
427 if (1 == compression || NEFIsUncompressed(raw))
428 mode << bitPerPixel << "bit-uncompressed";
429 else
430 mode << bitPerPixel << "bit-compressed";
431 }
432 return mode.str();
433}
434
435std::string NefDecoder::getExtendedMode(const std::string& mode) const {
436 ostringstream extended_mode;
437
438 const auto* ifd = mRootIFD->getIFDWithTag(TiffTag::CFAPATTERN);
439 uint32_t width = ifd->getEntry(TiffTag::IMAGEWIDTH)->getU32();
440 uint32_t height = ifd->getEntry(TiffTag::IMAGELENGTH)->getU32();
441
442 extended_mode << width << "x" << height << "-" << mode;
443 return extended_mode.str();
444}
445
446// We use this for the D50 and D2X whacky WB "encryption"
447const std::array<uint8_t, 256> NefDecoder::serialmap = {
448 {0xc1, 0xbf, 0x6d, 0x0d, 0x59, 0xc5, 0x13, 0x9d, 0x83, 0x61, 0x6b, 0x4f,
449 0xc7, 0x7f, 0x3d, 0x3d, 0x53, 0x59, 0xe3, 0xc7, 0xe9, 0x2f, 0x95, 0xa7,
450 0x95, 0x1f, 0xdf, 0x7f, 0x2b, 0x29, 0xc7, 0x0d, 0xdf, 0x07, 0xef, 0x71,
451 0x89, 0x3d, 0x13, 0x3d, 0x3b, 0x13, 0xfb, 0x0d, 0x89, 0xc1, 0x65, 0x1f,
452 0xb3, 0x0d, 0x6b, 0x29, 0xe3, 0xfb, 0xef, 0xa3, 0x6b, 0x47, 0x7f, 0x95,
453 0x35, 0xa7, 0x47, 0x4f, 0xc7, 0xf1, 0x59, 0x95, 0x35, 0x11, 0x29, 0x61,
454 0xf1, 0x3d, 0xb3, 0x2b, 0x0d, 0x43, 0x89, 0xc1, 0x9d, 0x9d, 0x89, 0x65,
455 0xf1, 0xe9, 0xdf, 0xbf, 0x3d, 0x7f, 0x53, 0x97, 0xe5, 0xe9, 0x95, 0x17,
456 0x1d, 0x3d, 0x8b, 0xfb, 0xc7, 0xe3, 0x67, 0xa7, 0x07, 0xf1, 0x71, 0xa7,
457 0x53, 0xb5, 0x29, 0x89, 0xe5, 0x2b, 0xa7, 0x17, 0x29, 0xe9, 0x4f, 0xc5,
458 0x65, 0x6d, 0x6b, 0xef, 0x0d, 0x89, 0x49, 0x2f, 0xb3, 0x43, 0x53, 0x65,
459 0x1d, 0x49, 0xa3, 0x13, 0x89, 0x59, 0xef, 0x6b, 0xef, 0x65, 0x1d, 0x0b,
460 0x59, 0x13, 0xe3, 0x4f, 0x9d, 0xb3, 0x29, 0x43, 0x2b, 0x07, 0x1d, 0x95,
461 0x59, 0x59, 0x47, 0xfb, 0xe5, 0xe9, 0x61, 0x47, 0x2f, 0x35, 0x7f, 0x17,
462 0x7f, 0xef, 0x7f, 0x95, 0x95, 0x71, 0xd3, 0xa3, 0x0b, 0x71, 0xa3, 0xad,
463 0x0b, 0x3b, 0xb5, 0xfb, 0xa3, 0xbf, 0x4f, 0x83, 0x1d, 0xad, 0xe9, 0x2f,
464 0x71, 0x65, 0xa3, 0xe5, 0x07, 0x35, 0x3d, 0x0d, 0xb5, 0xe9, 0xe5, 0x47,
465 0x3b, 0x9d, 0xef, 0x35, 0xa3, 0xbf, 0xb3, 0xdf, 0x53, 0xd3, 0x97, 0x53,
466 0x49, 0x71, 0x07, 0x35, 0x61, 0x71, 0x2f, 0x43, 0x2f, 0x11, 0xdf, 0x17,
467 0x97, 0xfb, 0x95, 0x3b, 0x7f, 0x6b, 0xd3, 0x25, 0xbf, 0xad, 0xc7, 0xc5,
468 0xc5, 0xb5, 0x8b, 0xef, 0x2f, 0xd3, 0x07, 0x6b, 0x25, 0x49, 0x95, 0x25,
469 0x49, 0x6d, 0x71, 0xc7}};
470const std::array<uint8_t, 256> NefDecoder::keymap = {
471 {0xa7, 0xbc, 0xc9, 0xad, 0x91, 0xdf, 0x85, 0xe5, 0xd4, 0x78, 0xd5, 0x17,
472 0x46, 0x7c, 0x29, 0x4c, 0x4d, 0x03, 0xe9, 0x25, 0x68, 0x11, 0x86, 0xb3,
473 0xbd, 0xf7, 0x6f, 0x61, 0x22, 0xa2, 0x26, 0x34, 0x2a, 0xbe, 0x1e, 0x46,
474 0x14, 0x68, 0x9d, 0x44, 0x18, 0xc2, 0x40, 0xf4, 0x7e, 0x5f, 0x1b, 0xad,
475 0x0b, 0x94, 0xb6, 0x67, 0xb4, 0x0b, 0xe1, 0xea, 0x95, 0x9c, 0x66, 0xdc,
476 0xe7, 0x5d, 0x6c, 0x05, 0xda, 0xd5, 0xdf, 0x7a, 0xef, 0xf6, 0xdb, 0x1f,
477 0x82, 0x4c, 0xc0, 0x68, 0x47, 0xa1, 0xbd, 0xee, 0x39, 0x50, 0x56, 0x4a,
478 0xdd, 0xdf, 0xa5, 0xf8, 0xc6, 0xda, 0xca, 0x90, 0xca, 0x01, 0x42, 0x9d,
479 0x8b, 0x0c, 0x73, 0x43, 0x75, 0x05, 0x94, 0xde, 0x24, 0xb3, 0x80, 0x34,
480 0xe5, 0x2c, 0xdc, 0x9b, 0x3f, 0xca, 0x33, 0x45, 0xd0, 0xdb, 0x5f, 0xf5,
481 0x52, 0xc3, 0x21, 0xda, 0xe2, 0x22, 0x72, 0x6b, 0x3e, 0xd0, 0x5b, 0xa8,
482 0x87, 0x8c, 0x06, 0x5d, 0x0f, 0xdd, 0x09, 0x19, 0x93, 0xd0, 0xb9, 0xfc,
483 0x8b, 0x0f, 0x84, 0x60, 0x33, 0x1c, 0x9b, 0x45, 0xf1, 0xf0, 0xa3, 0x94,
484 0x3a, 0x12, 0x77, 0x33, 0x4d, 0x44, 0x78, 0x28, 0x3c, 0x9e, 0xfd, 0x65,
485 0x57, 0x16, 0x94, 0x6b, 0xfb, 0x59, 0xd0, 0xc8, 0x22, 0x36, 0xdb, 0xd2,
486 0x63, 0x98, 0x43, 0xa1, 0x04, 0x87, 0x86, 0xf7, 0xa6, 0x26, 0xbb, 0xd6,
487 0x59, 0x4d, 0xbf, 0x6a, 0x2e, 0xaa, 0x2b, 0xef, 0xe6, 0x78, 0xb6, 0x4e,
488 0xe0, 0x2f, 0xdc, 0x7c, 0xbe, 0x57, 0x19, 0x32, 0x7e, 0x2a, 0xd0, 0xb8,
489 0xba, 0x29, 0x00, 0x3c, 0x52, 0x7d, 0xa8, 0x49, 0x3b, 0x2d, 0xeb, 0x25,
490 0x49, 0xfa, 0xa3, 0xaa, 0x39, 0xa7, 0xc5, 0xa7, 0x50, 0x11, 0x36, 0xfb,
491 0xc6, 0x67, 0x4a, 0xf5, 0xa5, 0x12, 0x65, 0x7e, 0xb0, 0xdf, 0xaf, 0x4e,
492 0xb3, 0x61, 0x7f, 0x2f}};
493
495 // Read the whitebalance
496
497 if (mRootIFD->hasEntryRecursive(static_cast<TiffTag>(12))) {
498 const TiffEntry* wb = mRootIFD->getEntryRecursive(static_cast<TiffTag>(12));
499 if (wb->count == 4) {
500 std::array<float, 4> wbCoeffs = {};
501 wbCoeffs[0] = wb->getFloat(0);
502 wbCoeffs[1] = wb->getFloat(2);
503 wbCoeffs[2] = wb->getFloat(1);
504 if (wbCoeffs[1] <= 0.0F)
505 wbCoeffs[1] = 1.0F;
506 mRaw->metadata.wbCoeffs = wbCoeffs;
507 }
508 } else if (mRootIFD->hasEntryRecursive(static_cast<TiffTag>(0x0097))) {
509 const TiffEntry* wb =
510 mRootIFD->getEntryRecursive(static_cast<TiffTag>(0x0097));
511 if (wb->count > 4) {
512 uint32_t version = 0;
513 for (uint32_t i = 0; i < 4; i++) {
514 const auto v = wb->getByte(i);
515 if (v < '0' || v > '9')
516 ThrowRDE("Bad version component: %c - not a digit", v);
517 version = (version << 4) + v - '0';
518 }
519
520 if (version == 0x100 && wb->count >= 80 &&
522 std::array<float, 4> wbCoeffs = {};
523 wbCoeffs[0] = static_cast<float>(wb->getU16(36));
524 wbCoeffs[2] = static_cast<float>(wb->getU16(37));
525 wbCoeffs[1] = static_cast<float>(wb->getU16(38));
526 mRaw->metadata.wbCoeffs = wbCoeffs;
527 } else if (version == 0x103 && wb->count >= 26 &&
529 std::array<float, 4> wbCoeffs = {};
530 wbCoeffs[0] = static_cast<float>(wb->getU16(10));
531 wbCoeffs[1] = static_cast<float>(wb->getU16(11));
532 wbCoeffs[2] = static_cast<float>(wb->getU16(12));
533 mRaw->metadata.wbCoeffs = wbCoeffs;
534 } else if (((version == 0x204 && wb->count >= 564) ||
535 (version == 0x205 && wb->count >= 284)) &&
536 mRootIFD->hasEntryRecursive(static_cast<TiffTag>(0x001d)) &&
537 mRootIFD->hasEntryRecursive(static_cast<TiffTag>(0x00a7))) {
538 // Get the serial number
539 std::string serial =
540 mRootIFD->getEntryRecursive(static_cast<TiffTag>(0x001d))
541 ->getString();
542 if (serial.length() > 9)
543 ThrowRDE("Serial number is too long (%zu)", serial.length());
544 uint32_t serialno = 0;
545 for (unsigned char c : serial) {
546 if (c >= '0' && c <= '9')
547 serialno = serialno * 10 + c - '0';
548 else
549 serialno = serialno * 10 + c % 10;
550 }
551
552 // Get the decryption key
553 const TiffEntry* key =
554 mRootIFD->getEntryRecursive(static_cast<TiffTag>(0x00a7));
555 const auto keydata = key->getData().getBuffer(4);
556 uint32_t keyno = keydata[0] ^ keydata[1] ^ keydata[2] ^ keydata[3];
557
558 // "Decrypt" the block using the serial and key
559 uint8_t ci = serialmap[serialno & 0xff];
560 uint8_t cj = keymap[keyno & 0xff];
561 uint8_t ck = 0x60;
562
563 ByteStream bs = wb->getData();
564 bs.skipBytes(version == 0x204 ? 284 : 4);
565
566 std::array<uint8_t, 14 + 8> buf;
567 for (unsigned char& i : buf) {
568 cj = uint8_t(cj + (ci * ck)); // modulo arithmetics.
569 i = bs.getByte() ^ cj;
570 ck++;
571 }
572
573 // Finally set the WB coeffs
574 uint32_t off = (version == 0x204) ? 6 : 14;
575 std::array<float, 4> wbCoeffs = {};
576
577 wbCoeffs[0] = static_cast<float>(getU16BE(&buf[off + 0]));
578 wbCoeffs[1] = static_cast<float>(getU16BE(&buf[off + 2]));
579 wbCoeffs[2] = static_cast<float>(getU16BE(&buf[off + 6]));
580 mRaw->metadata.wbCoeffs = wbCoeffs;
581 }
582 }
583 } else if (mRootIFD->hasEntryRecursive(static_cast<TiffTag>(0x0014))) {
584 const TiffEntry* wb =
585 mRootIFD->getEntryRecursive(static_cast<TiffTag>(0x0014));
586 ByteStream bs = wb->getData();
587 if (wb->count == 2560 && wb->type == TiffDataType::UNDEFINED) {
588 bs.skipBytes(1248);
590 std::array<float, 4> wbCoeffs = {};
591 wbCoeffs[0] = static_cast<float>(bs.getU16()) / 256.0F;
592 wbCoeffs[1] = 1.0F;
593 wbCoeffs[2] = static_cast<float>(bs.getU16()) / 256.0F;
594 mRaw->metadata.wbCoeffs = wbCoeffs;
595 } else if (bs.hasPatternAt("NRW ", 0)) {
596 uint32_t offset = 0;
597 if (!bs.hasPatternAt("0100", 4) && wb->count > 72)
598 offset = 56;
599 else if (wb->count > 1572)
600 offset = 1556;
601
602 if (offset) {
603 bs.skipBytes(offset);
605 std::array<float, 4> wbCoeffs = {};
606 wbCoeffs[0] = 4.0F * implicit_cast<float>(bs.getU32());
607 wbCoeffs[1] = implicit_cast<float>(bs.getU32());
608 wbCoeffs[1] += implicit_cast<float>(bs.getU32());
609 wbCoeffs[2] = 4.0F * implicit_cast<float>(bs.getU32());
610 mRaw->metadata.wbCoeffs = wbCoeffs;
611 }
612 }
613 }
614
615 if (hints.contains("nikon_wb_adjustment") && mRaw->metadata.wbCoeffs) {
616 (*mRaw->metadata.wbCoeffs)[0] *= 256.0F / 527.0F;
617 (*mRaw->metadata.wbCoeffs)[2] *= 256.0F / 317.0F;
618 }
619}
620
622 int iso = 0;
623 mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN,
625
626 auto makernotesWhite = mRaw->whitePoint;
627 int makernotesBlack = mRaw->blackLevel;
628
629 if (mRootIFD->hasEntryRecursive(TiffTag::ISOSPEEDRATINGS))
630 iso = mRootIFD->getEntryRecursive(TiffTag::ISOSPEEDRATINGS)->getU32();
631
633
634 auto id = mRootIFD->getID();
635 std::string mode = getMode();
636 std::string extended_mode = getExtendedMode(mode);
637
638 // Read black levels (seem to be recorded for 14bit always)
639 if (mRootIFD->hasEntryRecursive(TiffTag::NIKON_BLACKLEVEL)) {
640 const TiffEntry* bl =
641 mRootIFD->getEntryRecursive(TiffTag::NIKON_BLACKLEVEL);
642 if (bl->count != 4)
643 ThrowRDE("BlackLevel has %u entries instead of 4", bl->count);
644 uint32_t bitPerPixel = getBitPerSample();
645 if (bitPerPixel != 12 && bitPerPixel != 14)
646 ThrowRDE("Bad bit per pixel: %u", bitPerPixel);
647 const int sh = 14 - bitPerPixel;
648 mRaw->blackLevelSeparate =
649 Array2DRef(mRaw->blackLevelSeparateStorage.data(), 2, 2);
650 auto blackLevelSeparate1D = *mRaw->blackLevelSeparate->getAsArray1DRef();
651 blackLevelSeparate1D(0) = bl->getU16(0) >> sh;
652 blackLevelSeparate1D(1) = bl->getU16(1) >> sh;
653 blackLevelSeparate1D(2) = bl->getU16(2) >> sh;
654 blackLevelSeparate1D(3) = bl->getU16(3) >> sh;
655 }
656
657 if (meta->hasCamera(id.make, id.model, extended_mode)) {
658 setMetaData(meta, id, extended_mode, iso);
659 } else if (meta->hasCamera(id.make, id.model, mode)) {
660 setMetaData(meta, id, mode, iso);
661 } else {
662 setMetaData(meta, id, "", iso);
663 }
664
665 if (makernotesWhite)
666 mRaw->whitePoint = *makernotesWhite;
667 if (makernotesBlack != -1)
668 mRaw->blackLevel = makernotesBlack;
669}
670
671// DecodeNikonYUY2 decodes 12 bit data in an YUY2-like pattern (2 Luma, 1 Chroma
672// per 2 pixels). We un-apply the whitebalance, so output matches lossless. Note
673// that values are scaled. See comment below on details. OPTME: It would be
674// trivial to run this multithreaded.
676 if (mRaw->dim.x < 6)
677 ThrowIOE("got a %i wide sNEF, aborting", mRaw->dim.x);
678
679 // We need to read the applied whitebalance, since we should return
680 // data before whitebalance, so we "unapply" it.
681 const TiffEntry* wb = mRootIFD->getEntryRecursive(static_cast<TiffTag>(12));
682 if (!wb)
683 ThrowRDE("Unable to locate whitebalance needed for decompression");
684
685 assert(wb != nullptr);
686 if (wb->count != 4 || wb->type != TiffDataType::RATIONAL)
687 ThrowRDE("Whitebalance has unknown count or type");
688
689 float wb_r = wb->getFloat(0);
690 float wb_b = wb->getFloat(1);
691
692 // ((1024/x)*((1<<16)-1)+(1<<9))<=((1<<31)-1), x>0 gives: (0.0312495)
693 if (const auto lower_limit =
694 implicit_cast<float>(13'421'568.0 / 429'496'627.0);
695 wb_r < lower_limit || wb_b < lower_limit || wb_r > 10.0F || wb_b > 10.0F)
696 ThrowRDE("Whitebalance has bad values (%f, %f)",
698
699 std::array<float, 4> wbCoeffs = {};
700 wbCoeffs[0] = wb_r;
701 wbCoeffs[1] = 1.0F;
702 wbCoeffs[2] = wb_b;
703 mRaw->metadata.wbCoeffs = wbCoeffs;
704
705 auto inv_wb_r = static_cast<int>(1024.0F / wb_r);
706 auto inv_wb_b = static_cast<int>(1024.0F / wb_b);
707
708 auto curve = gammaCurve(1 / 2.4, 12.92, 4095);
709
710 // Scale output values to 16 bits.
711 for (int i = 0; i < 4096; i++) {
712 curve[i] = clampBits(static_cast<int>(curve[i]) << 2, 16);
713 }
714
715 curve.resize(4095);
716
717 RawImageCurveGuard curveHandler(&mRaw, curve, false);
718
719 uint16_t tmp;
720 auto* tmpch = reinterpret_cast<std::byte*>(&tmp);
721
722 const Array2DRef<uint16_t> out(mRaw->getU16DataAsUncroppedArray2DRef());
723 const auto in = Array2DRef(input.peekData(out.width() * out.height()),
724 out.width(), out.height());
725
726 for (int row = 0; row < out.height(); row++) {
727 uint32_t random = in(row, 0) + (in(row, 1) << 8) + (in(row, 2) << 16);
728 for (int col = 0; col < out.width(); col += 6) {
729 uint32_t g1 = in(row, col + 0);
730 uint32_t g2 = in(row, col + 1);
731 uint32_t g3 = in(row, col + 2);
732 uint32_t g4 = in(row, col + 3);
733 uint32_t g5 = in(row, col + 4);
734 uint32_t g6 = in(row, col + 5);
735
736 auto y1 = static_cast<float>(g1 | ((g2 & 0x0f) << 8));
737 auto y2 = static_cast<float>((g2 >> 4) | (g3 << 4));
738 auto cb = static_cast<float>(g4 | ((g5 & 0x0f) << 8));
739 auto cr = static_cast<float>((g5 >> 4) | (g6 << 4));
740
741 float cb2 = cb;
742 float cr2 = cr;
743 // Interpolate right pixel. We assume the sample is aligned with left
744 // pixel.
745 if ((col + 6) < out.width()) {
746 g4 = in(row, col + 6 + 3);
747 g5 = in(row, col + 6 + 4);
748 g6 = in(row, col + 6 + 5);
749 cb2 = (static_cast<float>((g4 | ((g5 & 0x0f) << 8))) + cb) * 0.5F;
750 cr2 = (static_cast<float>(((g5 >> 4) | (g6 << 4))) + cr) * 0.5F;
751 }
752
753 cb -= 2048;
754 cr -= 2048;
755 cb2 -= 2048;
756 cr2 -= 2048;
757
758 mRaw->setWithLookUp(
759 clampBits(static_cast<int>(implicit_cast<double>(y1) +
760 (1.370705 * implicit_cast<double>(cr))),
761 12),
762 tmpch, &random);
763 out(row, col) = clampBits((inv_wb_r * tmp + (1 << 9)) >> 10, 15);
764
765 mRaw->setWithLookUp(
766 clampBits(static_cast<int>(implicit_cast<double>(y1) -
767 (0.337633 * implicit_cast<double>(cb)) -
768 (0.698001 * implicit_cast<double>(cr))),
769 12),
770 reinterpret_cast<std::byte*>(&out(row, col + 1)), &random);
771
772 mRaw->setWithLookUp(
773 clampBits(
774 static_cast<int>(implicit_cast<double>(y1) +
775 (1.732446 // NOLINT(modernize-use-std-numbers)
776 * implicit_cast<double>(cb))),
777 12),
778 tmpch, &random);
779 out(row, col + 2) = clampBits((inv_wb_b * tmp + (1 << 9)) >> 10, 15);
780
781 mRaw->setWithLookUp(
782 clampBits(static_cast<int>(implicit_cast<double>(y2) +
783 (1.370705 * implicit_cast<double>(cr2))),
784 12),
785 tmpch, &random);
786 out(row, col + 3) = clampBits((inv_wb_r * tmp + (1 << 9)) >> 10, 15);
787
788 mRaw->setWithLookUp(
789 clampBits(static_cast<int>(implicit_cast<double>(y2) -
790 (0.337633 * implicit_cast<double>(cb2)) -
791 (0.698001 * implicit_cast<double>(cr2))),
792 12),
793 reinterpret_cast<std::byte*>(&out(row, col + 4)), &random);
794
795 mRaw->setWithLookUp(
796 clampBits(
797 static_cast<int>(implicit_cast<double>(y2) +
798 (1.732446 // NOLINT(modernize-use-std-numbers)
799 * implicit_cast<double>(cb2))),
800 12),
801 tmpch, &random);
802 out(row, col + 5) = clampBits((inv_wb_b * tmp + (1 << 9)) >> 10, 15);
803 }
804 }
805}
806
807// From: dcraw.c -- Dave Coffin's raw photo decoder
808#define SQR(x) ((x) * (x))
809std::vector<uint16_t> NefDecoder::gammaCurve(double pwr, double ts, int imax) {
810 std::vector<uint16_t> curve(65536);
811
812 int i;
813 std::array<double, 6> g;
814 std::array<double, 2> bnd = {{}};
815 g[0] = pwr;
816 g[1] = ts;
817 g[2] = g[3] = g[4] = 0;
818 bnd[g[1] >= 1] = 1;
819 if (std::abs(g[1]) > 0 && (g[1] - 1) * (g[0] - 1) <= 0) {
820 for (i = 0; i < 48; i++) {
821 g[2] = (bnd[0] + bnd[1]) / 2;
822 if (std::abs(g[0]) > 0)
823 bnd[(pow(g[2] / g[1], -g[0]) - 1) / g[0] - 1 / g[2] > -1] = g[2];
824 else
825 bnd[g[2] / exp(1 - (1 / g[2])) < g[1]] = g[2];
826 }
827 g[3] = g[2] / g[1];
828 if (std::abs(g[0]) > 0)
829 g[4] = g[2] * (1 / g[0] - 1);
830 }
831 if (std::abs(g[0]) > 0) {
832 g[5] = 1 / (g[1] * SQR(g[3]) / 2 - g[4] * (1 - g[3]) +
833 (1 - pow(g[3], 1 + g[0])) * (1 + g[4]) / (1 + g[0])) -
834 1;
835 } else {
836 g[5] = 1 / (g[1] * SQR(g[3]) / 2 + 1 - g[2] - g[3] -
837 g[2] * g[3] * (log(g[3]) - 1)) -
838 1;
839 }
840
841 for (i = 0; i < 0x10000; i++) {
842 curve[i] = 0xffff;
843 const double r = static_cast<double>(i) / imax;
844 if (r >= 1)
845 continue;
846 double v;
847 if (r < g[2]) {
848 v = r / g[1];
849 } else {
850 if (std::abs(g[0]) > 0) {
851 v = pow((r + g[4]) / (1 + g[4]), 1 / g[0]);
852 } else {
853 v = exp((r - 1) / g[2]);
854 }
855 }
856 curve[i] = static_cast<uint16_t>(0x10000 * v);
857 }
858
859 assert(curve.size() == 65536);
860
861 return curve;
862}
863#undef SQR
864
865} // namespace rawspeed
#define s
#define ThrowIOE(...)
Definition IOException.h:37
#define SQR(x)
#define ThrowRDE(...)
assert(dim.area() >=area)
bool checkCameraSupported(const CameraMetaData *meta, const TiffID &id, const std::string &mode)
void setMetaData(const CameraMetaData *meta, const TiffID &id, const std::string &mode, int iso_speed)
const TiffIFD * getIFDWithLargestImage(TiffTag filter=TiffTag::IMAGEWIDTH) const
int RAWSPEED_READONLY height() const
int RAWSPEED_READONLY width() const
size_type getRemainingSize() const
uint32_t getBits(int nbits)
Array1DRef< const uint8_t > getAsArray1DRef() const
Definition Buffer.h:70
size_type RAWSPEED_READONLY getSize() const
Definition Buffer.h:115
size_type RAWSPEED_READONLY getRemainSize() const
Definition ByteStream.h:87
Buffer getBuffer(size_type size_)
Definition ByteStream.h:103
ByteStream getStream(size_type size_)
Definition ByteStream.h:119
void skipBytes(size_type nbytes)
Definition ByteStream.h:130
const uint8_t * peekData(size_type count) const
Definition ByteStream.h:92
bool hasPatternAt(std::string_view pattern, size_type relPos) const
Definition ByteStream.h:135
Buffer peekRemainingBuffer() const
Definition ByteStream.h:108
bool hasCamera(const std::string &make, const std::string &model, const std::string &mode) const
Endianness setByteOrder(Endianness endianness_)
Definition Buffer.h:156
std::string getExtendedMode(const std::string &mode) const
static bool NEFIsUncompressed(const TiffIFD *raw)
static std::vector< uint16_t > gammaCurve(double pwr, double ts, int imax)
static bool NEFIsUncompressedRGB(const TiffIFD *raw)
void DecodeNikonSNef(ByteStream input) const
std::string getMode() const
RawImage decodeRawInternal() override
void DecodeSNefUncompressed() const
void DecodeD100Uncompressed() const
void checkSupportInternal(const CameraMetaData *meta) override
void DecodeUncompressed() const
void decodeMetaDataInternal(const CameraMetaData *meta) override
static const std::array< uint8_t, 256 > serialmap
Definition NefDecoder.h:71
static bool isAppropriateDecoder(const TiffRootIFD *rootIFD, Buffer file)
bool D100IsCompressed(uint32_t offset) const
void readCoolpixSplitRaw(ByteStream input, const iPoint2D &size, const iPoint2D &offset, int inputPitch) const
static const std::array< uint8_t, 256 > keymap
Definition NefDecoder.h:72
int getBitPerSample() const
void parseWhiteBalance() const
void decompress(Array1DRef< const uint8_t > input, bool uncorrectedRawValues)
Definition TiffEntry.h:62
float getFloat(uint32_t index=0) const
uint32_t getU32(uint32_t index=0) const
ByteStream getData() const
Definition TiffEntry.h:129
uint32_t count
Definition TiffEntry.h:84
uint16_t getU16(uint32_t index=0) const
TiffDataType type
Definition TiffEntry.h:83
uint8_t getByte(uint32_t index=0) const
TiffEntry * getEntry(TiffTag tag) const
Definition TiffIFD.cpp:313
TiffID getID() const
Definition TiffIFD.cpp:325
area_type RAWSPEED_READONLY area() const
Definition Point.h:81
constexpr uint64_t RAWSPEED_READNONE roundUpDivisionSafe(uint64_t value, uint64_t div)
Definition Common.h:145
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
uint16_t getU16BE(const void *data)
Definition Endianness.h:124
Array2DRef(Array1DRef< T > data, int width, int height, int pitch) -> Array2DRef< T >
void RAWSPEED_UNLIKELY_FUNCTION RAWSPEED_NOINLINE static char buf[bufSize]
constexpr auto RAWSPEED_READNONE clampBits(T value, unsigned int nBits)
Definition Bit.h:75
std::string make
Definition TiffIFD.h:134