"Fossies" - the Fresh Open Source Software Archive 
Member "darktable-2.6.3/src/external/rawspeed/src/librawspeed/decoders/RawDecoder.cpp" (19 Oct 2019, 10581 Bytes) of package /linux/misc/darktable-2.6.3.tar.xz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "RawDecoder.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.6.2_vs_2.6.3.
1 /*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5 Copyright (C) 2014 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/RawDecoder.h"
23 #include "common/Common.h" // for uint32_t, roundUpD...
24 #include "common/Point.h" // for iPoint2D, iRecta...
25 #include "decoders/RawDecoderException.h" // for ThrowRDE
26 #include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
27 #include "io/Buffer.h" // for Buffer
28 #include "io/FileIOException.h" // for FileIOException
29 #include "io/IOException.h" // for IOException
30 #include "metadata/BlackArea.h" // for BlackArea
31 #include "metadata/Camera.h" // for Camera, Hints
32 #include "metadata/CameraMetaData.h" // for CameraMetaData
33 #include "metadata/CameraSensorInfo.h" // for CameraSensorInfo
34 #include "metadata/ColorFilterArray.h" // for ColorFilterArray
35 #include "parsers/TiffParserException.h" // for TiffParserException
36 #include "tiff/TiffEntry.h" // for TiffEntry
37 #include "tiff/TiffIFD.h" // for TiffIFD
38 #include "tiff/TiffTag.h" // for BITSPERSAMPLE
39 #include <array> // for array
40 #include <cassert> // for assert
41 #include <string> // for string, basic_st...
42 #include <vector> // for vector
43
44 using std::vector;
45 using std::string;
46
47 namespace rawspeed {
48
49 RawDecoder::RawDecoder(const Buffer* file)
50 : mRaw(RawImage::create()), mFile(file) {
51 failOnUnknown = false;
52 interpolateBadPixels = true;
53 applyStage1DngOpcodes = true;
54 applyCrop = true;
55 uncorrectedRawValues = false;
56 fujiRotate = true;
57 }
58
59 void RawDecoder::decodeUncompressed(const TiffIFD *rawIFD, BitOrder order) {
60 TiffEntry *offsets = rawIFD->getEntry(STRIPOFFSETS);
61 TiffEntry *counts = rawIFD->getEntry(STRIPBYTECOUNTS);
62 uint32_t yPerSlice = rawIFD->getEntry(ROWSPERSTRIP)->getU32();
63 uint32_t width = rawIFD->getEntry(IMAGEWIDTH)->getU32();
64 uint32_t height = rawIFD->getEntry(IMAGELENGTH)->getU32();
65 uint32_t bitPerPixel = rawIFD->getEntry(BITSPERSAMPLE)->getU32();
66
67 if (width == 0 || height == 0 || width > 5632 || height > 3720)
68 ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
69
70 mRaw->dim = iPoint2D(width, height);
71
72 if (counts->count != offsets->count) {
73 ThrowRDE("Byte count number does not match strip size: "
74 "count:%u, stips:%u ",
75 counts->count, offsets->count);
76 }
77
78 if (yPerSlice == 0 || yPerSlice > static_cast<uint32_t>(mRaw->dim.y) ||
79 roundUpDivision(mRaw->dim.y, yPerSlice) != counts->count) {
80 ThrowRDE("Invalid y per slice %u or strip count %u (height = %u)",
81 yPerSlice, counts->count, mRaw->dim.y);
82 }
83
84 switch (bitPerPixel) {
85 case 12:
86 case 14:
87 break;
88 default:
89 ThrowRDE("Unexpected bits per pixel: %u.", bitPerPixel);
90 }
91
92 vector<RawSlice> slices;
93 slices.reserve(counts->count);
94 uint32_t offY = 0;
95
96 for (uint32_t s = 0; s < counts->count; s++) {
97 RawSlice slice;
98 slice.offset = offsets->getU32(s);
99 slice.count = counts->getU32(s);
100
101 if (slice.count < 1)
102 ThrowRDE("Slice %u is empty", s);
103
104 if (offY + yPerSlice > height)
105 slice.h = height - offY;
106 else
107 slice.h = yPerSlice;
108
109 offY += yPerSlice;
110
111 if (!mFile->isValid(slice.offset, slice.count))
112 ThrowRDE("Slice offset/count invalid");
113
114 slices.push_back(slice);
115 }
116
117 if (slices.empty())
118 ThrowRDE("No valid slices found. File probably truncated.");
119
120 assert(height <= offY);
121 assert(slices.size() == counts->count);
122
123 mRaw->createData();
124
125 // Default white level is (2 ** BitsPerSample) - 1
126 mRaw->whitePoint = (1UL << bitPerPixel) - 1UL;
127
128 offY = 0;
129 for (const RawSlice& slice : slices) {
130 UncompressedDecompressor u(
131 ByteStream(DataBuffer(mFile->getSubView(slice.offset, slice.count),
132 Endianness::little)),
133 mRaw);
134 iPoint2D size(width, slice.h);
135 iPoint2D pos(0, offY);
136 bitPerPixel = static_cast<int>(
137 static_cast<uint64_t>(static_cast<uint64_t>(slice.count) * 8U) /
138 (slice.h * width));
139 const auto inputPitch = width * bitPerPixel / 8;
140 if (!inputPitch)
141 ThrowRDE("Bad input pitch. Can not decode anything.");
142
143 u.readUncompressedRaw(size, pos, inputPitch, bitPerPixel, order);
144
145 offY += slice.h;
146 }
147 }
148
149 void RawDecoder::askForSamples(const CameraMetaData* meta, const string& make,
150 const string& model, const string& mode) {
151 if ("dng" == mode)
152 return;
153
154 writeLog(DEBUG_PRIO_WARNING,
155 "Unable to find camera in database: '%s' '%s' "
156 "'%s'\nPlease consider providing samples on "
157 "<https://raw.pixls.us/>, thanks!",
158 make.c_str(), model.c_str(), mode.c_str());
159 }
160
161 bool RawDecoder::checkCameraSupported(const CameraMetaData* meta,
162 const string& make, const string& model,
163 const string& mode) {
164 mRaw->metadata.make = make;
165 mRaw->metadata.model = model;
166 const Camera* cam = meta->getCamera(make, model, mode);
167 if (!cam) {
168 askForSamples(meta, make, model, mode);
169
170 if (failOnUnknown)
171 ThrowRDE("Camera '%s' '%s', mode '%s' not supported, and not allowed to guess. Sorry.", make.c_str(), model.c_str(), mode.c_str());
172
173 // Assume the camera can be decoded, but return false, so decoders can see that we are unsure.
174 return false;
175 }
176
177 if (!cam->supported)
178 ThrowRDE("Camera not supported (explicit). Sorry.");
179
180 if (cam->decoderVersion > getDecoderVersion())
181 ThrowRDE("Camera not supported in this version. Update RawSpeed for support.");
182
183 hints = cam->hints;
184 return true;
185 }
186
187 void RawDecoder::setMetaData(const CameraMetaData* meta, const string& make,
188 const string& model, const string& mode,
189 int iso_speed) {
190 mRaw->metadata.isoSpeed = iso_speed;
191 const Camera* cam = meta->getCamera(make, model, mode);
192 if (!cam) {
193 askForSamples(meta, make, model, mode);
194
195 if (failOnUnknown)
196 ThrowRDE("Camera '%s' '%s', mode '%s' not supported, and not allowed to guess. Sorry.", make.c_str(), model.c_str(), mode.c_str());
197
198 return;
199 }
200
201 // Only override CFA with the data from cameras.xml if it actually contained
202 // the CFA.
203 if (cam->cfa.getSize().area() > 0)
204 mRaw->cfa = cam->cfa;
205
206 mRaw->metadata.canonical_make = cam->canonical_make;
207 mRaw->metadata.canonical_model = cam->canonical_model;
208 mRaw->metadata.canonical_alias = cam->canonical_alias;
209 mRaw->metadata.canonical_id = cam->canonical_id;
210 mRaw->metadata.make = make;
211 mRaw->metadata.model = model;
212 mRaw->metadata.mode = mode;
213
214 if (applyCrop) {
215 iPoint2D new_size = cam->cropSize;
216
217 // If crop size is negative, use relative cropping
218 if (new_size.x <= 0)
219 new_size.x = mRaw->dim.x - cam->cropPos.x + new_size.x;
220
221 if (new_size.y <= 0)
222 new_size.y = mRaw->dim.y - cam->cropPos.y + new_size.y;
223
224 mRaw->subFrame(iRectangle2D(cam->cropPos, new_size));
225 }
226
227 const CameraSensorInfo *sensor = cam->getSensorInfo(iso_speed);
228 mRaw->blackLevel = sensor->mBlackLevel;
229 mRaw->whitePoint = sensor->mWhiteLevel;
230 mRaw->blackAreas = cam->blackAreas;
231 if (mRaw->blackAreas.empty() && !sensor->mBlackLevelSeparate.empty()) {
232 auto cfaArea = mRaw->cfa.getSize().area();
233 if (mRaw->isCFA && cfaArea <= sensor->mBlackLevelSeparate.size()) {
234 for (auto i = 0UL; i < cfaArea; i++) {
235 mRaw->blackLevelSeparate[i] = sensor->mBlackLevelSeparate[i];
236 }
237 } else if (!mRaw->isCFA && mRaw->getCpp() <= sensor->mBlackLevelSeparate.size()) {
238 for (uint32_t i = 0; i < mRaw->getCpp(); i++) {
239 mRaw->blackLevelSeparate[i] = sensor->mBlackLevelSeparate[i];
240 }
241 }
242 }
243
244 // Allow overriding individual blacklevels. Values are in CFA order
245 // (the same order as the in the CFA tag)
246 // A hint could be:
247 // <Hint name="override_cfa_black" value="10,20,30,20"/>
248 string cfa_black = hints.get("override_cfa_black", string());
249 if (!cfa_black.empty()) {
250 vector<string> v = splitString(cfa_black, ',');
251 if (v.size() != 4) {
252 mRaw->setError("Expected 4 values '10,20,30,20' as values for override_cfa_black hint.");
253 } else {
254 for (int i = 0; i < 4; i++) {
255 mRaw->blackLevelSeparate[i] = stoi(v[i]);
256 }
257 }
258 }
259 }
260
261 rawspeed::RawImage RawDecoder::decodeRaw() {
262 try {
263 RawImage raw = decodeRawInternal();
264 raw->checkMemIsInitialized();
265
266 raw->metadata.pixelAspectRatio =
267 hints.get("pixel_aspect_ratio", raw->metadata.pixelAspectRatio);
268 if (interpolateBadPixels) {
269 raw->fixBadPixels();
270 raw->checkMemIsInitialized();
271 }
272
273 return raw;
274 } catch (TiffParserException &e) {
275 ThrowRDE("%s", e.what());
276 } catch (FileIOException &e) {
277 ThrowRDE("%s", e.what());
278 } catch (IOException &e) {
279 ThrowRDE("%s", e.what());
280 }
281 }
282
283 void RawDecoder::decodeMetaData(const CameraMetaData* meta) {
284 try {
285 decodeMetaDataInternal(meta);
286 } catch (TiffParserException &e) {
287 ThrowRDE("%s", e.what());
288 } catch (FileIOException &e) {
289 ThrowRDE("%s", e.what());
290 } catch (IOException &e) {
291 ThrowRDE("%s", e.what());
292 }
293 }
294
295 void RawDecoder::checkSupport(const CameraMetaData* meta) {
296 try {
297 checkSupportInternal(meta);
298 } catch (TiffParserException &e) {
299 ThrowRDE("%s", e.what());
300 } catch (FileIOException &e) {
301 ThrowRDE("%s", e.what());
302 } catch (IOException &e) {
303 ThrowRDE("%s", e.what());
304 }
305 }
306
307 } // namespace rawspeed