Coverage Report

Created: 2026-09-15 07:01

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
403M
#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
14.6k
{
26
14.6k
  uchar hist[3][13] = {{7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0},
27
14.6k
                       {7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0},
28
14.6k
                       {3, 3, 0, 0, 63, 47, 31, 15, 0}};
29
14.6k
  int low, high = 0xff, carry = 0, nbits = 8;
30
14.6k
  int s, count, bin, next, i, sym[3];
31
14.6k
  unsigned pix;
32
14.6k
  uchar diff, pred[] = {0, 0};
33
14.6k
  ushort data = 0, range = 0;
34
35
14.6k
  fseek(ifp, seg[0][1] + 1, SEEK_SET);
36
14.6k
  getbits(-1);
37
14.6k
  if (seg[1][0] > unsigned(raw_width * raw_height))
38
13.7k
    seg[1][0] = raw_width * raw_height;
39
191k
  for (pix = seg[0][0]; pix < seg[1][0]; pix++)
40
176k
  {
41
705k
    for (s = 0; s < 3; s++)
42
528k
    {
43
528k
      data = data << nbits | getbits(nbits);
44
528k
      if (carry < 0)
45
39.2k
        carry = (nbits += carry + 1) < 1 ? nbits - 1 : 0;
46
881k
      while (--nbits >= 0)
47
357k
        if ((data >> nbits & 0xff) == 0xff)
48
5.04k
          break;
49
528k
      if (nbits > 0)
50
2.69k
        data =
51
2.69k
            ((data & ((1 << (nbits - 1)) - 1)) << 1) |
52
2.69k
            ((data + (((data & (1 << (nbits - 1)))) << 1)) & ((~0u) << nbits));
53
528k
      if (nbits >= 0)
54
5.04k
      {
55
5.04k
        data += getbits(1);
56
5.04k
        carry = nbits - 8;
57
5.04k
      }
58
528k
      count = ((((data - range + 1) & 0xffff) << 2) - 1) / (high >> 4);
59
1.68M
      for (bin = 0; hist[s][bin + 5] > count; bin++)
60
1.15M
        ;
61
528k
      low = hist[s][bin + 5] * (high >> 4) >> 2;
62
528k
      if (bin)
63
229k
        high = hist[s][bin + 4] * (high >> 4) >> 2;
64
528k
      high -= low;
65
919k
      for (nbits = 0; high << nbits < 128; nbits++)
66
390k
        ;
67
528k
      range = (range + low) << nbits;
68
528k
      high <<= nbits;
69
528k
      next = hist[s][1];
70
528k
      if (++hist[s][2] > hist[s][3])
71
192k
      {
72
192k
        next = (next + 1) & hist[s][0];
73
192k
        hist[s][3] = (hist[s][next + 4] - hist[s][next + 5]) >> 2;
74
192k
        hist[s][2] = 1;
75
192k
      }
76
528k
      if (hist[s][hist[s][1] + 4] - hist[s][hist[s][1] + 5] > 1)
77
426k
      {
78
426k
        if (bin < hist[s][1])
79
257k
          for (i = bin; i < hist[s][1]; i++)
80
199k
            hist[s][i + 5]--;
81
368k
        else if (next <= bin)
82
532k
          for (i = hist[s][1]; i < bin; i++)
83
183k
            hist[s][i + 5]++;
84
426k
      }
85
528k
      hist[s][1] = next;
86
528k
      sym[s] = bin;
87
528k
    }
88
176k
    diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
89
176k
    if (sym[0] & 4)
90
67.6k
      diff = diff ? -diff : 0x80;
91
176k
    if (ftell(ifp) + 12 >= seg[1][1])
92
16.3k
      diff = 0;
93
176k
    if (pix >= unsigned(raw_width * raw_height))
94
0
      throw LIBRAW_EXCEPTION_IO_CORRUPT;
95
176k
    raw_image[pix] = pred[pix & 1] += diff;
96
176k
    if (!(pix & 1) && HOLE(pix / raw_width))
97
27.4k
      pix += 2;
98
176k
  }
99
14.6k
  maximum = 0xff;
100
14.6k
}
101
102
void LibRaw::smal_v6_load_raw()
103
118
{
104
118
  unsigned seg[2][2];
105
106
118
  fseek(ifp, 16, SEEK_SET);
107
118
  seg[0][0] = 0;
108
118
  seg[0][1] = get2();
109
118
  seg[1][0] = raw_width * raw_height;
110
118
  seg[1][1] = INT_MAX;
111
118
  smal_decode_segment(seg, 0);
112
118
}
113
114
int LibRaw::median4(int *p)
115
195M
{
116
195M
  int min, max, sum, i;
117
118
195M
  min = max = sum = p[0];
119
783M
  for (i = 1; i < 4; i++)
120
587M
  {
121
587M
    sum += p[i];
122
587M
    if (min > p[i])
123
1.06M
      min = p[i];
124
587M
    if (max < p[i])
125
989k
      max = p[i];
126
587M
  }
127
195M
  return (sum - min - max) >> 1;
128
195M
}
129
130
void LibRaw::fill_holes(int holes)
131
159
{
132
159
  int row, col, val[4];
133
134
1.14M
  for (row = 2; row < height - 2; row++)
135
1.14M
  {
136
1.14M
    if (!HOLE(row))
137
517k
      continue;
138
183M
    for (col = 1; col < width - 1; col += 4)
139
182M
    {
140
182M
      val[0] = RAW(row - 1, col - 1);
141
182M
      val[1] = RAW(row - 1, col + 1);
142
182M
      val[2] = RAW(row + 1, col - 1);
143
182M
      val[3] = RAW(row + 1, col + 1);
144
182M
      RAW(row, col) = median4(val);
145
182M
    }
146
182M
    for (col = 2; col < width - 2; col += 4)
147
182M
      if (HOLE(row - 2) || HOLE(row + 2))
148
182M
        RAW(row, col) = (RAW(row, col - 2) + RAW(row, col + 2)) >> 1;
149
13.3M
      else
150
13.3M
      {
151
13.3M
        val[0] = RAW(row, col - 2);
152
13.3M
        val[1] = RAW(row, col + 2);
153
13.3M
        val[2] = RAW(row - 2, col);
154
13.3M
        val[3] = RAW(row + 2, col);
155
13.3M
        RAW(row, col) = median4(val);
156
13.3M
      }
157
626k
  }
158
159
}
159
160
void LibRaw::smal_v9_load_raw()
161
263
{
162
263
  unsigned seg[256][2], offset, nseg, holes, i;
163
164
263
  fseek(ifp, 67, SEEK_SET);
165
263
  offset = get4();
166
263
  nseg = (uchar)fgetc(ifp);
167
263
  fseek(ifp, offset, SEEK_SET);
168
43.3k
  for (i = 0; i < nseg * 2; i++)
169
43.1k
    ((unsigned *)seg)[i] = get4() + unsigned(data_offset & 0xffffffff) * (i & 1);
170
263
  fseek(ifp, 78, SEEK_SET);
171
263
  holes = fgetc(ifp);
172
263
  fseek(ifp, 88, SEEK_SET);
173
263
  seg[nseg][0] = raw_height * raw_width;
174
263
  seg[nseg][1] = get4() + unsigned(data_offset & 0xffffffff);
175
14.7k
  for (i = 0; i < nseg; i++)
176
14.5k
    smal_decode_segment(seg + i, holes);
177
263
  if (holes)
178
159
    fill_holes(holes);
179
263
}
180
181
#undef HOLE