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, TIFF_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

45 1
FiffParser::FiffParser(const Buffer* inputData) : RawParser(inputData) {}
46

47 1
void FiffParser::parseData() {
48 1
  ByteStream bs(DataBuffer(*mInput, Endianness::big));
49 1
  bs.skipBytes(0x54);
50

51 1
  uint32_t first_ifd = bs.getU32();
52 1
  if (first_ifd >= numeric_limits<uint32_t>::max() - 12)
53 0
    ThrowFPE("Not Fiff. First IFD too far away");
54

55 1
  first_ifd += 12;
56

57 1
  bs.skipBytes(4);
58 1
  const uint32_t third_ifd = bs.getU32();
59 1
  bs.skipBytes(4);
60 1
  const uint32_t second_ifd = bs.getU32();
61

62 1
  rootIFD = TiffParser::parse(nullptr, mInput->getSubView(first_ifd));
63 1
  TiffIFDOwner subIFD = std::make_unique<TiffIFD>(rootIFD.get());
64

65 1
  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 1
      rootIFD->add(
70 1
          TiffParser::parse(rootIFD.get(), mInput->getSubView(second_ifd)));
71 0
    } catch (TiffParserException&) {
72
      // the offset will be interpreted relative to the rootIFD where this
73
      // subIFD gets inserted
74

75 0
      if (second_ifd <= first_ifd)
76 0
        ThrowFPE("Fiff is corrupted: second IFD is not after the first IFD");
77

78 0
      uint32_t rawOffset = second_ifd - first_ifd;
79 0
      subIFD->add(std::make_unique<TiffEntry>(
80 0
          subIFD.get(), FUJI_STRIPOFFSETS, TIFF_OFFSET, 1,
81 0
          ByteStream::createCopy(&rawOffset, 4)));
82 0
      uint32_t max_size = mInput->getSize() - second_ifd;
83 0
      subIFD->add(std::make_unique<TiffEntry>(
84 0
          subIFD.get(), FUJI_STRIPBYTECOUNTS, TIFF_LONG, 1,
85 0
          ByteStream::createCopy(&max_size, 4)));
86
    }
87
  }
88

89 1
  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(
97 1
        DataBuffer(mInput->getSubView(third_ifd), Endianness::big));
98 1
    uint32_t entries = bytes.getU32();
99

100 1
    if (entries > 255)
101 0
      ThrowFPE("Too many entries");
102

103 1
    for (uint32_t i = 0; i < entries; i++) {
104 1
      uint16_t tag = bytes.getU16();
105 1
      uint16_t length = bytes.getU16();
106 1
      TiffDataType type = TIFF_UNDEFINED;
107

108 1
      if (tag == IMAGEWIDTH || tag == FUJIOLDWB) // also 0x121?
109 1
        type = TIFF_SHORT;
110

111 1
      uint32_t count = type == TIFF_SHORT ? length / 2 : length;
112 1
      subIFD->add(std::make_unique<TiffEntry>(
113 1
          subIFD.get(), static_cast<TiffTag>(tag), type, count,
114 1
          bytes.getSubStream(bytes.getPosition(), length)));
115

116 1
      bytes.skipBytes(length);
117
    }
118
  }
119

120 1
  rootIFD->add(move(subIFD));
121
}
122

123 1
std::unique_ptr<RawDecoder> FiffParser::getDecoder(const CameraMetaData* meta) {
124 1
  if (!rootIFD)
125 1
    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 1
    if (!RafDecoder::isAppropriateDecoder(rootIFD.get(), mInput))
132 0
      ThrowFPE("Not a FUJIFILM RAF FIFF.");
133

134 1
    return std::make_unique<RafDecoder>(std::move(rootIFD), mInput);
135 0
  } catch (TiffParserException&) {
136 0
    ThrowFPE("No decoder found. Sorry.");
137
  }
138
}
139

140
} // namespace rawspeed

Read our documentation on viewing source code .

Loading