Coverage Report

Created: 2025-06-16 07:00

/src/libraw/src/decoders/olympus14.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- C++ -*-
2
 * File: pana8.cpp
3
 * Copyright (C) 2024 Alex Tutubalin, LibRaw LLC
4
 *
5
   Olympus/OM System 12/14-bit file decoder
6
7
LibRaw is free software; you can redistribute it and/or modify
8
it under the terms of the one of two licenses as you choose:
9
10
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
11
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
12
13
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
14
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
15
16
 */
17
18
#include "../../internal/libraw_cxx_defs.h"
19
#include <vector>
20
21
22
 struct buffered_bitpump_t
23
{
24
  uint32_t bitcount;
25
  uint32_t bitstorage;
26
  LibRaw_abstract_datastream *input;
27
  std::vector<uint8_t> buffer;
28
  uint8_t *bufp;
29
  int pos, datasz;
30
  bool is_buf;
31
0
  buffered_bitpump_t(LibRaw_abstract_datastream *in, int bufsz) : bitcount(0), bitstorage(0), input(in),
32
0
    buffer(bufsz),pos(0),datasz(0)
33
0
  {
34
0
    is_buf = input->is_buffered();
35
0
    input->buffering_off();
36
0
    bufp = buffer.data();
37
0
    }
38
  ~buffered_bitpump_t()
39
0
  {
40
0
    if (is_buf)
41
0
      input->buffering_on();
42
0
  }
43
void skip_bit(uint32_t &vbits)
44
0
  {
45
0
    if (!vbits)
46
0
    {
47
0
      replace_data();
48
0
      vbits = --bitcount;
49
0
    }
50
0
    else
51
0
      bitcount = --vbits;
52
0
  }
53
  void replace_data() 
54
0
  {
55
0
     bitstorage = get4();
56
0
     bitcount = 32;
57
0
  }
58
59
  uint32_t add_data()
60
0
  {
61
0
  uint32_t bb = get2();
62
0
  bitstorage = bitstorage << 16 | bb;
63
0
    bitcount += 16;
64
0
  return bitcount;
65
0
  }
66
  uint32_t getbits(unsigned wbits)
67
0
  {
68
0
    while (bitcount < wbits)
69
0
      add_data();
70
0
    uint32_t ret = bitstorage << (32 - (bitcount & 0x1f)) >> (32 - wbits);
71
0
    bitcount -= wbits;
72
0
    return ret;
73
0
  }
74
  uint32_t get2()
75
0
  {
76
0
    if (pos < datasz - 1)
77
0
    {
78
0
      uint32_t ret = bufp[pos] << 8 | bufp[pos + 1];
79
0
      pos += 2;
80
0
      return ret;
81
0
    }
82
0
    uint8_t b[2];
83
0
    int i = 0;
84
0
    while (pos < datasz)
85
0
      b[i++] = bufp[pos++];
86
0
    refill(2);
87
0
    for (; i < 2; i++)
88
0
      b[i] = bufp[pos++];
89
0
    return b[0] << 8 | b[1];
90
0
  }
91
92
  uint32_t get4()
93
0
  {
94
0
    if (pos < datasz - 3)
95
0
    {
96
0
      uint32_t ret = bufp[pos] << 24 | bufp[pos + 1] << 16 | bufp[pos + 2] << 8 | bufp[pos + 3];
97
0
      pos += 4;
98
0
      return ret;
99
0
    }
100
0
    uint8_t b[4];
101
0
    int i = 0;
102
0
    while (pos < datasz)
103
0
      b[i++] = bufp[pos++];
104
0
    refill(4);
105
0
    for (; i < 4; i++)
106
0
      b[i] = bufp[pos++];
107
0
    return b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];
108
0
  }
109
  void refill(int b)
110
0
  {
111
0
    int r = input->read(bufp, 1, buffer.size());
112
0
    pos = 0;
113
0
    datasz = r > b ? r : b; 
114
0
  }
115
};
116
117
118
static bool checkhdr(LibRaw_abstract_datastream *ifp, int bytes)
119
5
{
120
5
  if (bytes <= 0) return false;
121
0
  uint64_t b64 = 0ULL;
122
0
  for(int i = 0; i < bytes; i++)
123
0
    {
124
0
      uint8_t databyte1 = (uint8_t)ifp->get_char();
125
0
      uint64_t q = (b64 << 8) | databyte1;
126
0
      b64 = q;
127
0
    } 
128
0
  if (b64 != 1ULL)
129
0
    return false;
130
0
  if (ifp->get_char() | ifp->get_char())
131
0
    return false;
132
0
  return true;
133
0
}
134
135
static
136
#ifdef _MSC_VER
137
    __forceinline
