Coverage Report

Created: 2026-04-01 07:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/LibRaw/src/decoders/olympus14.cpp
Line
Count
Source
1
/* -*- C++ -*-
2
 * File: pana8.cpp
3
 * Copyright (C) 2024-2025 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
1
{
120
1
  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
void LibRaw::olympus_load_raw()
205
1
{ 
206
1
  if (!checkhdr(libraw_internal_data.internal_data.input, imgdata.makernotes.olympus.tagX653))
207
1
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
208
209
0
  const int32_t tag0x640 = imgdata.makernotes.olympus.tagX640; // usually 0
210
0
    const uint32_t tag0x643 = imgdata.makernotes.olympus.tagX643; // usually 2
211
212
0
  uint32_t context[4] = { 0,0,0,0 };
213
0
  buffered_bitpump_t pump(libraw_internal_data.internal_data.input, 65536);
214
215
0
  const int32_t one_shl_tag0x641 = 1 << imgdata.makernotes.olympus.tagX641;
216
0
  const int32_t tag0x642 = imgdata.makernotes.olympus.tagX642;
217
0
  const int32_t tag0x644 = imgdata.makernotes.olympus.tagX644;
218
0
  const int32_t one_shl_tag645 = 1 << (imgdata.makernotes.olympus.tagX645 & 0x1f);
219
0
  const int32_t tag0x646 = imgdata.makernotes.olympus.tagX646;
220
0
  const int32_t tag0x647 = imgdata.makernotes.olympus.tagX647;
221
0
  const int32_t tag0x648 = imgdata.makernotes.olympus.tagX648;
222
0
  const int32_t tag0x649 = imgdata.makernotes.olympus.tagX649;
223
0
  const int32_t tag0x650 = imgdata.makernotes.olympus.tagX650;
224
0
  const int32_t tag0x651 = imgdata.makernotes.olympus.tagX651;
225
0
  const int32_t tag0x652 = MAX(1, imgdata.makernotes.olympus.tagX652);
226
0
  const uint16_t datamax = 1<<imgdata.makernotes.olympus.ValidBits;
227
228
0
    const int32_t raw_width = imgdata.sizes.raw_width;
229
0
    ushort * const raw_image = imgdata.rawdata.raw_image;
230
231
0
  std::vector<uint32_t> bitcounts(65536);
232
0
  bitcounts[0] = 0;
233
0
  for (int i = 0, n = 1; i < 16; i++)
234
0
    for (int j = 0; j < 1 << i; j++)
235
0
      bitcounts[n++] = i+1;
236
237
0
  int32_t lpred = 0, pred1 = 0, glc = 0, gcode=0;
238
239
0
  for (uint32_t row = 0; row < imgdata.sizes.raw_height; row++)
240
0
  {
241
0
    checkCancel();
242
0
    for (uint32_t col = 0; col < raw_width; col++)
243
0
    {
244
0
          int32_t wbits, vbits, t640bits, t643bits;
245
0
          int32_t p = gcode;
246
0
      gcode = glc;
247
0
      int32_t psel = ((col>1) && one_shl_tag645 >= p) ? context[3] + 1 : 0;
248
0
      context[3] = context[2];
249
0
      context[2] = psel;
250
0
          if (col>1)
251
0
          {
252
0
            int highbitcount = bitcounts[p & 0xffff];
253
0
            int32_t T1 = ((col > 1) && (psel >= tag0x646)) ? tag0x648 : tag0x650;
254
0
            int32_t T2 = ((col > 1) && (psel >= tag0x646)) ? tag0x647 : tag0x649;
255
0
            int32_t TT = MAX((highbitcount - T1),-1);
256
0
            wbits = T2 + TT + 1;
257
0
          }
258
0
      else
259
0
        wbits = tag0x649;
260
261
0
      if (wbits > tag0x651) 
262
0
            wbits = tag0x651;
263
264
0
          int32_t gcode = oly_code(&pump, wbits, tag0x640, tag0x643, tag0x652, &glc, &t640bits, &t643bits);
265
0
          if (tag0x643) 
266
0
          {
267
0
            if (tag0x643 == 1) 
268
0
            {
269
0
              int32_t v = col<2 ? 0 : pred1;
270
0
              gcode = t643bits + 2 * (v + gcode);
271
0
              vbits = v + (gcode >> 1);
272
0
            }
273
0
            else
274
0
            {
275
0
              int32_t v = col<2 ? 0 : pred1;
276
0
              gcode = t643bits + 4 * (v + gcode);
277
0
              vbits = ((gcode >> 1) & 0xFFFFFFFE) + v + (gcode >> 2);
278
0
            }
279
0
          }
280
0
          else
281
0
            vbits = 0;
282
283
0
      pred1 = context[0];
284
0
      context[0] = (tag0x644 == 15) ? 0 : vbits >> tag0x644;
285
0
          int32_t W = col < 2 ? tag0x642 : context[1];
286
0
          int32_t N = row < 2 ? tag0x642 : raw_image[(row - 2) * raw_width + col] >> tag0x640;
287
0
          int32_t NW = (row < 2 || col < 2)? tag0x642 : NW = raw_image[(row - 2) * raw_width + col - 2] >> tag0x640;
288
289
0
      context[1] = lpred;
290
0
          if ((W < N) || (NW < W))
291
0
      {
292
0
        if (NW <= N && W >= N)
293
0
          N = W;
294
0
        else if (NW < N || W >= N)
295
0
        {
296
0
                if (NW > W || W >= N)
297
0
                {
298
0
                  if (_local_iabs(N - NW) > one_shl_tag0x641)
299
0
                    N += W - NW;
300
0
                  else if (_local_iabs(W - NW) <= one_shl_tag0x641)
301
0
                    N = (N + W) >> 1;
302
0
                  else
303
0
                    N = N + W - NW;
304
0
                }
305
0
              }
306
0
              else
307
0
                N = W;
308
0
      }
309
0
          lpred = gcode + N;
310
0
          uint32_t pixel_final_value = t640bits + ((gcode + N) << tag0x640);
311
0
          if(((raw_image[row * raw_width + col] = (ushort)pixel_final_value) > datamax)
312
0
        && col >= imgdata.sizes.width)
313
0
            derror();
314
0
    }
315
0
  }
316
0
}