/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 | } |