Coverage Report

Created: 2026-02-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/LibRaw/src/decoders/smal.cpp
Line
Count
Source
1
/* -*- C++ -*-
2
 * Copyright 2019-2025 LibRaw LLC (info@libraw.org)
3
 *
4
 LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder,
5
 dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net.
6
 LibRaw do not use RESTRICTED code from dcraw.c
7
8
 LibRaw is free software; you can redistribute it and/or modify
9
 it under the terms of the one of two licenses as you choose:
10
11
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
12
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
13
14
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
15
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
16
17
 */
18
19
#include "../../internal/dcraw_defs.h"
20
21
7.30M
#define HOLE(row) ((holes >> (((row)-raw_height) & 7)) & 1)
22
23
/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
24
void LibRaw::smal_decode_segment(unsigned seg[2][2], int holes)
25
1.71k
{
26
1.71k
  uchar hist[3][13] = {{7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0},
27
1.71k
                       {7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0},
28
1.71k
                       {3, 3, 0, 0, 63, 47, 31, 15, 0}};
29
1.71k
  int low, high = 0xff, carry = 0, nbits = 8;
30
1.71k
  int s, count, bin, next, i, sym[3];
31
1.71k
  unsigned pix;
32
1.71k
  uchar diff, pred[] = {0, 0};
33
1.71k
  ushort data = 0, range = 0;
34
35
1.71k
  fseek(ifp, seg[0][1] + 1, SEEK_SET);
36
1.71k
  getbits(-1);
37
1.71k
  if (seg[1][0] > unsigned(raw_width * raw_height))
38
1.53k
    seg[1][0] = raw_width * raw_height;
39
83.1k
  for (pix = seg[0][0]; pix < seg[1][0]; pix++)
40
81.3k
  {
41
325k
    for (s = 0; s < 3; s++)
42
244k
    {
43
244k
      data = data << nbits | getbits(nbits);
44
244k
      if (carry < 0)
45
43.6k
        carry = (nbits += carry + 1) < 1 ? nbits - 1 : 0;
46
314k
      while (--nbits >= 0)
47
72.4k
        if ((data >> nbits & 0xff) == 0xff)
48
1.71k
          break;
49
244k
      if (nbits > 0)
50
487
        data =
51
487
            ((data & ((1 << (nbits - 1)) - 1)) << 1) |
52
487
            ((data + (((data & (1 << (nbits - 1)))) << 1)) & ((~0u) << nbits));
53
244k
      if (nbits >= 0)
54
1.71k
      {
55
1.71k
        data += getbits(1);
56
1.71k
        carry = nbits - 8;
57
1.71k
      }
58
244k
      count = ((((data - range + 1) & 0xffff) << 2) - 1) / (high >> 4);
59
329k
      for (bin = 0; hist[s][bin + 5] > count; bin++)
60
85.1k
        ;
61
244k
      low = hist[s][bin + 5] * (high >> 4) >> 2;
62
244k
      if (bin)
63
17.5k
        high = hist[s][bin + 4] * (high >> 4) >> 2;
64
244k
      high -= low;
65
327k
      for (nbits = 0; high << nbits < 128; nbits++)
66
83.7k
        ;
67
244k
      range = (range + low) << nbits;
68
244k
      high <<= nbits;
69
244k
      next = hist[s][1];
70
244k
      if (++hist[s][2] > hist[s][3])
71
83.5k
      {
72
83.5k
        next = (next + 1) & hist[s][0];
73
83.5k
        hist[s][3] = (hist[s][next + 4] - hist[s][next + 5]) >> 2;
74
83.5k
        hist[s][2] = 1;
75
83.5k
      }
76
244k
      if (hist[s][hist[s][1] + 4] - hist[s][hist[s][1] + 5] > 1)
77
185k
      {
78
185k
        if (bin < hist[s][1])
79
66.6k
          for (i = bin; i < hist[s][1]; i++)
80
52.0k
            hist[s][i + 5]--;
81
171k
        else if (next <= bin)
82
184k
          for (i = hist[s][1]; i < bin; i++)
83
24.6k
            hist[s][i + 5]++;
84
185k
      }
85
244k
      hist[s][1] = next;
86
244k
      sym[s] = bin;
87
244k
    }
88
81.3k
    diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
89
81.3k
    if (sym[0] & 4)
90
5.18k
      diff = diff ? -diff : 0x80;
91
81.3k
    if (ftell(ifp) + 12 >= seg[1][1])
92
1.87k
      diff = 0;
93
81.3k
    if (pix >= unsigned(raw_width * raw_height))
94
0
      throw LIBRAW_EXCEPTION_IO_CORRUPT;
95
81.3k
    raw_image[pix] = pred[pix & 1] += diff;
96
81.3k
    if (!(pix & 1) && HOLE(pix / raw_width))
97
21.6k
      pix += 2;
98
81.3k
  }
99
1.71k
  maximum = 0xff;
100
1.71k
}
101
102
void LibRaw::smal_v6_load_raw()
103
18
{
104
18
  unsigned seg[2][2];
105
106
18
  fseek(ifp, 16, SEEK_SET);
107
18
  seg[0][0] = 0;
108
18
  seg[0][1] = get2();
109
18
  seg[1][0] = raw_width * raw_height;
110
18
  seg[1][1] = INT_MAX;
111
18
  smal_decode_segment(seg, 0);
112
18
}
113
114
int LibRaw::median4(int *p)
115
3.68M
{
116
3.68M
  int min, max, sum, i;
117
118
3.68M
  min = max = sum = p[0];
119
14.7M
  for (i = 1; i < 4; i++)
120
11.0M
  {
121
11.0M
    sum += p[i];
122
11.0M
    if (min > p[i])
123
16.2k
      min = p[i];
124
11.0M
    if (max < p[i])
125
17.4k
      max = p[i];
126
11.0M
  }
127
3.68M
  return (sum - min - max) >> 1;
128
3.68M
}
129
130
void LibRaw::fill_holes(int holes)
131
55
{
132
55
  int row, col, val[4];
133
134
85.6k
  for (row = 2; row < height - 2; row++)
135
85.6k
  {
136
85.6k
    if (!HOLE(row))
137
22.3k
      continue;
138
3.31M
    for (col = 1; col < width - 1; col += 4)
139
3.25M
    {
140
3.25M
      val[0] = RAW(row - 1, col - 1);
141
3.25M
      val[1] = RAW(row - 1, col + 1);
142
3.25M
      val[2] = RAW(row + 1, col - 1);
143
3.25M
      val[3] = RAW(row + 1, col + 1);
144
3.25M
      RAW(row, col) = median4(val);
145
3.25M
    }
146
3.25M
    for (col = 2; col < width - 2; col += 4)
147
3.19M
      if (HOLE(row - 2) || HOLE(row + 2))
148
3.19M
        RAW(row, col) = (RAW(row, col - 2) + RAW(row, col + 2)) >> 1;
149
430k
      else
150
430k
      {
151
430k
        val[0] = RAW(row, col - 2);
152
430k
        val[1] = RAW(row, col + 2);
153
430k
        val[2] = RAW(row - 2, col);
154
430k
        val[3] = RAW(row + 2, col);
155
430k
        RAW(row, col) = median4(val);
156
430k
      }
157
63.3k
  }
158
55
}
159
160
void LibRaw::smal_v9_load_raw()
161
97
{
162
97
  unsigned seg[256][2], offset, nseg, holes, i;
163
164
97
  fseek(ifp, 67, SEEK_SET);
165
97
  offset = get4();
166
97
  nseg = (uchar)fgetc(ifp);
167
97
  fseek(ifp, offset, SEEK_SET);
168
8.31k
  for (i = 0; i < nseg * 2; i++)
169
8.22k
    ((unsigned *)seg)[i] = get4() + unsigned(data_offset & 0xffffffff) * (i & 1);
170
97
  fseek(ifp, 78, SEEK_SET);
171
97
  holes = fgetc(ifp);
172
97
  fseek(ifp, 88, SEEK_SET);
173
97
  seg[nseg][0] = raw_height * raw_width;
174
97
  seg[nseg][1] = get4() + unsigned(data_offset & 0xffffffff);
175
1.79k
  for (i = 0; i < nseg; i++)
176
1.69k
    smal_decode_segment(seg + i, holes);
177
97
  if (holes)
178
55
    fill_holes(holes);
179
97
}
180
181
#undef HOLE