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