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