Coverage Report

Created: 2026-07-20 07:19

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
1.55M
#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
17.6k
{
26
17.6k
  uchar hist[3][13] = {{7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0},
27
17.6k
                       {7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0},
28
17.6k
                       {3, 3, 0, 0, 63, 47, 31, 15, 0}};
29
17.6k
  int low, high = 0xff, carry = 0, nbits = 8;
30
17.6k
  int s, count, bin, next, i, sym[3];
31
17.6k
  unsigned pix;
32
17.6k
  uchar diff, pred[] = {0, 0};
33
17.6k
  ushort data = 0, range = 0;
34
35
17.6k
  fseek(ifp, seg[0][1] + 1, SEEK_SET);
36
17.6k
  getbits(-1);
37
17.6k
  if (seg[1][0] > unsigned(raw_width * raw_height))
38
17.0k
    seg[1][0] = raw_width * raw_height;
39
270k
  for (pix = seg[0][0]; pix < seg[1][0]; pix++)
40
252k
  {
41
1.01M
    for (s = 0; s < 3; s++)
42
758k
    {
43
758k
      data = data << nbits | getbits(nbits);
44
758k
      if (carry < 0)
45
40.8k
        carry = (nbits += carry + 1) < 1 ? nbits - 1 : 0;
46
1.19M
      while (--nbits >= 0)
47
443k
        if ((data >> nbits & 0xff) == 0xff)
48
2.99k
          break;
49
758k
      if (nbits > 0)
50
1.29k
        data =
51
1.29k
            ((data & ((1 << (nbits - 1)) - 1)) << 1) |
52
1.29k
            ((data + (((data & (1 << (nbits - 1)))) << 1)) & ((~0u) << nbits));
53
758k
      if (nbits >= 0)
54
2.99k
      {
55
2.99k
        data += getbits(1);
56
2.99k
        carry = nbits - 8;
57
2.99k
      }
58
758k
      count = ((((data - range + 1) & 0xffff) << 2) - 1) / (high >> 4);
59
1.60M
      for (bin = 0; hist[s][bin + 5] > count; bin++)
60
848k
        ;
61
758k
      low = hist[s][bin + 5] * (high >> 4) >> 2;
62
758k
      if (bin)
63
177k
        high = hist[s][bin + 4] * (high >> 4) >> 2;
64
758k
      high -= low;
65
1.22M
      for (nbits = 0; high << nbits < 128; nbits++)
66
462k
        ;
67
758k
      range = (range + low) << nbits;
68
758k
      high <<= nbits;
69
758k
      next = hist[s][1];
70
758k
      if (++hist[s][2] > hist[s][3])
71
268k
      {
72
268k
        next = (next + 1) & hist[s][0];
73
268k
        hist[s][3] = (hist[s][next + 4] - hist[s][next + 5]) >> 2;
74
268k
        hist[s][2] = 1;
75
268k
      }
76
758k
      if (hist[s][hist[s][1] + 4] - hist[s][hist[s][1] + 5] > 1)
77
597k
      {
78
597k
        if (bin < hist[s][1])
79
335k
          for (i = bin; i < hist[s][1]; i++)
80
260k
            hist[s][i + 5]--;
81
522k
        else if (next <= bin)
82
671k
          for (i = hist[s][1]; i < bin; i++)
83
182k
            hist[s][i + 5]++;
84
597k
      }
85
758k
      hist[s][1] = next;
86
758k
      sym[s] = bin;
87
758k
    }
88
252k
    diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
89
252k
    if (sym[0] & 4)
90
50.2k
      diff = diff ? -diff : 0x80;
91
252k
    if (ftell(ifp) + 12 >= seg[1][1])
92
90.2k
      diff = 0;
93
252k
    if (pix >= unsigned(raw_width * raw_height))
94
0
      throw LIBRAW_EXCEPTION_IO_CORRUPT;
95
252k
    raw_image[pix] = pred[pix & 1] += diff;
96
252k
    if (!(pix & 1) && HOLE(pix / raw_width))
97
35.9k
      pix += 2;
98
252k
  }
99
17.6k
  maximum = 0xff;
100
17.6k
}
101
102
void LibRaw::smal_v6_load_raw()
103
37
{
104
37
  unsigned seg[2][2];
105
106
37
  fseek(ifp, 16, SEEK_SET);
107
37
  seg[0][0] = 0;
108
37
  seg[0][1] = get2();
109
37
  seg[1][0] = raw_width * raw_height;
110
37
  seg[1][1] = INT_MAX;
111
37
  smal_decode_segment(seg, 0);
112
37
}
113
114
int LibRaw::median4(int *p)
115
735k
{
116
735k
  int min, max, sum, i;
117
118
735k
  min = max = sum = p[0];
119
2.94M
  for (i = 1; i < 4; i++)
120
2.20M
  {
121
2.20M
    sum += p[i];
122
2.20M
    if (min > p[i])
123
6.34k
      min = p[i];
124
2.20M
    if (max < p[i])
125
4.29k
      max = p[i];
126
2.20M
  }
127
735k
  return (sum - min - max) >> 1;
128
735k
}
129
130
void LibRaw::fill_holes(int holes)
131
113
{
132
113
  int row, col, val[4];
133
134
14.4k
  for (row = 2; row < height - 2; row++)
135
14.3k
  {
136
14.3k
    if (!HOLE(row))
137
1.93k
      continue;
138
689k
    for (col = 1; col < width - 1; col += 4)
139
677k
    {
140
677k
      val[0] = RAW(row - 1, col - 1);
141
677k
      val[1] = RAW(row - 1, col + 1);
142
677k
      val[2] = RAW(row + 1, col - 1);
143
677k
      val[3] = RAW(row + 1, col + 1);
144
677k
      RAW(row, col) = median4(val);
145
677k
    }
146
679k
    for (col = 2; col < width - 2; col += 4)
147
667k
      if (HOLE(row - 2) || HOLE(row + 2))
148
667k
        RAW(row, col) = (RAW(row, col - 2) + RAW(row, col + 2)) >> 1;
149
58.0k
      else
150
58.0k
      {
151
58.0k
        val[0] = RAW(row, col - 2);
152
58.0k
        val[1] = RAW(row, col + 2);
153
58.0k
        val[2] = RAW(row - 2, col);
154
58.0k
        val[3] = RAW(row + 2, col);
155
58.0k
        RAW(row, col) = median4(val);
156
58.0k
      }
157
12.3k
  }
158
113
}
159
160
void LibRaw::smal_v9_load_raw()
161
144
{
162
144
  unsigned seg[256][2], offset, nseg, holes, i;
163
164
144
  fseek(ifp, 67, SEEK_SET);
165
144
  offset = get4();
166
144
  nseg = (uchar)fgetc(ifp);
167
144
  fseek(ifp, offset, SEEK_SET);
168
47.1k
  for (i = 0; i < nseg * 2; i++)
169
47.0k
    ((unsigned *)seg)[i] = get4() + unsigned(data_offset & 0xffffffff) * (i & 1);
170
144
  fseek(ifp, 78, SEEK_SET);
171
144
  holes = fgetc(ifp);
172
144
  fseek(ifp, 88, SEEK_SET);
173
144
  seg[nseg][0] = raw_height * raw_width;
174
144
  seg[nseg][1] = get4() + unsigned(data_offset & 0xffffffff);
175
17.7k
  for (i = 0; i < nseg; i++)
176
17.5k
    smal_decode_segment(seg + i, holes);
177
144
  if (holes)
178
113
    fill_holes(holes);
179
144
}
180
181
#undef HOLE