RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
AbstractDngDecompressor.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-2018 Roman Lebeedv
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 "rawspeedconfig.h"
24#include "adt/Array1DRef.h"
25#include "adt/Casts.h"
26#include "adt/Invariant.h"
27#include "adt/Point.h"
29#include "common/Common.h"
30#include "common/RawImage.h"
35#include "io/ByteStream.h"
36#include "io/Endianness.h"
37#include "io/IOException.h"
38#include <cstdint>
39#include <limits>
40#include <string>
41#include <vector>
42
43#ifdef HAVE_ZLIB
45#include <memory>
46#endif
47
48#ifdef HAVE_JPEG
50#endif
51
52namespace rawspeed {
53
54template <> void AbstractDngDecompressor::decompressThread<1>() const noexcept {
55#ifdef HAVE_OPENMP
56#pragma omp for schedule(static)
57#endif
58 for (const auto& e :
59 Array1DRef(slices.data(), implicit_cast<int>(slices.size()))) {
60 try {
61 iPoint2D tileSize(e.width, e.height);
62 iPoint2D pos(e.offX, e.offY);
63
64 bool big_endian = e.bs.getByteOrder() == Endianness::big;
65
66 // DNG spec says that if not 8/16/32 bit/sample, always use big endian.
67 // It's not very obvious, but that does not appear to apply to FP.
68 switch (mBps) {
69 case 8:
70 case 16:
71 case 32:
72 break;
73 default:
74 if (mRaw->getDataType() == RawImageType::UINT16)
75 big_endian = true;
76 break;
77 }
78
79 const uint32_t inputPixelBits = mRaw->getCpp() * mBps;
80
81 if (e.dsc.tileW > std::numeric_limits<int>::max() / inputPixelBits)
82 ThrowIOE("Integer overflow when calculating input pitch");
83
84 const int inputPitchBits = inputPixelBits * e.dsc.tileW;
85 invariant(inputPitchBits > 0);
86
87 if (inputPitchBits % 8 != 0) {
88 ThrowRDE("Bad combination of cpp (%u), bps (%u) and width (%u), the "
89 "pitch is %d bits, which is not a multiple of 8 (1 byte)",
90 mRaw->getCpp(), mBps, e.width, inputPitchBits);
91 }
92
93 const int inputPitch = inputPitchBits / 8;
94 if (inputPitch == 0)
95 ThrowRDE("Data input pitch is too short. Can not decode!");
96
97 UncompressedDecompressor decompressor(
98 e.bs, mRaw, iRectangle2D(pos, tileSize), inputPitch, mBps,
99 big_endian ? BitOrder::MSB : BitOrder::LSB);
100 decompressor.readUncompressedRaw();
101 } catch (const RawDecoderException& err) {
102 mRaw->setError(err.what());
103 } catch (const IOException& err) {
104 mRaw->setError(err.what());
105 } catch (...) {
106 // We should not get any other exception type here.
107 __builtin_unreachable();
108 }
109 }
110}
111
112template <> void AbstractDngDecompressor::decompressThread<7>() const noexcept {
113#ifdef HAVE_OPENMP
114#pragma omp for schedule(static)
115#endif
116 for (const auto& e :
117 Array1DRef(slices.data(), implicit_cast<int>(slices.size()))) {
118 try {
119 LJpegDecoder d(e.bs, mRaw);
120 d.decode(e.offX, e.offY, e.width, e.height,
121 iPoint2D(e.dsc.tileW, e.dsc.tileH), mFixLjpeg);
122 } catch (const RawDecoderException& err) {
123 mRaw->setError(err.what());
124 } catch (const IOException& err) {
125 mRaw->setError(err.what());
126 } catch (...) {
127 // We should not get any other exception type here.
128 __builtin_unreachable();
129 }
130 }
131}
132
133#ifdef HAVE_ZLIB
134template <> void AbstractDngDecompressor::decompressThread<8>() const noexcept {
135 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
136 std::unique_ptr<unsigned char[]> uBuffer;
137
138#ifdef HAVE_OPENMP
139#pragma omp for schedule(static)
140#endif
141 for (const auto& e :
142 Array1DRef(slices.data(), implicit_cast<int>(slices.size()))) {
143 try {
144 DeflateDecompressor z(e.bs.peekBuffer(e.bs.getRemainSize()), mRaw,
146 z.decode(&uBuffer, iPoint2D(mRaw->getCpp() * e.dsc.tileW, e.dsc.tileH),
147 iPoint2D(mRaw->getCpp() * e.width, e.height),
148 iPoint2D(mRaw->getCpp() * e.offX, e.offY));
149 } catch (const RawDecoderException& err) {
150 mRaw->setError(err.what());
151 } catch (const IOException& err) {
152 mRaw->setError(err.what());
153 } catch (...) {
154 // We should not get any other exception type here.
155 __builtin_unreachable();
156 }
157 }
158}
159#endif
160
161template <> void AbstractDngDecompressor::decompressThread<9>() const noexcept {
162#ifdef HAVE_OPENMP
163#pragma omp for schedule(static)
164#endif
165 for (const auto& e :
166 Array1DRef(slices.data(), implicit_cast<int>(slices.size()))) {
167 try {
168 VC5Decompressor d(e.bs, mRaw);
169 d.decode(e.offX, e.offY, e.width, e.height);
170 } catch (const RawDecoderException& err) {
171 mRaw->setError(err.what());
172 } catch (const IOException& err) {
173 mRaw->setError(err.what());
174 } catch (...) {
175 // We should not get any other exception type here.
176 __builtin_unreachable();
177 }
178 }
179}
180
181#ifdef HAVE_JPEG
182template <>
184#ifdef HAVE_OPENMP
185#pragma omp for schedule(static)
186#endif
187 for (const auto& e :
188 Array1DRef(slices.data(), implicit_cast<int>(slices.size()))) {
189 try {
190 JpegDecompressor j(e.bs.peekBuffer(e.bs.getRemainSize()), mRaw);
191 j.decode(e.offX, e.offY);
192 } catch (const RawDecoderException& err) {
193 mRaw->setError(err.what());
194 } catch (const IOException& err) {
195 mRaw->setError(err.what());
196 } catch (...) {
197 // We should not get any other exception type here.
198 __builtin_unreachable();
199 }
200 }
201}
202#endif
203
205 invariant(mRaw->dim.x > 0);
206 invariant(mRaw->dim.y > 0);
207 invariant(mRaw->getCpp() > 0 && mRaw->getCpp() <= 4);
208 invariant(mBps > 0 && mBps <= 32);
209
210 if (compression == 1) {
211 /* Uncompressed */
213 } else if (compression == 7) {
214 /* Lossless JPEG */
216 } else if (compression == 8) {
217 /* Deflate compression */
218#ifdef HAVE_ZLIB
220#else
221#pragma message \
222 "ZLIB is not present! Deflate compression will not be supported!"
223 mRaw->setError("deflate support is disabled.");
224#endif
225 } else if (compression == 9) {
226 /* GOPRO VC-5 */
228 } else if (compression == 0x884c) {
229 /* Lossy DNG */
230#ifdef HAVE_JPEG
232#else
233#pragma message "JPEG is not present! Lossy JPEG DNG will not be supported!"
234 mRaw->setError("jpeg support is disabled.");
235#endif
236 } else {
237 mRaw->setError("AbstractDngDecompressor: Unknown compression");
238 }
239}
240
242#ifdef HAVE_OPENMP
243#pragma omp parallel default(none) num_threads( \
244 rawspeed_get_number_of_processor_cores()) if (slices.size() > 1)
245#endif
247
248 std::string firstErr;
249 if (mRaw->isTooManyErrors(1, &firstErr)) {
250 ThrowRDE("Too many errors encountered. Giving up. First Error:\n%s",
251 firstErr.c_str());
252 }
253}
254
255} // namespace rawspeed
#define ThrowIOE(...)
Definition IOException.h:37
#define invariant(expr)
Definition Invariant.h:27
#define ThrowRDE(...)
std::vector< DngSliceElement > slices
void decompressThread() const noexcept
void setError(const std::string &err) REQUIRES(!mutex)
Definition ErrorLog.cpp:29
void decode(uint32_t offsetX, uint32_t offsetY, uint32_t width, uint32_t height, iPoint2D maxDim, bool fixDng16Bug_)
uint32_t RAWSPEED_READONLY getCpp() const
Definition RawImage.h:118
void decode(unsigned int offsetX, unsigned int offsetY, unsigned int width, unsigned int height)
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
Array1DRef(T *data_, int numElts_) -> Array1DRef< T >