Coverage Report

Created: 2024-05-21 06:23

/src/librawspeed/src/librawspeed/decompressors/PentaxDecompressor.cpp
Line
Count
Source
1
/*
2
    RawSpeed - RAW file decoder.
3
4
    Copyright (C) 2009-2014 Klaus Post
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 "decompressors/PentaxDecompressor.h"
22
#include "adt/Array1DRef.h"
23
#include "adt/Array2DRef.h"
24
#include "adt/Bit.h"
25
#include "adt/Casts.h"
26
#include "adt/Invariant.h"
27
#include "adt/Optional.h"
28
#include "adt/Point.h"
29
#include "bitstreams/BitStreamerMSB.h"
30
#include "codes/AbstractPrefixCode.h"
31
#include "codes/HuffmanCode.h"
32
#include "codes/PrefixCodeDecoder.h"
33
#include "common/RawImage.h"
34
#include "decoders/RawDecoderException.h"
35
#include "io/Buffer.h"
36
#include "io/ByteStream.h"
37
#include <array>
38
#include <cassert>
39
#include <cstdint>
40
#include <utility>
41
#include <vector>
42
43
namespace rawspeed {
44
45
// 16 entries of codes per bit length
46
// 13 entries of code values
47
const std::array<std::array<std::array<uint8_t, 16>, 2>, 1>
48
    PentaxDecompressor::pentax_tree = {{
49
        {{{0, 2, 3, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
50
          {3, 4, 2, 5, 1, 6, 0, 7, 8, 9, 10, 11, 12}}},
51
    }};
52
53
PentaxDecompressor::PentaxDecompressor(RawImage img,
54
                                       Optional<ByteStream> metaData)
55
1.70k
    : mRaw(std::move(img)), ht(SetupPrefixCodeDecoder(metaData)) {
56
1.70k
  if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 ||
57
1.70k
      mRaw->getBpp() != sizeof(uint16_t))
58
1.70k
    ThrowRDE("Unexpected component count / data type");
59
60
1.69k
  if (!mRaw->dim.x || !mRaw->dim.y || mRaw->dim.x % 2 != 0 ||
61
1.69k
      mRaw->dim.x > 8384 || mRaw->dim.y > 6208) {
62
93
    ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
63
93
             mRaw->dim.y);
64
93
  }
65
1.69k
}
66
67
HuffmanCode<BaselineCodeTag>
68
1.18k
PentaxDecompressor::SetupPrefixCodeDecoder_Legacy() {
69
  // Temporary table, used during parsing LJpeg.
70
1.18k
  HuffmanCode<BaselineCodeTag> hc;
71
72
  /* Initialize with legacy data */
73
1.18k
  auto nCodes = hc.setNCodesPerLength(Buffer(pentax_tree[0][0].data(), 16));
74
1.18k
  invariant(nCodes == 13); // see pentax_tree definition
75
1.18k
  hc.setCodeValues(Array1DRef<const uint8_t>(pentax_tree[0][1].data(), nCodes));
76
77
1.18k
  return hc;
