/src/LibRaw/src/utils/curves.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 | | void LibRaw::cubic_spline(const int *x_, const int *y_, const int len) |
22 | 0 | { |
23 | 0 | float **A, *b, *c, *d, *x, *y; |
24 | 0 | int i, j; |
25 | |
|
26 | 0 | A = (float **)calloc(((2 * len + 4) * sizeof **A + sizeof *A), 2 * len); |
27 | 0 | if (!A) |
28 | 0 | return; |
29 | 0 | A[0] = (float *)(A + 2 * len); |
30 | 0 | for (i = 1; i < 2 * len; i++) |
31 | 0 | A[i] = A[0] + 2 * len * i; |
32 | 0 | y = len + (x = i + (d = i + (c = i + (b = A[0] + i * i)))); |
33 | 0 | for (i = 0; i < len; i++) |
34 | 0 | { |
35 | 0 | x[i] = float(x_[i]) / 65535.0f; |
36 | 0 | y[i] = float(y_[i]) / 65535.0f; |
37 | 0 | } |
38 | 0 | for (i = len - 1; i > 0; i--) |
39 | 0 | { |
40 | 0 | float _div = x[i] - x[i - 1]; |
41 | 0 | if (fabsf(_div) < 1.0e-15f) |
42 | 0 | _div = 1; |
43 | 0 | b[i] = (y[i] - y[i - 1]) / _div; |
44 | 0 | d[i - 1] = _div; |
45 | 0 | } |
46 | 0 | for (i = 1; i < len - 1; i++) |
47 | 0 | { |
48 | 0 | A[i][i] = 2 * (d[i - 1] + d[i]); |
49 | 0 | if (i > 1) |
50 | 0 | { |
51 | 0 | A[i][i - 1] = d[i - 1]; |
52 | 0 | A[i - 1][i] = d[i - 1]; |
53 | 0 | } |
54 | 0 | A[i][len - 1] = 6 * (b[i + 1] - b[i]); |
55 | 0 | } |
56 | 0 | for (i = 1; i < len - 2; i++) |
57 | 0 | { |
58 | 0 | float v = A[i + 1][i] / A[i][i]; |
59 | 0 | for (j = 1; j <= len - 1; j++) |
60 | 0 | A[i + 1][j] -= v * A[i][j]; |
61 | 0 | } |
62 | 0 | for (i = len - 2; i > 0; i--) |
63 | 0 | { |
64 | 0 | float acc = 0; |
65 | 0 | for (j = i; j <= len - 2; j++) |
66 | 0 | acc += A[i][j] * c[j]; |
67 | 0 | c[i] = (A[i][len - 1] - acc) / A[i][i]; |
68 | 0 | } |
69 | 0 | for (i = 0; i < 0x10000; i++) |
70 | 0 | { |
71 | 0 | float x_out = (float)(i / 65535.0f); |
72 | 0 | float y_out = 0; |
73 | 0 | for (j = 0; j < len - 1; j++) |
74 | 0 | { |
75 | 0 | if (x[j] <= x_out && x_out <= x[j + 1]) |
76 | 0 | { |
77 | 0 | float v = x_out - x[j]; |
78 | 0 | y_out = y[j] + |
79 | 0 | ((y[j + 1] - y[j]) / d[j] - |
80 | 0 | (2 * d[j] * c[j] + c[j + 1] * d[j]) / 6) * |
81 | 0 | v + |
82 | 0 | (c[j] * 0.5f) * v * v + |
83 | 0 | ((c[j + 1] - c[j]) / (6.f * d[j])) * v * v * v; |
84 | 0 | } |
85 | 0 | } |
86 | 0 | curve[i] = y_out < 0.0 |
87 | 0 | ? 0 |
88 | 0 | : (y_out >= 1.0 ? 65535 : (ushort)(y_out * 65535.0f + 0.5f)); |
89 | 0 | } |
90 | 0 | free(A); |
91 | 0 | } |
92 | | void LibRaw::gamma_curve(double pwr, double ts, int mode, int imax) |
93 | 4.55k | { |
94 | 4.55k | int i; |
95 | 4.55k | double g[6], bnd[2] = {0, 0}, r; |
96 | | |
97 | 4.55k | g[0] = pwr; |
98 | 4.55k | g[1] = ts; |
99 | 4.55k | g[2] = g[3] = g[4] = 0; |
100 | 4.55k | bnd[g[1] >= 1] = 1; |
101 | 4.55k | if (g[1] && (g[1] - 1) * (g[0] - 1) <= 0) |
102 | 4.48k | { |
103 | 219k | for (i = 0; i < 48; i++) |
104 | 215k | { |
105 | 215k | g[2] = (bnd[0] + bnd[1]) / 2; |
106 | 215k | if (g[0]) |
107 | 205k | bnd[(pow(g[2] / g[1], -g[0]) - 1) / g[0] - 1 / g[2] > -1] = g[2]; |
108 | 9.69k | else |
109 | 9.69k | bnd[g[2] / exp(1 - 1 / g[2]) < g[1]] = g[2]; |
110 | 215k | } |
111 | 4.48k | g[3] = g[2] / g[1]; |
112 | 4.48k | if (g[0]) |
113 | 4.28k | g[4] = g[2] * (1 / g[0] - 1); |
114 | 4.48k | } |
115 | 4.55k | if (g[0]) |
116 | 4.35k | g[5] = 1 / (g[1] * SQR(g[3]) / 2 - g[4] * (1 - g[3]) + |
117 | 4.35k | (1 - pow(g[3], 1 + g[0])) * (1 + g[4]) / (1 + g[0])) - |
118 | 4.35k | 1; |
119 | 202 | else |
120 | 202 | g[5] = 1 / (g[1] * SQR(g[3]) / 2 + 1 - g[2] - g[3] - |
121 | 202 | g[2] * g[3] * (log(g[3]) - 1)) - |
122 | 202 | 1; |
123 | 4.55k | if (!mode--) |
124 | 2.04k | { |
125 | 2.04k | memcpy(gamm, g, sizeof gamm); |
126 | 2.04k | return; |
127 | 2.04k | } |
128 | 164M | for (i = 0; i < 0x10000; i++) |
129 | 164M | { |
130 | 164M | curve[i] = 0xffff; |
131 | 164M | if ((r = (double)i / imax) < 1) |
132 | 85.2M | curve[i] = |
133 | 85.2M | ushort( |
134 | 85.2M | 0x10000 * |
135 | 85.2M | (mode ? (r < g[3] ? r * g[1] |
136 | 82.5M | : (g[0] ? pow(r, g[0]) * (1 + g[4]) - g[4] |
137 | 81.0M | : log(r) * g[2] + 1)) |
138 | 85.2M | : (r < g[2] ? r / g[1] |
139 | 2.67M | : (g[0] ? pow((r + g[4]) / (1 + g[4]), 1 / g[0]) |
140 | 2.63M | : exp((r - 1) / g[2])))) |
141 | 85.2M | ); |
142 | 164M | } |
143 | 2.50k | } |
144 | | |
145 | | void LibRaw::linear_table(unsigned len) |
146 | 2.77k | { |
147 | 2.77k | int i; |
148 | 2.77k | if (len > 0x10000) |
149 | 32 | len = 0x10000; |
150 | 2.74k | else if (len < 1) |
151 | 496 | return; |
152 | 2.27k | read_shorts(curve, len); |
153 | 146M | for (i = len; i < 0x10000; i++) |
154 | 146M | curve[i] = curve[i - 1]; |
155 | 2.27k | maximum = curve[len < 0x1000 ? 0xfff : len - 1]; |
156 | 2.27k | } |