RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
DeflateDecompressor.cpp
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2017 Vasily Khoruzhick
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19*/
20
21#include "rawspeedconfig.h" // IWYU pragma: keep
22#include <bit>
23
24#ifdef HAVE_ZLIB
25
26#include "adt/Array1DRef.h"
27#include "adt/Array2DRef.h"
28#include "adt/Casts.h"
31#include "adt/Invariant.h"
32#include "adt/Point.h"
34#include "common/RawImage.h"
37#include "io/Buffer.h"
38#include "io/Endianness.h"
39#include <array>
40#include <climits>
41#include <cstdint>
42#include <memory>
43#include <utility>
44#include <zconf.h>
45#include <zlib.h>
46
47namespace rawspeed {
48
49DeflateDecompressor::DeflateDecompressor(Buffer bs, RawImage img, int predictor,
50 int bps_)
51 : input(bs), mRaw(std::move(img)), bps(bps_) {
52 switch (predictor) {
53 case 3:
54 predFactor = 1;
55 break;
56 case 34894:
57 predFactor = 2;
58 break;
59 case 34895:
60 predFactor = 4;
61 break;
62 default:
63 ThrowRDE("Unsupported predictor %i", predictor);
64 }
65 predFactor *= mRaw->getCpp();
66}
67
68namespace {
69
70// decodeFPDeltaRow(): MIT License, copyright 2014 Javier Celaya
71// <jcelaya@gmail.com>
72inline void decodeDeltaBytes(Array1DRef<unsigned char> src, int realTileWidth,
73 int bytesps, int factor) {
74 for (int col = factor; col < realTileWidth * bytesps; ++col) {
75 // Yes, this is correct, and is symmetrical with EncodeDeltaBytes in
76 // hdrmerge, and they both combined are lossless.
77 // This is indeed working in modulo-2^n arighmetics.
78 src(col) = static_cast<unsigned char>(src(col) + src(col - factor));
79 }
80}
81
82} // namespace
83
84template <typename T> struct StorageType final {};
85template <> struct StorageType<ieee_754_2008::Binary16> {
86 using type = uint16_t;
87 static constexpr int padding_bytes = 0;
88};
89template <> struct StorageType<ieee_754_2008::Binary24> {
90 using type = uint32_t;
91 static constexpr int padding_bytes = 1;
92};
93template <> struct StorageType<ieee_754_2008::Binary32> {
94 using type = uint32_t;
95 static constexpr int padding_bytes = 0;
96};
97
98namespace {
99
100template <typename T>
101inline void decodeFPDeltaRow(Array1DRef<const unsigned char> src,
102 int realTileWidth, CroppedArray1DRef<float> out) {
103 using storage_type = typename StorageType<T>::type;
104 constexpr unsigned storage_bytes = sizeof(storage_type);
105 constexpr unsigned bytesps = T::StorageWidth / 8;
106
107 for (int col = 0; col < out.size(); ++col) {
108 std::array<unsigned char, storage_bytes> bytes;
109 for (int c = 0; c != bytesps; ++c)
110 bytes[c] = src(col + (c * realTileWidth));
111
112 auto tmp = getBE<storage_type>(bytes.data());
113 tmp >>= CHAR_BIT * StorageType<T>::padding_bytes;
114
115 uint32_t tmp_expanded;
116 switch (bytesps) {
117 case 2:
118 case 3:
119 tmp_expanded = extendBinaryFloatingPoint<T, ieee_754_2008::Binary32>(tmp);
120 break;
121 case 4:
122 tmp_expanded = tmp;
123 break;
124 default:
125 __builtin_unreachable();
126 }
127
128 out(col) = std::bit_cast<float>(tmp_expanded);
129 }
130}
131
132} // namespace
133
134// NOLINTNEXTLINE(modernize-avoid-c-arrays)
135void DeflateDecompressor::decode(std::unique_ptr<unsigned char[]>* uBuffer,
136 iPoint2D maxDim, iPoint2D dim, iPoint2D off) {
137 int bytesps = bps / 8;
138 invariant(bytesps >= 2 && bytesps <= 4);
139
140 auto dstLen = implicit_cast<uLongf>(bytesps * maxDim.area());
141
142 if (!*uBuffer) {
143 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
144 *uBuffer = std::unique_ptr<unsigned char[]>(new unsigned char[dstLen]);
145 }
146
147 Array2DRef<unsigned char> tmp(uBuffer->get(), bytesps * maxDim.x, maxDim.y);
148
149 if (int err =
150 uncompress(uBuffer->get(), &dstLen, input.begin(), input.getSize());
151 err != Z_OK) {
152 ThrowRDE("failed to uncompress tile: %d (%s)", err, zError(err));
153 }
154
155 const auto out = CroppedArray2DRef(
156 mRaw->getF32DataAsUncroppedArray2DRef(), /*offsetCols=*/off.x,
157 /*offsetRows=*/off.y, /*croppedWidth=*/dim.x, /*croppedHeight=*/dim.y);
158
159 for (int row = 0; row < out.croppedHeight; ++row) {
160 decodeDeltaBytes(tmp[row], maxDim.x, bytesps, predFactor);
161
162 switch (bytesps) {
163 case 2:
164 decodeFPDeltaRow<ieee_754_2008::Binary16>(tmp[row], maxDim.x, out[row]);
165 break;
166 case 3:
167 decodeFPDeltaRow<ieee_754_2008::Binary24>(tmp[row], maxDim.x, out[row]);
168 break;
169 case 4:
170 decodeFPDeltaRow<ieee_754_2008::Binary32>(tmp[row], maxDim.x, out[row]);
171 break;
172 default:
173 __builtin_unreachable();
174 }
175 }
176}
177
178} // namespace rawspeed
179
180#else
181
182#pragma message \
183 "ZLIB is not present! Deflate compression will not be supported!"
184
185#endif
T getBE(const void *data)
Definition Endianness.h:116
#define invariant(expr)
Definition Invariant.h:27
#define ThrowRDE(...)
iPoint2D dim(rawspeed::implicit_cast< int >(ceil(sqSide *sqARatio)), rawspeed::implicit_cast< int >(ceil(sqSide/sqARatio)))
Definition Common.cpp:55
value_type x
Definition Point.h:102
value_type y
Definition Point.h:103
area_type RAWSPEED_READONLY area() const
Definition Point.h:81
CroppedArray2DRef(Array2DRef< T > base_, int offsetCols_, int offsetRows_, int croppedWidth_, int croppedHeight_) -> CroppedArray2DRef< typename Array2DRef< T >::value_type >
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32