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/PefDecoder.h"
23 #include "common/Common.h"                    // for BitOrder_MSB
24 #include "common/Point.h"                     // for iPoint2D
25 #include "decoders/RawDecoderException.h"     // for ThrowRDE
26 #include "decompressors/PentaxDecompressor.h" // for PentaxDecompressor
27 #include "io/Buffer.h"                        // for Buffer, DataBuffer
28 #include "io/ByteStream.h"                    // for ByteStream
29 #include "io/Endianness.h"                    // for Endianness, Endianness...
30 #include "metadata/ColorFilterArray.h"        // for CFA_GREEN, CFA_BLUE
31 #include "tiff/TiffEntry.h"                   // for TiffEntry, TIFF_UNDEFINED
32 #include "tiff/TiffIFD.h"                     // for TiffRootIFD, TiffIFD
33 #include "tiff/TiffTag.h"                     // for TiffTag, ISOSPEEDRATINGS
34 #include <array>                              // for array
35 #include <cstdint>                            // for uint32_t
36 #include <memory>                             // for unique_ptr
37 #include <string>                             // for operator==, string
38 
39 namespace rawspeed {
40 
isAppropriateDecoder(const TiffRootIFD * rootIFD,const Buffer & file)41 bool PefDecoder::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 == "PENTAX Corporation" ||
49          make == "RICOH IMAGING COMPANY, LTD." || make == "PENTAX";
50 }
51 
decodeRawInternal()52 RawImage PefDecoder::decodeRawInternal() {
53   const auto* raw = mRootIFD->getIFDWithTag(STRIPOFFSETS);
54 
55   int compression = raw->getEntry(COMPRESSION)->getU32();
56 
57   if (1 == compression || compression == 32773) {
58     decodeUncompressed(raw, BitOrder_MSB);
59     return mRaw;
60   }
61 
62   if (65535 != compression)
63     ThrowRDE("Unsupported compression");
64 
65   TiffEntry *offsets = raw->getEntry(STRIPOFFSETS);
66   TiffEntry *counts = raw->getEntry(STRIPBYTECOUNTS);
67 
68   if (offsets->count != 1) {
69     ThrowRDE("Multiple Strips found: %u", offsets->count);
70   }
71   if (counts->count != offsets->count) {
72     ThrowRDE(
73         "Byte count number does not match strip size: count:%u, strips:%u ",
74         counts->count, offsets->count);
75   }
76   ByteStream bs(
77       DataBuffer(mFile.getSubView(offsets->getU32(), counts->getU32()),
78                  Endianness::little));
79 
80   uint32_t width = raw->getEntry(IMAGEWIDTH)->getU32();
81   uint32_t height = raw->getEntry(IMAGELENGTH)->getU32();
82 
83   mRaw->dim = iPoint2D(width, height);
84 
85   ByteStream* metaData = nullptr;
86   ByteStream stream;
87   if (getRootIFD()->hasEntryRecursive(static_cast<TiffTag>(0x220))) {
88     /* Attempt to read huffman table, if found in makernote */
89     TiffEntry* t = getRootIFD()->getEntryRecursive(static_cast<TiffTag>(0x220));
90     if (t->type != TIFF_UNDEFINED)
91       ThrowRDE("Unknown Huffman table type.");
92 
93     stream = t->getData();
94     metaData = &stream;
95   }
96 
97   PentaxDecompressor p(mRaw, metaData);
98   mRaw->createData();
99   p.decompress(bs);
100 
101   return mRaw;
102 }
103 
decodeMetaDataInternal(const CameraMetaData * meta)104 void PefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
105   int iso = 0;
106   mRaw->cfa.setCFA(iPoint2D(2,2), CFA_RED, CFA_GREEN, CFA_GREEN, CFA_BLUE);
107 
108   if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
109     iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getU32();
110 
111   setMetaData(meta, "", iso);
112 
113   // Read black level
114   if (mRootIFD->hasEntryRecursive(static_cast<TiffTag>(0x200))) {
115     TiffEntry* black = mRootIFD->getEntryRecursive(static_cast<TiffTag>(0x200));
116     if (black->count == 4) {
117       for (int i = 0; i < 4; i++)
118         mRaw->blackLevelSeparate[i] = black->getU32(i);
119     }
120   }
121 
122   // Set the whitebalance
123   if (mRootIFD->hasEntryRecursive(static_cast<TiffTag>(0x0201))) {
124     TiffEntry* wb = mRootIFD->getEntryRecursive(static_cast<TiffTag>(0x0201));
125     if (wb->count == 4) {
126       mRaw->metadata.wbCoeffs[0] = wb->getU32(0);
127       mRaw->metadata.wbCoeffs[1] = wb->getU32(1);
128       mRaw->metadata.wbCoeffs[2] = wb->getU32(3);
129     }
130   }
131 }
132 
133 } // namespace rawspeed
134