1 /*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5 Copyright (C) 2017 Axel Waggershauser
6 Copyright (C) 2017-2018 Roman Lebedev
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "parsers/FiffParser.h"
24 #include "decoders/RafDecoder.h" // for RafDecoder
25 #include "decoders/RawDecoder.h" // for RawDecoder
26 #include "io/Buffer.h" // for Buffer, DataBuffer
27 #include "io/ByteStream.h" // for ByteStream
28 #include "io/Endianness.h" // for Endianness, Endianness::big
29 #include "parsers/FiffParserException.h" // for ThrowFPE
30 #include "parsers/RawParser.h" // for RawParser
31 #include "parsers/TiffParser.h" // for TiffParser
32 #include "parsers/TiffParserException.h" // for TiffParserException
33 #include "tiff/TiffEntry.h" // for TiffEntry, TiffDataType::SHORT, TIFF...
34 #include "tiff/TiffIFD.h" // for TiffIFD, TiffRootIFDOwner
35 #include "tiff/TiffTag.h" // for FUJIOLDWB, FUJI_STRIPBYTECO...
36 #include <cstdint> // for uint32_t, uint16_t
37 #include <limits> // for numeric_limits
38 #include <memory> // for make_unique, unique_ptr
39 #include <utility> // for move
40
41 using std::numeric_limits;
42
43 namespace rawspeed {
44
FiffParser(const Buffer & inputData)45 FiffParser::FiffParser(const Buffer& inputData) : RawParser(inputData) {}
46
parseData()47 void FiffParser::parseData() {
48 ByteStream bs(DataBuffer(mInput, Endianness::big));
49 bs.skipBytes(0x54);
50
51 uint32_t first_ifd = bs.getU32();
52 if (first_ifd >= numeric_limits<uint32_t>::max() - 12)
53 ThrowFPE("Not Fiff. First IFD too far away");
54
55 first_ifd += 12;
56
57 bs.skipBytes(4);
58 const uint32_t third_ifd = bs.getU32();
59 bs.skipBytes(4);
60 const uint32_t second_ifd = bs.getU32();
61
62 rootIFD = TiffParser::parse(nullptr, mInput.getSubView(first_ifd));
63 auto subIFD = std::make_unique<TiffIFD>(rootIFD.get());
64
65 if (mInput.isValid(second_ifd)) {
66 // RAW Tiff on newer models, pointer to raw data on older models
67 // -> so we try parsing as Tiff first and add it as data if parsing fails
68 try {
69 rootIFD->add(
70 TiffParser::parse(rootIFD.get(), mInput.getSubView(second_ifd)));
71 } catch (const TiffParserException&) {
72 // the offset will be interpreted relative to the rootIFD where this
73 // subIFD gets inserted
74
75 if (second_ifd <= first_ifd)
76 ThrowFPE("Fiff is corrupted: second IFD is not after the first IFD");
77
78 uint32_t rawOffset = second_ifd - first_ifd;
79 subIFD->add(std::make_unique<TiffEntry>(
80 subIFD.get(), TiffTag::FUJI_STRIPOFFSETS, TiffDataType::OFFSET, 1,
81 ByteStream::createCopy(&rawOffset, 4)));
82 uint32_t max_size = mInput.getSize() - second_ifd;
83 subIFD->add(std::make_unique<TiffEntry>(
84 subIFD.get(), TiffTag::FUJI_STRIPBYTECOUNTS, TiffDataType::LONG, 1,
85 ByteStream::createCopy(&max_size, 4)));
86 }
87 }
88
89 if (mInput.isValid(third_ifd)) {
90 // RAW information IFD on older
91
92 // This Fuji directory structure is similar to a Tiff IFD but with two
93 // differences:
94 // a) no type info and b) data is always stored in place.
95 // 4b: # of entries, for each entry: 2b tag, 2b len, xb data
96 ByteStream bytes(DataBuffer(mInput.getSubView(third_ifd), Endianness::big));
97 uint32_t entries = bytes.getU32();
98
99 if (entries > 255)
100 ThrowFPE("Too many entries");
101
102 for (uint32_t i = 0; i < entries; i++) {
103 auto tag = static_cast<TiffTag>(bytes.getU16());
104 uint16_t length = bytes.getU16();
105 TiffDataType type = TiffDataType::UNDEFINED;
106
107 if (tag == TiffTag::IMAGEWIDTH ||
108 tag == TiffTag::FUJIOLDWB) // also 0x121?
109 type = TiffDataType::SHORT;
110
111 uint32_t count = type == TiffDataType::SHORT ? length / 2 : length;
112 subIFD->add(std::make_unique<TiffEntry>(
113 subIFD.get(), tag, type, count,
114 bytes.getSubStream(bytes.getPosition(), length)));
115
116 bytes.skipBytes(length);
117 }
118 }
119
120 rootIFD->add(move(subIFD));
121 }
122
getDecoder(const CameraMetaData * meta)123 std::unique_ptr<RawDecoder> FiffParser::getDecoder(const CameraMetaData* meta) {
124 if (!rootIFD)
125 parseData();
126
127 // WARNING: do *NOT* fallback to ordinary TIFF parser here!
128 // All the FIFF raws are '.RAF' (Fujifilm). Do use RafDecoder directly.
129
130 try {
131 if (!RafDecoder::isAppropriateDecoder(rootIFD.get(), mInput))
132 ThrowFPE("Not a FUJIFILM RAF FIFF.");
133
134 return std::make_unique<RafDecoder>(std::move(rootIFD), mInput);
135 } catch (const TiffParserException&) {
136 ThrowFPE("No decoder found. Sorry.");
137 }
138 }
139
140 } // namespace rawspeed
141