RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
KodakDecompressor.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 Pedro CĂ´rte-Real
6 Copyright (C) 2017 Roman Lebedev
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21*/
22
24#include "adt/Array2DRef.h"
25#include "adt/Bit.h"
26#include "adt/Casts.h"
27#include "adt/Invariant.h"
28#include "adt/Point.h"
30#include "common/RawImage.h"
32#include "io/Buffer.h"
33#include "io/ByteStream.h"
34#include <algorithm>
35#include <array>
36#include <cstddef>
37#include <cstdint>
38#include <utility>
39
40#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
41#include <sanitizer/common_interface_defs.h>
42#endif
43
44namespace rawspeed {
45
47 bool uncorrectedRawValues_)
48 : mRaw(std::move(img)), input(bs), bps(bps_),
49 uncorrectedRawValues(uncorrectedRawValues_) {
50 if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 ||
51 mRaw->getBpp() != sizeof(uint16_t))
52 ThrowRDE("Unexpected component count / data type");
53
54 if (!mRaw->dim.hasPositiveArea() || mRaw->dim.x % 4 != 0 ||
55 mRaw->dim.x > 4516 || mRaw->dim.y > 3012)
56 ThrowRDE("Unexpected image dimensions found: (%d; %d)", mRaw->dim.x,
57 mRaw->dim.y);
58
59 if (bps != 10 && bps != 12)
60 ThrowRDE("Unexpected bits per sample: %i", bps);
61
62 // Lower estimate: this decompressor requires *at least* half a byte
63 // per output pixel
64 (void)input.check(implicit_cast<Buffer::size_type>(mRaw->dim.area() / 2ULL));
65}
66
69 invariant(bsize > 0);
70 invariant(bsize % 4 == 0);
71 invariant(bsize <= segment_size);
72
73 segment out;
74 static_assert(out.size() == segment_size, "Wrong segment size");
75
76#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
77 // We are to produce only bsize pixels.
78 __sanitizer_annotate_contiguous_container(out.begin(), out.end(), out.end(),
79 &out[bsize]);
80#endif
81
82 std::array<uint8_t, 2 * segment_size> blen;
83 uint64_t bitbuf = 0;
84 uint32_t bits = 0;
85
86 for (uint32_t i = 0; i < bsize; i += 2) {
87 // One byte per two pixels
88 blen[i] = input.peekByte() & 15;
89 blen[i + 1] = input.getByte() >> 4;
90 }
91 if ((bsize & 7) == 4) {
92 bitbuf = (static_cast<uint64_t>(input.getByte())) << 8UL;
93 bitbuf += (static_cast<int>(input.getByte()));
94 bits = 16;
95 }
96 for (uint32_t i = 0; i < bsize; i++) {
97 uint32_t len = blen[i];
98 invariant(len < 16);
99
100 if (bits < len) {
101 for (uint32_t j = 0; j < 32; j += 8) {
102 bitbuf += static_cast<int64_t>(static_cast<int>(input.getByte()))
103 << (bits + (j ^ 8));
104 }
105 bits += 32;
106 }
107
108 uint32_t diff = static_cast<uint32_t>(bitbuf) &
109 extractHighBits(0xffffU, len, /*effectiveBitwidth=*/16);
110 bitbuf >>= len;
111 bits -= len;
112
113 out[i] = implicit_cast<int16_t>(
114 len != 0 ? PrefixCodeDecoder<>::extend(diff, len) : int(diff));
115 }
116
117 return out;
118}
119
121 const Array2DRef<uint16_t> out(mRaw->getU16DataAsUncroppedArray2DRef());
122
123 uint32_t random = 0;
124 for (int row = 0; row < out.height(); row++) {
125 for (int col = 0; col < out.width();) {
126 const int len = std::min(segment_size, mRaw->dim.x - col);
127
128 const segment buf = decodeSegment(len);
129
130 std::array<int, 2> pred;
131 pred.fill(0);
132
133 for (int i = 0; i < len; ++i, ++col) {
134 pred[i & 1] += buf[i];
135
136 int value = pred[i & 1];
137 if (!isIntN(value, bps))
138 ThrowRDE("Value out of bounds %d (bps = %i)", value, bps);
139
141 out(row, col) = implicit_cast<uint16_t>(value);
142 else {
143 mRaw->setWithLookUp(implicit_cast<uint16_t>(value),
144 reinterpret_cast<std::byte*>(&out(row, col)),
145 &random);
146 }
147 }
148 }
149 }
150}
151
152} // namespace rawspeed
#define invariant(expr)
Definition Invariant.h:27
#define ThrowRDE(...)
static int RAWSPEED_READNONE extend(uint32_t diff, uint32_t len)
int RAWSPEED_READONLY height() const
int RAWSPEED_READONLY width() const
KodakDecompressor(RawImage img, ByteStream bs, int bps, bool uncorrectedRawValues_)
segment decodeSegment(uint32_t bsize)
static constexpr int segment_size
std::array< int16_t, segment_size > segment
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
constexpr bool RAWSPEED_READNONE isIntN(T value, unsigned int nBits)
Definition Bit.h:87
void RAWSPEED_UNLIKELY_FUNCTION RAWSPEED_NOINLINE static char buf[bufSize]
constexpr RAWSPEED_READNONE T extractHighBits(T value, unsigned nBits, unsigned effectiveBitwidth=bitwidth< T >())
Definition Bit.h:120