Coverage Report

Created: 2026-10-28 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/LibRaw/src/postprocessing/postprocessing_utils.cpp
Line
Count
Source
1
/* -*- C++ -*-
2
 * Copyright 2019-2025 LibRaw LLC (info@libraw.org)
3
 *
4
 LibRaw is free software; you can redistribute it and/or modify
5
 it under the terms of the one of two licenses as you choose:
6
7
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
8
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
9
10
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
11
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
12
13
 */
14
15
#include "../../internal/libraw_cxx_defs.h"
16
17
0
#define TBLN 65535
18
19
void LibRaw::exp_bef(float shift, float smooth)
20
0
{
21
  // params limits
22
0
  if (shift > 8)
23
0
    shift = 8;
24
0
  if (shift < 0.25)
25
0
    shift = 0.25;
26
0
  if (smooth < 0.0)
27
0
    smooth = 0.0;
28
0
  if (smooth > 1.0)
29
0
    smooth = 1.0;
30
31
0
  unsigned short *lut = (ushort *)malloc((TBLN + 1) * sizeof(unsigned short));
32
33
0
  if (shift <= 1.0)
34
0
  {
35
0
    for (int i = 0; i <= TBLN; i++)
36
0
      lut[i] = (unsigned short)((float)i * shift);
37
0
  }
38
0
  else
39
0
  {
40
0
    float x1, x2, y1, y2;
41
42
0
    float cstops = log(shift) / log(2.0f);
43
0
    float room = cstops * 2;
44
0
    float roomlin = powf(2.0f, room);
45
0
    x2 = (float)TBLN;
46
0
    x1 = (x2 + 1) / roomlin - 1;
47
0
    y1 = x1 * shift;
48
0
    y2 = x2 * (1 + (1 - smooth) * (shift - 1));
49
0
    float sq3x = powf(x1 * x1 * x2, 1.0f / 3.0f);
50
0
    float B = (y2 - y1 + shift * (3 * x1 - 3.0f * sq3x)) /
51
0
              (x2 + 2.0f * x1 - 3.0f * sq3x);
52
0
    float A = (shift - B) * 3.0f * powf(x1 * x1, 1.0f / 3.0f);
53
0
    float CC = y2 - A * powf(x2, 1.0f / 3.0f) - B * x2;
54
0
    for (int i = 0; i <= TBLN; i++)
55
0
    {
56
0
      float X = (float)i;
57
0
      float Y = A * powf(X, 1.0f / 3.0f) + B * X + CC;
58
0
      if (i < x1)
59
0
        lut[i] = (unsigned short)((float)i * shift);
60
0
      else
61
0
        lut[i] = Y < 0 ? 0 : (Y > TBLN ? TBLN : (unsigned short)(Y));
62
0
    }
63
0
  }
64
0
  for (int i = 0; i < S.height * S.width; i++)
65
0
  {
66
0
    imgdata.image[i][0] = lut[imgdata.image[i][0]];
67
0
    imgdata.image[i][1] = lut[imgdata.image[i][1]];
68
0
    imgdata.image[i][2] = lut[imgdata.image[i][2]];
69
0
    imgdata.image[i][3] = lut[imgdata.image[i][3]];
70
0
  }
71
72
0
  if (C.data_maximum <= TBLN)
73
0
    C.data_maximum = lut[C.data_maximum];
74
0
  if (C.maximum <= TBLN)
75
0
    C.maximum = lut[C.maximum];
76
0
  free(lut);
77
0
}
78
79
void LibRaw::convert_to_rgb_loop(float out_cam[3][4])
80
0
{
81
0
  int row, col, c;
82
0
  float out[3];
83
0
  ushort *img;
84
0
  memset(libraw_internal_data.output_data.histogram, 0,
85
0
         sizeof(int) * LIBRAW_HISTOGRAM_SIZE * 4);
86
0
  if (libraw_internal_data.internal_output_params.raw_color)
87
0
  {
88
0
    for (img = imgdata.image[0], row = 0; row < S.height; row++)
89
0
    {
90
0
      for (col = 0; col < S.width; col++, img += 4)
91
0
      {
92
0
        for (c = 0; c < imgdata.idata.colors; c++)
93
0
        {
94
0
          libraw_internal_data.output_data.histogram[c][img[c] >> 3]++;
95
0
        }
96
0
      }
97
0
    }
98
0
  }
99
0
  else if (imgdata.idata.colors == 3)
100
0
  {
101
0
    for (img = imgdata.image[0], row = 0; row < S.height; row++)
102
0
    {
103
0
      for (col = 0; col < S.width; col++, img += 4)
104
0
      {
105
0
        out[0] = out_cam[0][0] * img[0] + out_cam[0][1] * img[1] +
106
0
                 out_cam[0][2] * img[2];
107
0
        out[1] = out_cam[1][0] * img[0] + out_cam[1][1] * img[1] +
108
0
                 out_cam[1][2] * img[2];
109
0
        out[2] = out_cam[2][0] * img[0] + out_cam[2][1] * img[1] +
110
0
                 out_cam[2][2] * img[2];
111
0
        img[0] = CLIP((int)out[0]);
112
0
        img[1] = CLIP((int)out[1]);
113
0
        img[2] = CLIP((int)out[2]);
114
0
        libraw_internal_data.output_data.histogram[0][img[0] >> 3]++;
115
0
        libraw_internal_data.output_data.histogram[1][img[1] >> 3]++;
116
0
        libraw_internal_data.output_data.histogram[2][img[2] >> 3]++;
117
0
      }
118
0
    }
119
0
  }
120
0
  else if (imgdata.idata.colors == 4)
121
0
  {
122
0
    for (img = imgdata.image[0], row = 0; row < S.height; row++)
123
0
    {
124
0
      for (col = 0; col < S.width; col++, img += 4)
125
0
      {
126
0
        out[0] = out_cam[0][0] * img[0] + out_cam[0][1] * img[1] +
127
0
                 out_cam[0][2] * img[2] + out_cam[0][3] * img[3];
128
0
        out[1] = out_cam[1][0] * img[0] + out_cam[1][1] * img[1] +
129
0
                 out_cam[1][2] * img[2] + out_cam[1][3] * img[3];
130
0
        out[2] = out_cam[2][0] * img[0] + out_cam[2][1] * img[1] +
131
0
                 out_cam[2][2] * img[2] + out_cam[2][3] * img[3];
132
0
        img[0] = CLIP((int)out[0]);
133
0
        img[1] = CLIP((int)out[1]);
134
0
        img[2] = CLIP((int)out[2]);
135
0
        libraw_internal_data.output_data.histogram[0][img[0] >> 3]++;
136
0
        libraw_internal_data.output_data.histogram[1][img[1] >> 3]++;
137
0
        libraw_internal_data.output_data.histogram[2][img[2] >> 3]++;
138
0
        libraw_internal_data.output_data.histogram[3][img[3] >> 3]++;
139
0
      }
140
0
    }
141
0
  }
142
0
}
143
144
void LibRaw::scale_colors_loop(float scale_mul[4])
145
0
{
146
0
  unsigned size = S.iheight * S.iwidth;
147
148
0
  if (C.cblack[4] && C.cblack[5])
149
0
  {
150
0
    int val;
151
0
    for (unsigned i = 0; i < size; i++)
152
0
    {
153
0
      for (unsigned c = 0; c < 4; c++)
154
0
      {
155
0
        if (!(val = imgdata.image[i][c])) continue;
156
0
        val -= C.cblack[6 + i / S.iwidth % C.cblack[4] * C.cblack[5] +
157
0
                        i % S.iwidth % C.cblack[5]];
158
0
        val -= C.cblack[c];
159
0
        val = int(val * scale_mul[c]);
160
0
        imgdata.image[i][c] = CLIP(val);
161
0
      }
162
0
    }
163
0
  }
164
0
  else if (C.cblack[0] || C.cblack[1] || C.cblack[2] || C.cblack[3])
165
0
  {
166
0
    for (unsigned i = 0; i < size; i++)
167
0
    {
168
0
      for (unsigned c = 0; c < 4; c++)
169
0
      {
170
0
        int val = imgdata.image[i][c];
171
0
        if (!val) continue;
172
0
        val -= C.cblack[c];
173
0
        val = int(val * scale_mul[c]);
174
0
        imgdata.image[i][c] = CLIP(val);
175
0
      }
176
0
    }
177
0
  }
178
0
  else // BL is zero
179
0
  {
180
0
    for (unsigned i = 0; i < size; i++)
181
0
    {
182
0
      for (unsigned c = 0; c < 4; c++)
183
0
      {
184
0
        int val = imgdata.image[i][c];
185
0
        val = int(val * scale_mul[c]);
186
0
        imgdata.image[i][c] = CLIP(val);
187
0
      }
188
0
    }
189
0
  }
190
0
}