138
#else
139
    inline
140
#endif
141
0
int32_t _local_iabs(int32_t x){ return (x ^ (x >> 31)) - (x >> 31);}
142
143
static
144
#ifdef _MSC_VER
145
__forceinline
146
#else
147
inline
148
#endif
149
int32_t oly_code(buffered_bitpump_t *th, unsigned int wbits, unsigned int tag0x640,
150
                           unsigned int tag0x643, int tag0x652, 
151
                           int *glc, int *t640bits, int *t643bits)
152
0
{
153
0
  int highdatabit;
154
155
0
  if (!th->bitcount)
156
0
    th->replace_data();
157
158
0
  int v = --th->bitcount;
159
0
  highdatabit = (th->bitstorage >> v) & 1;
160
0
  *t643bits = tag0x643 ? th->getbits(tag0x643) : 0;
161
0
  *t640bits = tag0x640 ? th->getbits(tag0x640) : 0;
162
163
0
  uint32_t vbits = th->bitcount;
164
0
  uint32_t high = 0;
165
0
  uint32_t low = 0;
166
167
0
  while (1)
168
0
  {
169
0
    th->skip_bit(vbits);
170
0
    if ((th->bitstorage >> vbits) & 1)
171
0
      break;
172
0
    if ((uint32_t)tag0x652 == ++high)
173
0
    {
174
0
      high = 0;
175
0
      if (wbits != 15)
176
0
      {
177
0
        uint32_t i;
178
0
        for (i = 15 - wbits; vbits < i;)
179
0
          vbits = th->add_data();
180
181
0
        high = th->bitstorage << (32 - (vbits & 0x1f)) >> (wbits + 17);
182
0
        vbits -= i;
183
0
        th->bitcount = vbits;
184
0
      }
185
0
      th->skip_bit(vbits);
186
0
      break;
187
0
    }
188
0
  } 
189
  
190
0
  if (wbits < 1)
191
0
    low = 0;
192
0
  else
193
0
  {
194
0
    while (vbits < wbits)
195
0
      vbits = th->add_data();
196
0
    low = th->bitstorage << (32 - (vbits & 0x1f)) >> (32 - (wbits & 0x1f));
197
0
    th->bitcount = vbits - wbits;
198
0
  }
199
0
  *glc = low | (high << wbits);
200
0
  int32_t result = *glc ^ (unsigned int)(-highdatabit);
201
0
  return result;
202
0
}
203
204
205
206
void LibRaw::olympus14_load_raw() 
207
5
{ 
208
5
  if (!checkhdr(libraw_internal_data.internal_data.input, imgdata.makernotes.olympus.tagX653))
209
5
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
210
211
0
  const int32_t tag0x640 = imgdata.makernotes.olympus.tagX640; // usually 0
212
0
    const uint32_t tag0x643 = imgdata.makernotes.olympus.tagX643; // usually 2
213
214
0
  uint32_t context[4] = { 0,0,0,0 };
215
0
  buffered_bitpump_t pump(libraw_internal_data.internal_data.input, 65536);
216
217
0
  const int32_t one_shl_tag0x641 = 1 << imgdata.makernotes.olympus.tagX641;
218
0
  const int32_t tag0x642 = imgdata.makernotes.olympus.tagX642;
219
0
  const int32_t tag0x644 = imgdata.makernotes.olympus.tagX644;
220
0
  const int32_t one_shl_tag645 = 1 << (imgdata.makernotes.olympus.tagX645 & 0x1f);
221
0
  const int32_t tag0x646 = imgdata.makernotes.olympus.tagX646;
222
0
  const int32_t tag0x647 = imgdata.makernotes.olympus.tagX647;
223
0
  const int32_t tag0x648 = imgdata.makernotes.olympus.tagX648;
224
0
  const int32_t tag0x649 = imgdata.makernotes.olympus.tagX649;
225
0
  const int32_t tag0x650 = imgdata.makernotes.olympus.tagX650;
226
0
  const int32_t tag0x651 = imgdata.makernotes.olympus.tagX651;
227
0
  const int32_t tag0x652 = MAX(1, imgdata.makernotes.olympus.tagX652);
228
0
  const uint16_t datamax = 1<<imgdata.makernotes.olympus.ValidBits;
229
230
0
    const int32_t raw_width = imgdata.sizes.raw_width;
231
0
    ushort * const raw_image = imgdata.rawdata.raw_image;
232
233
0
  std::vector<uint32_t> bitcounts(65536);
234
0
  bitcounts[0] = 0;
235
0
  for (int i = 0, n = 1; i < 16; i++)
236
0
    for (int j = 0; j < 1 << i; j++)
237
0
      bitcounts[n++] = i+1;
238
239
0
  int32_t lpred = 0, pred1 = 0, glc = 0, gcode=0;
240
241
0
  for (uint32_t row = 0; row < imgdata.sizes.raw_height; row++)
242
0
  {
243
0
    checkCancel();
244
0
    for (uint32_t col = 0; col < raw_width; col++)
245
0
    {
246
0
          int32_t wbits, vbits, t640bits, t643bits;
247
0
          int32_t p = gcode;
248
0
      gcode = glc;
249
0
      int32_t psel = ((col>1) && one_shl_tag645 >= p) ? context[3] + 1 : 0;
250
0
      context[3] = context[2];
251
0
      context[2] = psel;
252
0
          if (col>1)
253
0
          {
254
0
            int highbitcount = bitcounts[p & 0xffff];
255
0
            int32_t T1 = ((col > 1) && (psel >= tag0x646)) ? tag0x648 : tag0x650;
256
0
            int32_t T2 = ((col > 1) && (psel >= tag0x646)) ? tag0x647 : tag0x649;
257
0
            int32_t TT = MAX((highbitcount - T1),-1);
258
0
            wbits = T2 + TT + 1;
259
0
          }
260
0
      else
261
0
        wbits = tag0x649;
262
263
0
      if (wbits > tag0x651) 
264
0
            wbits = tag0x651;
265
266
0
          int32_t gcode = oly_code(&pump, wbits, tag0x640, tag0x643, tag0x652, &glc, &t640bits, &t643bits);
267
0
          if (tag0x643) 
268
0
          {
269
0
            if (tag0x643 == 1) 
270
0
            {
271
0
              int32_t v = col<2 ? 0 : pred1;
272
0
              gcode = t643bits + 2 * (v + gcode);
273
0
              vbits = v + (gcode >> 1);
274
0
            }
275
0
            else
276
0
            {
277
0
              int32_t v = col<2 ? 0 : pred1;
278
0
              gcode = t643bits + 4 * (v + gcode);
279
0
              vbits = ((gcode >> 1) & 0xFFFFFFFE) + v + (gcode >> 2);
280
0
            }
281
0
          }
282
0
          else
283
0
            vbits = 0;
284
285
0
      pred1 = context[0];
286
0
      context[0] = (tag0x644 == 15) ? 0 : vbits >> tag0x644;
287
0
          int32_t W = col < 2 ? tag0x642 : context[1];
288
0
          int32_t N = row < 2 ? tag0x642 : raw_image[(row - 2) * raw_width + col] >> tag0x640;
289
0
          int32_t NW = (row < 2 || col < 2)? tag0x642 : NW = raw_image[(row - 2) * raw_width + col - 2] >> tag0x640;
290
291
0
      context[1] = lpred;
292
0
          if ((W < N) || (NW < W))
293
0
      {
294
0
        if (NW <= N && W >= N)
295
0
          N = W;
296
0
        else if (NW < N || W >= N)
297
0
        {
298
0
                if (NW > W || W >= N)
299
0
                {
300
0
                  if (_local_iabs(N - NW) > one_shl_tag0x641)
301
0
                    N += W - NW;
302
0
                  else if (_local_iabs(W - NW) <= one_shl_tag0x641)
303
0
                    N = (N + W) >> 1;
304
0
                  else
305
0
                    N = N + W - NW;
306
0
                }
307
0
              }
308
0
              else
309
0
                N = W;
310
0
      }
311
0
          lpred = gcode + N;
312
0
          uint32_t pixel_final_value = t640bits + ((gcode + N) << tag0x640);
313
0
          if(((raw_image[row * raw_width + col] = (ushort)pixel_final_value) > datamax)
314
0
        && col >= imgdata.sizes.width)
315
0
            derror();
316
0
    }
317
0
  }
318
0
}