RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
FiffParser.cpp
Go to the documentation of this file.
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"
25#include "io/Buffer.h"
26#include "io/ByteStream.h"
27#include "io/Endianness.h"
29#include "parsers/RawParser.h"
30#include "parsers/TiffParser.h"
32#include "tiff/TiffEntry.h"
33#include "tiff/TiffIFD.h"
34#include "tiff/TiffTag.h"
35#include <cstdint>
36#include <limits>
37#include <memory>
38#include <utility>
39
40using std::numeric_limits;
41
42namespace rawspeed {
43
44FiffParser::FiffParser(Buffer inputData) : RawParser(inputData) {}
45
48 bs.skipBytes(0x54);
49
50 uint32_t first_ifd = bs.getU32();
51 if (first_ifd >= numeric_limits<uint32_t>::max() - 12)
52 ThrowFPE("Not Fiff. First IFD too far away");
53
54 first_ifd += 12;
55
56 bs.skipBytes(4);
57 const uint32_t third_ifd = bs.getU32();
58 bs.skipBytes(4);
59 const uint32_t second_ifd = bs.getU32();
60
61 rootIFD = TiffParser::parse(nullptr, mInput.getSubView(first_ifd));
62 auto subIFD = std::make_unique<TiffIFD>(rootIFD.get());
63
64 if (mInput.isValid(second_ifd)) {
65 // RAW Tiff on newer models, pointer to raw data on older models
66 // -> so we try parsing as Tiff first and add it as data if parsing fails
67 try {
68 rootIFD->add(
69 TiffParser::parse(rootIFD.get(), mInput.getSubView(second_ifd)));
70 } catch (const TiffParserException&) {
71 // the offset will be interpreted relative to the rootIFD where this
72 // subIFD gets inserted
73
74 if (second_ifd <= first_ifd)
75 ThrowFPE("Fiff is corrupted: second IFD is not after the first IFD");
76
77 uint32_t rawOffset = second_ifd - first_ifd;
78 subIFD->add(std::make_unique<TiffEntryWithData>(
80 Buffer(reinterpret_cast<const uint8_t*>(&rawOffset),
81 sizeof(rawOffset))));
82 uint32_t max_size = mInput.getSize() - second_ifd;
83 subIFD->add(std::make_unique<TiffEntryWithData>(
85 Buffer(reinterpret_cast<const uint8_t*>(&max_size),
86 sizeof(rawOffset))));
87 }
88 }
89
90 if (mInput.isValid(third_ifd)) {
91 // RAW information IFD on older
92
93 // This Fuji directory structure is similar to a Tiff IFD but with two
94 // differences:
95 // a) no type info and b) data is always stored in place.
96 // 4b: # of entries, for each entry: 2b tag, 2b len, xb data
97 ByteStream bytes(DataBuffer(mInput.getSubView(third_ifd), Endianness::big));
98 uint32_t entries = bytes.getU32();
99
100 if (entries > 255)
101 ThrowFPE("Too many entries");
102
103 for (uint32_t i = 0; i < entries; i++) {
104 auto tag = static_cast<TiffTag>(bytes.getU16());
105 uint16_t length = bytes.getU16();
106
107 TiffDataType type;
108 switch (tag) {
109 using enum TiffTag;
114 // also 0x121?
115 type = TiffDataType::SHORT;
116 break;
117 default:
119 break;
120 }
121
122 uint32_t count = type == TiffDataType::SHORT ? length / 2 : length;
123 subIFD->add(std::make_unique<TiffEntry>(
124 subIFD.get(), tag, type, count,
125 bytes.getSubStream(bytes.getPosition(), length)));
126
127 bytes.skipBytes(length);
128 }
129 }
130
131 rootIFD->add(std::move(subIFD));
132}
133
134std::unique_ptr<RawDecoder> FiffParser::getDecoder(const CameraMetaData* meta) {
135 if (!rootIFD)
136 parseData();
137
138 // WARNING: do *NOT* fallback to ordinary TIFF parser here!
139 // All the FIFF raws are '.RAF' (Fujifilm). Do use RafDecoder directly.
140
141 try {
143 ThrowFPE("Not a FUJIFILM RAF FIFF.");
144
145 return std::make_unique<RafDecoder>(std::move(rootIFD), mInput);
146 } catch (const TiffParserException&) {
147 ThrowFPE("No decoder found. Sorry.");
148 }
149}
150
151} // namespace rawspeed
#define ThrowFPE(...)
ByteStream getSubStream(size_type offset, size_type size_) const
Definition ByteStream.h:54
void skipBytes(size_type nbytes)
Definition ByteStream.h:130
size_type getPosition() const
Definition ByteStream.h:78
TiffRootIFDOwner rootIFD
Definition FiffParser.h:34
std::unique_ptr< RawDecoder > getDecoder(const CameraMetaData *meta=nullptr) override
FiffParser(Buffer input)
static bool isAppropriateDecoder(const TiffRootIFD *rootIFD, Buffer file)
RawParser(Buffer inputData)
Definition RawParser.h:33
static TiffRootIFDOwner parse(TiffIFD *parent, Buffer data)
@ FUJI_RAWIMAGECROPPEDSIZE
Definition TiffTag.h:54
@ FUJI_RAWIMAGECROPTOPLEFT
Definition TiffTag.h:52