78
1.18k
}
79
80
HuffmanCode<BaselineCodeTag>
81
526
PentaxDecompressor::SetupPrefixCodeDecoder_Modern(ByteStream stream) {
82
  // Temporary table, used during parsing LJpeg.
83
526
  HuffmanCode<BaselineCodeTag> hc;
84
85
526
  const uint32_t depth = stream.getU16() + 12;
86
526
  if (depth > 15)
87
526
    ThrowRDE("Depth of huffman table is too great (%u).", depth);
88
89
482
  stream.skipBytes(12);
90
91
482
  std::array<uint32_t, 16> v0;
92
482
  std::array<uint32_t, 16> v1;
93
6.18k
  for (uint32_t i = 0; i < depth; i++)
94
5.70k
    v0[i] = stream.getU16();
95
5.29k
  for (uint32_t i = 0; i < depth; i++) {
96
4.86k
    v1[i] = stream.getByte();
97
98
4.86k
    if (v1[i] == 0 || v1[i] > 12)
99
4.86k
      ThrowRDE("Data corrupt: v1[%i]=%i, expected [1..12]", depth, v1[i]);
100
4.86k
  }
101
102
426
  std::vector<uint8_t> nCodesPerLength;
103
426
  nCodesPerLength.resize(17);
104
105
426
  std::array<uint32_t, 16> v2;
106
  /* Calculate codes and store bitcounts */
107
5.00k
  for (uint32_t c = 0; c < depth; c++) {
108
4.57k
    v2[c] = extractHighBits(v0[c], v1[c], /*effectiveBitwidth=*/12);
109
4.57k
    nCodesPerLength.at(v1[c])++;
110
4.57k
  }
111
112
426
  assert(nCodesPerLength.size() == 17);
113
367
  assert(nCodesPerLength[0] == 0);
114
367
  auto nCodes = hc.setNCodesPerLength(Buffer(&nCodesPerLength[1], 16));
115
367
  invariant(nCodes == depth);
116
117
352
  std::vector<uint8_t> codeValues;
118
352
  codeValues.reserve(nCodes);
119
120
  /* Find smallest */
121
4.74k
  for (uint32_t i = 0; i < depth; i++) {
122
4.39k
    uint32_t sm_val = 0xfffffff;
123
4.39k
    uint32_t sm_num = 0xff;
124
59.4k
    for (uint32_t j = 0; j < depth; j++) {
125
55.0k
      if (v2[j] <= sm_val) {
126
12.0k
        sm_num = j;
127
12.0k
        sm_val = v2[j];
128
12.0k
      }
129
55.0k
    }
130
4.39k
    invariant(sm_num < 16);
131
4.39k
    codeValues.push_back(implicit_cast<uint8_t>(sm_num));
132
4.39k
    v2[sm_num] = 0xffffffff;
133
4.39k
  }
134
135
352
  assert(codeValues.size() == nCodes);
136
352
  hc.setCodeValues(Array1DRef<const uint8_t>(codeValues.data(), nCodes));
137
138
352
  return hc;
139
352
}
140
141
PrefixCodeDecoder<>
142
1.70k
PentaxDecompressor::SetupPrefixCodeDecoder(Optional<ByteStream> metaData) {
143
1.70k
  Optional<HuffmanCode<BaselineCodeTag>> hc;
144
145
1.70k
  if (metaData)
146
526
    hc = SetupPrefixCodeDecoder_Modern(*metaData);
147
1.18k
  else
148
1.18k
    hc = SetupPrefixCodeDecoder_Legacy();
149
150
1.70k
  PrefixCodeDecoder<> ht(std::move(*hc));
151
1.70k
  ht.setup(true, false);
152
153
1.70k
  return ht;
154
1.70k
}
155
156
1.09k
void PentaxDecompressor::decompress(ByteStream data) const {
157
1.09k
  const Array2DRef<uint16_t> out(mRaw->getU16DataAsUncroppedArray2DRef());
158
159
1.09k
  invariant(out.height() > 0);
160
1.09k
  invariant(out.width() > 0);
161
1.09k
  invariant(out.width() % 2 == 0);
162
163
1.09k
  BitStreamerMSB bs(data.peekRemainingBuffer().getAsArray1DRef());
164
124k
  for (int row = 0; row < out.height(); row++) {
165
123k
    std::array<int, 2> pred = {{}};
166
123k
    if (row >= 2)
167
121k
      pred = {out(row - 2, 0), out(row - 2, 1)};
168
169
27.5M
    for (int col = 0; col < out.width(); col++) {
170
27.4M
      pred[col & 1] += ht.decodeDifference(bs);
171
27.4M
      int value = pred[col & 1];
172
27.4M
      if (!isIntN(value, 16))
173
27.4M
        ThrowRDE("decoded value out of bounds at %d:%d", col, row);
174
27.4M
      out(row, col) = implicit_cast<uint16_t>(value);
175
27.4M
    }
176
123k
  }
177
1.09k
}
178
179
} // namespace rawspeed