1 /*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5 Copyright (C) 2014 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/DcrDecoder.h"
23 #include "common/NORangesSet.h" // for set
24 #include "decoders/RawDecoderException.h" // for ThrowRDE
25 #include "decompressors/KodakDecompressor.h" // for KodakDecompressor
26 #include "io/Buffer.h" // for Buffer, DataBuffer
27 #include "io/ByteStream.h" // for ByteStream
28 #include "io/Endianness.h" // for Endianness, Endianness:...
29 #include "tiff/TiffEntry.h" // for TiffEntry, TIFF_SHORT
30 #include "tiff/TiffIFD.h" // for TiffRootIFD, TiffID
31 #include "tiff/TiffTag.h" // for COMPRESSION, KODAK_IFD
32 #include <array> // for array
33 #include <cassert> // for assert
34 #include <memory> // for unique_ptr
35 #include <string> // for operator==, string
36
37 namespace rawspeed {
38
39 class CameraMetaData;
40
isAppropriateDecoder(const TiffRootIFD * rootIFD,const Buffer * file)41 bool DcrDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD,
42 const Buffer* file) {
43 const auto id = rootIFD->getID();
44 const std::string& make = id.make;
45
46 // FIXME: magic
47
48 return make == "Kodak";
49 }
50
checkImageDimensions()51 void DcrDecoder::checkImageDimensions() {
52 if (width > 4516 || height > 3012)
53 ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
54 }
55
decodeRawInternal()56 RawImage DcrDecoder::decodeRawInternal() {
57 SimpleTiffDecoder::prepareForRawDecoding();
58
59 ByteStream input(DataBuffer(mFile->getSubView(off), Endianness::little));
60
61 int compression = raw->getEntry(COMPRESSION)->getU32();
62 if (65000 != compression)
63 ThrowRDE("Unsupported compression %d", compression);
64
65 TiffEntry* ifdoffset = mRootIFD->getEntryRecursive(KODAK_IFD);
66 if (!ifdoffset)
67 ThrowRDE("Couldn't find the Kodak IFD offset");
68
69 NORangesSet<Buffer> ifds;
70
71 assert(ifdoffset != nullptr);
72 TiffRootIFD kodakifd(nullptr, &ifds, ifdoffset->getRootIfdData(),
73 ifdoffset->getU32());
74
75 TiffEntry* linearization = kodakifd.getEntryRecursive(KODAK_LINEARIZATION);
76 if (!linearization ||
77 !(linearization->count == 1024 || linearization->count == 4096) ||
78 linearization->type != TIFF_SHORT)
79 ThrowRDE("Couldn't find the linearization table");
80
81 assert(linearization != nullptr);
82 auto linTable = linearization->getU16Array(linearization->count);
83
84 RawImageCurveGuard curveHandler(&mRaw, linTable, uncorrectedRawValues);
85
86 // FIXME: dcraw does all sorts of crazy things besides this to fetch
87 // WB from what appear to be presets and calculate it in weird ways
88 // The only file I have only uses this method, if anybody careas look
89 // in dcraw.c parse_kodak_ifd() for all that weirdness
90 TiffEntry* blob = kodakifd.getEntryRecursive(static_cast<TiffTag>(0x03fd));
91 if (blob && blob->count == 72) {
92 for (auto i = 0U; i < 3; i++) {
93 const auto mul = blob->getU16(20 + i);
94 if (0 == mul)
95 ThrowRDE("WB coeffient is zero!");
96 mRaw->metadata.wbCoeffs[i] = 2048.0F / mul;
97 }
98 }
99
100 const int bps = [CurveSize = linearization->count]() -> int {
101 switch (CurveSize) {
102 case 1024:
103 return 10;
104 case 4096:
105 return 12;
106 }
107 __builtin_unreachable();
108 }();
109
110 KodakDecompressor k(mRaw, input, bps, uncorrectedRawValues);
111 k.decompress();
112
113 return mRaw;
114 }
115
decodeMetaDataInternal(const CameraMetaData * meta)116 void DcrDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
117 setMetaData(meta, "", 0);
118 }
119
120 } // namespace rawspeed
121