RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
MosDecoder.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) 2014-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/MosDecoder.h"
23#include "adt/Casts.h"
24#include "adt/Point.h"
26#include "common/Common.h"
27#include "common/RawImage.h"
29#include "decoders/IiqDecoder.h"
30#include "decoders/RawDecoder.h"
33#include "io/Buffer.h"
34#include "io/ByteStream.h"
35#include "io/Endianness.h"
37#include "tiff/TiffEntry.h"
38#include "tiff/TiffIFD.h"
39#include "tiff/TiffTag.h"
40#include <array>
41#include <cassert>
42#include <cstdint>
43#include <cstring>
44#include <istream>
45#include <memory>
46#include <sstream>
47#include <string>
48#include <string_view>
49#include <utility>
50
51namespace rawspeed {
52
53class CameraMetaData;
54
56 try {
57 const auto id = rootIFD->getID();
58 const std::string& make = id.make;
59
60 // This is messy. see https://github.com/darktable-org/rawspeed/issues/116
61 // Old Leafs are MOS, new ones are IIQ. Use IIQ's magic to differentiate.
62 return make == "Leaf" && !IiqDecoder::isAppropriateDecoder(file);
63 } catch (const TiffParserException&) {
64 // Last ditch effort to identify Leaf cameras that don't have a Tiff Make
65 // set
66 const TiffEntry* softwareIFD =
68 if (!softwareIFD)
69 return false;
70
71 const std::string software = trimSpaces(softwareIFD->getString());
72 return software == "Camera Library";
73 }
74}
75
77 : AbstractTiffDecoder(std::move(rootIFD), file) {
78 if (mRootIFD->getEntryRecursive(TiffTag::MAKE)) {
79 auto id = mRootIFD->getID();
80 make = id.make;
81 model = id.model;
82 } else {
83 const TiffEntry* xmp = mRootIFD->getEntryRecursive(TiffTag::XMP);
84 if (!xmp)
85 ThrowRDE("Couldn't find the XMP");
86
87 assert(xmp != nullptr);
88 std::string xmpText = xmp->getString();
89 make = getXMPTag(xmpText, "Make");
90 model = getXMPTag(xmpText, "Model");
91 }
92}
93
94std::string MosDecoder::getXMPTag(std::string_view xmp, std::string_view tag) {
95 std::string::size_type start = xmp.find("<tiff:" + std::string(tag) + ">");
96 std::string::size_type end = xmp.find("</tiff:" + std::string(tag) + ">");
97 if (start == std::string::npos || end == std::string::npos || end <= start)
98 ThrowRDE("Couldn't find tag '%s' in the XMP", tag.data());
99 auto startlen = implicit_cast<int>(tag.size() + 7);
100 return std::string(xmp.substr(start + startlen, end - start - startlen));
101}
102
104 uint32_t off = 0;
105
106 const TiffIFD* raw = nullptr;
107
108 if (mRootIFD->hasEntryRecursive(TiffTag::TILEOFFSETS)) {
109 raw = mRootIFD->getIFDWithTag(TiffTag::TILEOFFSETS);
110 off = raw->getEntry(TiffTag::TILEOFFSETS)->getU32();
111 } else {
112 raw = mRootIFD->getIFDWithTag(TiffTag::CFAPATTERN);
114 }
115
118
119 // FIXME: could be wrong. max "active pixels" - "80 MP"
120 if (width == 0 || height == 0 || width > 10328 || height > 7760)
121 ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
122
123 mRaw->dim = iPoint2D(width, height);
124
125 const ByteStream bs(DataBuffer(mFile.getSubView(off), Endianness::little));
126 if (bs.getRemainSize() == 0)
127 ThrowRDE("Input buffer is empty");
128
129 if (int compression = raw->getEntry(TiffTag::COMPRESSION)->getU32();
130 1 == compression) {
131 const Endianness endianness =
134 bs, mRaw, iRectangle2D({0, 0}, iPoint2D(width, height)), 2 * width, 16,
136 mRaw->createData();
137 u.readUncompressedRaw();
138 } else if (99 == compression || 7 == compression) {
139 ThrowRDE("Leaf LJpeg not yet supported");
140 // LJpegPlain l(mFile, mRaw);
141 // l.startDecoder(off, mFile.getSize()-off, 0, 0);
142 } else {
143 ThrowRDE("Unsupported compression: %d", compression);
144 }
145
146 return mRaw;
147}
148
152
154 RawDecoder::setMetaData(meta, make, model, "", 0);
155
156 // Fetch the white balance (see dcraw.c parse_mos for more metadata that can
157 // be gotten)
158 if (mRootIFD->hasEntryRecursive(TiffTag::LEAFMETADATA)) {
159 ByteStream bs =
160 mRootIFD->getEntryRecursive(TiffTag::LEAFMETADATA)->getData();
161
162 // We need at least a couple of bytes:
163 // "NeutObj_neutrals" + 28 bytes binary + 4x uint as strings + 3x space + \0
164 const uint32_t minSize = 16 + 28 + 4 + 3 + 1;
165
166 // dcraw does actual parsing, since we just want one field we bruteforce it
167 while (bs.getRemainSize() > minSize) {
168 if (bs.skipPrefix("NeutObj_neutrals")) {
169 bs.skipBytes(28);
170 // check for nulltermination of string inside bounds
171 if (!memchr(bs.peekData(bs.getRemainSize()), 0, bs.getRemainSize()))
172 break;
173 std::array<uint32_t, 4> tmp = {{}};
174 const std::string tmpString(bs.peekString());
175 std::istringstream iss(tmpString);
176 iss >> tmp[0] >> tmp[1] >> tmp[2] >> tmp[3];
177 if (!iss.fail() && tmp[0] > 0 && tmp[1] > 0 && tmp[2] > 0 &&
178 tmp[3] > 0) {
179 std::array<float, 4> wbCoeffs = {};
180 wbCoeffs[0] =
181 static_cast<float>(tmp[0]) / implicit_cast<float>(tmp[1]);
182 wbCoeffs[1] =
183 static_cast<float>(tmp[0]) / implicit_cast<float>(tmp[2]);
184 wbCoeffs[2] =
185 static_cast<float>(tmp[0]) / implicit_cast<float>(tmp[3]);
186 mRaw->metadata.wbCoeffs = wbCoeffs;
187 }
188 break;
189 }
190 bs.skipBytes(1);
191 }
192 }
193}
194
195} // namespace rawspeed
#define ThrowRDE(...)
AbstractTiffDecoder(TiffRootIFDOwner &&root, Buffer file)
std::string_view peekString() const
Definition ByteStream.h:199
size_type RAWSPEED_READONLY getRemainSize() const
Definition ByteStream.h:87
void skipBytes(size_type nbytes)
Definition ByteStream.h:130
const uint8_t * peekData(size_type count) const
Definition ByteStream.h:92
bool skipPrefix(std::string_view prefix)
Definition ByteStream.h:149
static bool isAppropriateDecoder(Buffer file)
MosDecoder(TiffRootIFDOwner &&rootIFD, Buffer file)
static std::string getXMPTag(std::string_view xmp, std::string_view tag)
void checkSupportInternal(const CameraMetaData *meta) override
static bool isAppropriateDecoder(const TiffRootIFD *rootIFD, Buffer file)
void decodeMetaDataInternal(const CameraMetaData *meta) override
RawImage decodeRawInternal() override
std::string model
Definition MosDecoder.h:47
virtual void setMetaData(const CameraMetaData *meta, const std::string &make, const std::string &model, const std::string &mode, int iso_speed=0)
bool checkCameraSupported(const CameraMetaData *meta, const std::string &make, const std::string &model, const std::string &mode)
Definition TiffEntry.h:62
uint32_t getU32(uint32_t index=0) const
std::string getString() const
TiffEntry *RAWSPEED_READONLY getEntryRecursive(TiffTag tag) const
Definition TiffIFD.cpp:246
TiffEntry * getEntry(TiffTag tag) const
Definition TiffIFD.cpp:313
TiffID getID() const
Definition TiffIFD.cpp:325
std::string trimSpaces(std::string_view str)
Definition Common.h:163
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
std::unique_ptr< TiffRootIFD > TiffRootIFDOwner
Definition TiffIFD.h:46
Endianness getTiffByteOrder(ByteStream bs, uint32_t pos, const char *context="")
Definition TiffIFD.h:153