RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
SrwDecoder.cpp
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2010 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/SrwDecoder.h"
23#include "adt/Point.h"
29#include "io/Buffer.h"
30#include "io/ByteStream.h"
31#include "io/Endianness.h"
32#include "metadata/Camera.h"
34#include "tiff/TiffEntry.h"
35#include "tiff/TiffIFD.h"
36#include "tiff/TiffTag.h"
37#include <array>
38#include <cstdint>
39#include <memory>
40#include <sstream>
41#include <string>
42#include <vector>
43
44namespace rawspeed {
45
47 [[maybe_unused]] Buffer file) {
48 const auto id = rootIFD->getID();
49 const std::string& make = id.make;
50
51 // FIXME: magic
52
53 return make == "SAMSUNG";
54}
55
57 const auto* raw = mRootIFD->getIFDWithTag(TiffTag::STRIPOFFSETS);
58
59 int compression = raw->getEntry(TiffTag::COMPRESSION)->getU32();
60 const int bits = raw->getEntry(TiffTag::BITSPERSAMPLE)->getU32();
61
62 if (12 != bits && 14 != bits)
63 ThrowRDE("Unsupported bits per sample");
64
65 if (32769 != compression && 32770 != compression && 32772 != compression &&
66 32773 != compression)
67 ThrowRDE("Unsupported compression");
68
69 if (uint32_t nslices = raw->getEntry(TiffTag::STRIPOFFSETS)->count;
70 nslices != 1)
71 ThrowRDE("Only one slice supported, found %u", nslices);
72
73 if (const auto wrongComp =
74 32770 == compression && !raw->hasEntry(static_cast<TiffTag>(40976));
75 32769 == compression || wrongComp) {
76 bool bit_order = hints.get("msb_override", wrongComp ? bits == 12 : false);
77 this->decodeUncompressed(raw, bit_order ? BitOrder::MSB : BitOrder::LSB);
78 return mRaw;
79 }
80
81 const uint32_t width = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32();
82 const uint32_t height = raw->getEntry(TiffTag::IMAGELENGTH)->getU32();
83 mRaw->dim = iPoint2D(width, height);
84
85 if (32770 == compression) {
86 const TiffEntry* sliceOffsets = raw->getEntry(static_cast<TiffTag>(40976));
87 if (sliceOffsets->type != TiffDataType::LONG || sliceOffsets->count != 1)
88 ThrowRDE("Entry 40976 is corrupt");
89
91 bso.skipBytes(sliceOffsets->getU32());
92 bso = bso.getStream(height, 4);
93
94 const uint32_t offset = raw->getEntry(TiffTag::STRIPOFFSETS)->getU32();
95 const uint32_t count = raw->getEntry(TiffTag::STRIPBYTECOUNTS)->getU32();
96 Buffer rbuf(mFile.getSubView(offset, count));
98
99 SamsungV0Decompressor s0(mRaw, bso, bsr);
100
101 mRaw->createData();
102
103 s0.decompress();
104
105 return mRaw;
106 }
107 if (32772 == compression) {
108 uint32_t offset = raw->getEntry(TiffTag::STRIPOFFSETS)->getU32();
109 uint32_t count = raw->getEntry(TiffTag::STRIPBYTECOUNTS)->getU32();
110 const ByteStream bs(
111 DataBuffer(mFile.getSubView(offset, count), Endianness::little));
112
113 SamsungV1Decompressor s1(mRaw, bs, bits);
114
115 mRaw->createData();
116
117 s1.decompress();
118
119 return mRaw;
120 }
121 if (32773 == compression) {
122 uint32_t offset = raw->getEntry(TiffTag::STRIPOFFSETS)->getU32();
123 uint32_t count = raw->getEntry(TiffTag::STRIPBYTECOUNTS)->getU32();
124 const ByteStream bs(
125 DataBuffer(mFile.getSubView(offset, count), Endianness::little));
126
127 SamsungV2Decompressor s2(mRaw, bs, bits);
128
129 mRaw->createData();
130
131 s2.decompress();
132
133 return mRaw;
134 }
135 ThrowRDE("Unsupported compression");
136}
137
138std::string SrwDecoder::getMode() const {
139 std::vector<const TiffIFD*> data =
140 mRootIFD->getIFDsWithTag(TiffTag::CFAPATTERN);
141 std::ostringstream mode;
142 if (!data.empty() && data[0]->hasEntryRecursive(TiffTag::BITSPERSAMPLE)) {
143 mode << data[0]->getEntryRecursive(TiffTag::BITSPERSAMPLE)->getU32()
144 << "bit";
145 return mode.str();
146 }
147 return "";
148}
149
151 auto id = mRootIFD->getID();
152 std::string mode = getMode();
153 if (meta->hasCamera(id.make, id.model, mode))
154 this->checkCameraSupported(meta, id, getMode());
155 else
156 this->checkCameraSupported(meta, id, "");
157}
158
160 int iso = 0;
161 if (mRootIFD->hasEntryRecursive(TiffTag::ISOSPEEDRATINGS))
162 iso = mRootIFD->getEntryRecursive(TiffTag::ISOSPEEDRATINGS)->getU32();
163
164 auto id = mRootIFD->getID();
165 if (std::string mode = getMode(); meta->hasCamera(id.make, id.model, mode))
166 setMetaData(meta, id, mode, iso);
167 else
168 setMetaData(meta, id, "", iso);
169
170 // Set the whitebalance
171 if (mRootIFD->hasEntryRecursive(TiffTag::SAMSUNG_WB_RGGBLEVELSUNCORRECTED) &&
172 mRootIFD->hasEntryRecursive(TiffTag::SAMSUNG_WB_RGGBLEVELSBLACK)) {
173 const TiffEntry* wb_levels =
175 const TiffEntry* wb_black =
177 if (wb_levels->count == 4 && wb_black->count == 4) {
178 std::array<float, 4> wbCoeffs = {};
179 wbCoeffs[0] = wb_levels->getFloat(0) - wb_black->getFloat(0);
180 wbCoeffs[1] = wb_levels->getFloat(1) - wb_black->getFloat(1);
181 wbCoeffs[2] = wb_levels->getFloat(3) - wb_black->getFloat(3);
182 mRaw->metadata.wbCoeffs = wbCoeffs;
183 }
184 }
185}
186
187} // namespace rawspeed
#define ThrowRDE(...)
bool checkCameraSupported(const CameraMetaData *meta, const TiffID &id, const std::string &mode)
void setMetaData(const CameraMetaData *meta, const TiffID &id, const std::string &mode, int iso_speed)
ByteStream getStream(size_type size_)
Definition ByteStream.h:119
void skipBytes(size_type nbytes)
Definition ByteStream.h:130
bool hasCamera(const std::string &make, const std::string &model, const std::string &mode) const
void decodeUncompressed(const TiffIFD *rawIFD, BitOrder order) const
void decodeMetaDataInternal(const CameraMetaData *meta) override
std::string getMode() const
static bool isAppropriateDecoder(const TiffRootIFD *rootIFD, Buffer file)
RawImage decodeRawInternal() override
void checkSupportInternal(const CameraMetaData *meta) override
Definition TiffEntry.h:62
float getFloat(uint32_t index=0) const
uint32_t getU32(uint32_t index=0) const
uint32_t count
Definition TiffEntry.h:84
TiffDataType type
Definition TiffEntry.h:83
TiffID getID() const
Definition TiffIFD.cpp:325
@ SAMSUNG_WB_RGGBLEVELSBLACK
Definition TiffTag.h:214
@ SAMSUNG_WB_RGGBLEVELSUNCORRECTED
Definition TiffTag.h:213
std::string make
Definition TiffIFD.h:134