Coverage Report

Created: 2025-09-08 07:52

/src/LibRaw/src/decoders/smal.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- C++ -*-
2
 * Copyright 2019-2024 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.68M
#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
437
{
26
437
  uchar hist[3][13] = {{7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0},
27
437
                       {7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0},
28
437
                       {3, 3, 0, 0, 63, 47, 31, 15, 0}};
29
437
  int low, high = 0xff, carry = 0, nbits = 8;
30
437
  int s, count, bin, next, i, sym[3];
31
437
  unsigned pix;
32
437
  uchar diff, pred[] = {0, 0};
33
437
  ushort data = 0, range = 0;
34
35
437
  fseek(ifp, seg[0][1] + 1, SEEK_SET);
36
437
  getbits(-1);
37
437
  if (seg[1][0] > unsigned(raw_width * raw_height))
38
214
    seg[1][0] = raw_width * raw_height;
39
125k
  for (pix = seg[0][0]; pix < seg[1][0]; pix++)
40
125k
  {
41
501k
    for (s = 0; s < 3; s++)
42
376k
    {
43
376k
      data = data << nbits | getbits(nbits);
44
376k
      if (carry < 0)
45
65.9k
        carry = (nbits += carry + 1) < 1 ? nbits - 1 : 0;
46
476k
      while (--nbits >= 0)
47
102k
        if ((data >> nbits & 0xff) == 0xff)
48
2.26k
          break;
49
376k
      if (nbits > 0)
50
596
        data =
51
596
            ((data & ((1 << (nbits - 1)) - 1)) << 1) |
52
596
            ((data + (((data & (1 << (nbits - 1)))) << 1)) & ((~0u) << nbits));
53
376k
      if (nbits >= 0)
54
2.26k
      {
55
2.26k
        data += getbits(1);
56
2.26k
        carry = nbits - 8;
57
2.26k
      }
58
376k
      count = ((((data - range + 1) & 0xffff) << 2) - 1) / (high >> 4);
59
477k
      for (bin = 0; hist[s][bin + 5] > count; bin++)
60
100k
        ;
61
376k
      low = hist[s][bin + 5] * (high >> 4) >> 2;
62
376k
      if (bin)
63
21.1k
        high = hist[s][bin + 4] * (high >> 4) >> 2;
64
376k
      high -= low;
65
493k
      for (nbits = 0; high << nbits < 128; nbits++)
66
117k
        ;
67
376k
      range = (range + low) << nbits;
68
376k
      high <<= nbits;
69
376k
      next = hist[s][1];
70
376k
      if (++hist[s][2] > hist[s][3])
71
128k
      {
72
128k
        next = (next + 1) & hist[s][0];
73
128k
        hist[s][3] = (hist[s][next + 4] - hist[s][next + 5]) >> 2;
74
128k
        hist[s][2] = 1;
75
128k
      }
76
376k
      if (hist[s][hist[s][1] + 4] - hist[s][hist[s][1] + 5] > 1)
77
284k
      {
78
284k
        if (bin < hist[s][1])
79
87.2k
          for (i = bin; i < hist[s][1]; i++)
80
68.0k
            hist[s][i + 5]--;
81
265k
        else if (next <= bin)
82
279k
          for (i = hist[s][1]; i < bin; i++)
83
32.6k
            hist[s][i + 5]++;
84
284k
      }
85
376k
      hist[s][1] = next;
86
376k
      sym[s] = bin;
87
376k
    }
88
125k
    diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
89
125k
    if (sym[0] & 4)
90
6.21k
      diff = diff ? -diff : 0x80;
91
125k
    if (ftell(ifp) + 12 >= seg[1][1])
92
22.1k
      diff = 0;
93
125k
    if (pix >= unsigned(raw_width * raw_height))
94
0
      throw LIBRAW_EXCEPTION_IO_CORRUPT;
95
125k
    raw_image[pix] = pred[pix & 1] += diff;
96
125k
    if (!(pix & 1) && HOLE(pix / raw_width))
97
30.7k
      pix += 2;
98
125k
  }
99
437
  maximum = 0xff;
100
437
}
101
102
void LibRaw::smal_v6_load_raw()
103
34
{
104
34
  unsigned seg[2][2];
105
106
34
  fseek(ifp, 16, SEEK_SET);
107
34
  seg[0][0] = 0;
108
34
  seg[0][1] = get2();
109
34
  seg[1][0] = raw_width * raw_height;
110
34
  seg[1][1] = INT_MAX;
111
34
  smal_decode_segment(seg, 0);
112
34
}
113
114
int LibRaw::median4(int *p)
115
3.58M
{
116
3.58M
  int min, max, sum, i;
117
118
3.58M
  min = max = sum = p[0];
119
14.3M
  for (i = 1; i < 4; i++)
120
10.7M
  {
121
10.7M
    sum += p[i];
122
10.7M
    if (min > p[i])
123
8.07k
      min = p[i];
124
10.7M
    if (max < p[i])
125
7.64k
      max = p[i];
126
10.7M
  }
127
3.58M
  return (sum - min - max) >> 1;
128
3.58M
}
129
130
void LibRaw::fill_holes(int holes)
131
65
{
132
65
  int row, col, val[4];
133
134
84.9k
  for (row = 2; row < height - 2; row++)
135
84.9k
  {
136
84.9k
    if (!HOLE(row))
137
48.2k
      continue;
138
3.16M
    for (col = 1; col < width - 1; col += 4)
139
3.12M
    {
140
3.12M
      val[0] = RAW(row - 1, col - 1);
141
3.12M
      val[1] = RAW(row - 1, col + 1);
142
3.12M
      val[2] = RAW(row + 1, col - 1);
143
3.12M
      val[3] = RAW(row + 1, col + 1);
144
3.12M
      RAW(row, col) = median4(val);
145
3.12M
    }
146
3.14M
    for (col = 2; col < width - 2; col += 4)
147
3.11M
      if (HOLE(row - 2) || HOLE(row + 2))
148
3.11M
        RAW(row, col) = (RAW(row, col - 2) + RAW(row, col + 2)) >> 1;
149
450k
      else
150
450k
      {
151
450k
        val[0] = RAW(row, col - 2);
152
450k
        val[1] = RAW(row, col + 2);
153
450k
        val[2] = RAW(row - 2, col);
154
450k
        val[3] = RAW(row + 2, col);
155
450k
        RAW(row, col) = median4(val);
156
450k
      }
157
36.6k
  }
158
65
}
159
160
void LibRaw::smal_v9_load_raw()
161
117
{
162
117
  unsigned seg[256][2], offset, nseg, holes, i;
163
164
117
  fseek(ifp, 67, SEEK_SET);
165
117
  offset = get4();
166
117
  nseg = (uchar)fgetc(ifp);
167
117
  fseek(ifp, offset, SEEK_SET);
168
1.86k
  for (i = 0; i < nseg * 2; i++)
169
1.74k
    ((unsigned *)seg)[i] = get4() + unsigned(data_offset & 0xffffffff) * (i & 1);
170
117
  fseek(ifp, 78, SEEK_SET);
171
117
  holes = fgetc(ifp);
172
117
  fseek(ifp, 88, SEEK_SET);
173
117
  seg[nseg][0] = raw_height * raw_width;
174
117
  seg[nseg][1] = get4() + unsigned(data_offset & 0xffffffff);
175
520
  for (i = 0; i < nseg; i++)
176
403
    smal_decode_segment(seg + i, holes);
177
117
  if (holes)
178
65
    fill_holes(holes);
179
117
}
180
181
#undef HOLE