Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
imageop_math.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2016 Dan Torop.
4 Copyright (C) 2016 Pedro Côrte-Real.
5 Copyright (C) 2016, 2018 Roman Lebedev.
6 Copyright (C) 2016 Tobias Ellinghaus.
7 Copyright (C) 2019 Andreas Schneider.
8 Copyright (C) 2019-2021, 2025 Aurélien PIERRE.
9 Copyright (C) 2019 Marcus Rückert.
10 Copyright (C) 2020 Diederik Ter Rahe.
11 Copyright (C) 2020 Pascal Obry.
12 Copyright (C) 2020-2021 Ralf Brown.
13 Copyright (C) 2022 Martin Bařinka.
14 Copyright (C) 2025 Alynx Zhou.
15
16 darktable is free software: you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation, either version 3 of the License, or
19 (at your option) any later version.
20
21 darktable is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with darktable. If not, see <http://www.gnu.org/licenses/>.
28*/
29
30#ifndef DT_DEVELOP_IMAGEOP_MATH_H
31#define DT_DEVELOP_IMAGEOP_MATH_H
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#ifdef HAVE_OPENCL
37#include <CL/cl.h> // for cl_mem
38#endif
39
40#include "common/image.h" // for dt_image_t, dt_image_orientation_t
41#include "develop/imageop.h" // for dt_iop_roi_t
42#include <glib.h> // for inline
43#include <math.h> // for log, logf, powf
44#include <stddef.h> // for size_t, NULL
45#include <stdint.h> // for uint8_t, uint16_t, uint32_t
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
52void dt_iop_flip_and_zoom_8(const uint8_t *in, int32_t iw, int32_t ih, uint8_t *out, int32_t ow, int32_t oh,
53 const dt_image_orientation_t orientation, uint32_t *width, uint32_t *height);
54
56void dt_iop_clip_and_zoom(float *out, const float *const in, const struct dt_iop_roi_t *const roi_out,
57 const struct dt_iop_roi_t *const roi_in, const int32_t out_stride,
58 const int32_t in_stride);
59
61void dt_iop_clip_and_zoom_roi(float *out, const float *const in, const struct dt_iop_roi_t *const roi_out,
62 const struct dt_iop_roi_t *const roi_in, const int32_t out_stride,
63 const int32_t in_stride);
64#ifdef HAVE_OPENCL
65int dt_iop_clip_and_zoom_cl(int devid, cl_mem dev_out, cl_mem dev_in,
66 const struct dt_iop_roi_t *const roi_out,
67 const struct dt_iop_roi_t *const roi_in);
68
69int dt_iop_clip_and_zoom_roi_cl(int devid, cl_mem dev_out, cl_mem dev_in,
70 const struct dt_iop_roi_t *const roi_out,
71 const struct dt_iop_roi_t *const roi_in);
72#endif
73
74void dt_iop_clip_and_zoom_mosaic_half_size_f(float *const out, const float *const in,
75 const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in,
76 const int32_t out_stride, const int32_t in_stride,
77 const uint32_t filters);
78
79void dt_iop_clip_and_zoom_mosaic_half_size(uint16_t *const out, const uint16_t *const in,
80 const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in,
81 const int32_t out_stride, const int32_t in_stride,
82 const uint32_t filters);
83
84void dt_iop_clip_and_zoom_mosaic_third_size_xtrans(uint16_t *const out, const uint16_t *const in,
85 const dt_iop_roi_t *const roi_out,
86 const dt_iop_roi_t *const roi_in, const int32_t out_stride,
87 const int32_t in_stride, const uint8_t (*const xtrans)[6]);
88
89void dt_iop_clip_and_zoom_mosaic_third_size_xtrans_f(float *const out, const float *const in,
90 const dt_iop_roi_t *const roi_out,
91 const dt_iop_roi_t *const roi_in, const int32_t out_stride,
92 const int32_t in_stride, const uint8_t (*const xtrans)[6]);
93
95 const struct dt_iop_roi_t *const roi_out,
96 const struct dt_iop_roi_t *const roi_in,
97 const int32_t out_stride,
98 const int32_t in_stride);
99
100void dt_iop_clip_and_zoom_demosaic_half_size_f(float *out, const float *const in,
101 const struct dt_iop_roi_t *const roi_out,
102 const struct dt_iop_roi_t *const roi_in, const int32_t out_stride,
103 const int32_t in_stride, const uint32_t filters);
104
108 const struct dt_iop_roi_t *const roi_out,
109 const struct dt_iop_roi_t *const roi_in,
110 const int32_t out_stride, const int32_t in_stride,
111 const uint8_t (*const xtrans)[6]);
112
114void dt_iop_clip_and_zoom_8(const uint8_t *i, int32_t ix, int32_t iy, int32_t iw, int32_t ih, int32_t ibw,
115 int32_t ibh, uint8_t *o, int32_t ox, int32_t oy, int32_t ow, int32_t oh,
116 int32_t obw, int32_t obh);
117
120
123void dt_iop_estimate_cubic(const float x[4], const float y[4], float a[4]);
124
126static inline float dt_iop_eval_cubic(const float *const a, const float x)
127{
128 // could be sse4.1 _mm_dot_ps
129 const float x4[4] = { x * x * x, x * x, x, 1.0f };
130 return a[3] * x4[3] + a[2] * x4[2] + a[1] * x4[1] + a[0] * x4[0];
131}
132
135static inline void dt_iop_estimate_exp(const float *const x, const float *const y, const int num, float *coeff)
136{
137 // map every thing to y = y0*(x/x0)^g
138 // and fix (x0,y0) as the last point.
139 // assume (x,y) pairs are ordered by ascending x, so this is the last point:
140 const float x0 = x[num - 1], y0 = y[num - 1];
141
142 float g = 0.0f;
143 int cnt = 0;
144 // solving for g yields
145 // g = log(y/y0)/log(x/x0)
146 //
147 // average that over the course of the other samples:
148 for(int k = 0; k < num - 1; k++)
149 {
150 const float yy = y[k] / y0, xx = x[k] / x0;
151 if(yy > 0.0f && xx > 0.0f)
152 {
153 const float gg = logf(y[k] / y0) / logf(x[k] / x0);
154 g += gg;
155 cnt++;
156 }
157 }
158 if(cnt)
159 g *= 1.0f / cnt;
160 else
161 g = 1.0f;
162 coeff[0] = 1.0f / x0;
163 coeff[1] = y0;
164 coeff[2] = g;
165}
166
167
170static inline float dt_iop_eval_exp(const float *const coeff, const float x)
171{
172 return coeff[1] * powf(x * coeff[0], coeff[2]);
173}
174
175
177__OMP_DECLARE_SIMD__(uniform(width, height) aligned(ivoid, ovoid:64))
178static inline void dt_iop_alpha_copy(const void *const ivoid,
179 void *const ovoid,
180 const size_t width, const size_t height)
181{
182 const float *const __restrict__ in = (const float *const)ivoid;
183 float *const __restrict__ out = (float *const)ovoid;
184 __OMP_FOR_SIMD__(aligned(out, in:64) )
185 for(size_t k = 3; k < width * height * 4; k += 4)
186 out[k] = in[k];
187}
188
190static inline int FC(const size_t row, const size_t col, const uint32_t filters)
191{
192 return filters >> (((row << 1 & 14) + (col & 1)) << 1) & 3;
193}
194
195#define RED 0
196#define GREEN 1
197#define BLUE 2
198#define ALPHA 3
199
201static inline int FCxtrans(const int row, const int col, const dt_iop_roi_t *const roi,
202 const uint8_t (*const xtrans)[6])
203{
204 // Add +600 (which must be a multiple of CFA width 6) as offset can
205 // be negative and need to ensure a non-negative array index. The
206 // negative offsets in current code come from the demosaic iop:
207 // Markesteijn 1-pass (-12), Markesteijn 3-pass (-17), and VNG (-2).
208 int irow = row + 600;
209 int icol = col + 600;
210 assert(irow >= 0 && icol >= 0);
211
212 if(!IS_NULL_PTR(roi))
213 {
214 irow += roi->y;
215 icol += roi->x;
216 }
217
218 return xtrans[irow % 6][icol % 6];
219}
220
221
223static inline int fcol(const int row, const int col, const uint32_t filters, const uint8_t (*const xtrans)[6])
224{
225 if(filters == 9)
226 return FCxtrans(row, col, NULL, xtrans);
227 else
228 return FC(row, col, filters);
229}
230
231#ifdef __cplusplus
232}
233#endif
234
235#endif // DT_DEVELOP_IMAGEOP_MATH_H
236
237// clang-format off
238// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
239// vim: shiftwidth=2 expandtab tabstop=2 cindent
240// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
241// clang-format on
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static const float x
const float *const const float coeff[3]
static dt_aligned_pixel_t rgb
static const int row
dt_image_orientation_t
Definition image.h:216
void dt_iop_clip_and_zoom_8(const uint8_t *i, int32_t ix, int32_t iy, int32_t iw, int32_t ih, int32_t ibw, int32_t ibh, uint8_t *o, int32_t ox, int32_t oy, int32_t ow, int32_t oh, int32_t obw, int32_t obh)
void *const ovoid
void dt_iop_clip_and_zoom_demosaic_passthrough_monochrome_f(float *out, const float *const in, const struct dt_iop_roi_t *const roi_out, const struct dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride)
void dt_iop_clip_and_zoom(float *out, const float *const in, const struct dt_iop_roi_t *const roi_out, const struct dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride)
void *const const size_t const size_t height
void dt_iop_clip_and_zoom_mosaic_half_size_f(float *const out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride, const uint32_t filters)
void dt_iop_clip_and_zoom_demosaic_third_size_xtrans_f(float *out, const float *const in, const struct dt_iop_roi_t *const roi_out, const struct dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride, const uint8_t(*const xtrans)[6])
static int FC(const size_t row, const size_t col, const uint32_t filters)
static float dt_iop_eval_cubic(const float *const a, const float x)
void dt_iop_YCbCr_to_RGB(const dt_aligned_pixel_t yuv, dt_aligned_pixel_t rgb)
void dt_iop_RGB_to_YCbCr(const dt_aligned_pixel_t rgb, dt_aligned_pixel_t yuv)
void dt_iop_flip_and_zoom_8(const uint8_t *in, int32_t iw, int32_t ih, uint8_t *out, int32_t ow, int32_t oh, const dt_image_orientation_t orientation, uint32_t *width, uint32_t *height)
for(size_t k=3;k< width *height *4;k+=4) out[k]
static int FCxtrans(const int row, const int col, const dt_iop_roi_t *const roi, const uint8_t(*const xtrans)[6])
void dt_iop_clip_and_zoom_mosaic_half_size(uint16_t *const out, const uint16_t *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride, const uint32_t filters)
static void dt_iop_estimate_exp(const float *const x, const float *const y, const int num, float *coeff)
void dt_iop_estimate_cubic(const float x[4], const float y[4], float a[4])
static int fcol(const int row, const int col, const uint32_t filters, const uint8_t(*const xtrans)[6])
int dt_iop_clip_and_zoom_roi_cl(int devid, cl_mem dev_out, cl_mem dev_in, const struct dt_iop_roi_t *const roi_out, const struct dt_iop_roi_t *const roi_in)
void dt_iop_clip_and_zoom_demosaic_half_size_f(float *out, const float *const in, const struct dt_iop_roi_t *const roi_out, const struct dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride, const uint32_t filters)
float *const __restrict__ out
static float dt_iop_eval_exp(const float *const coeff, const float x)
void dt_iop_clip_and_zoom_mosaic_third_size_xtrans(uint16_t *const out, const uint16_t *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride, const uint8_t(*const xtrans)[6])
void dt_iop_clip_and_zoom_roi(float *out, const float *const in, const struct dt_iop_roi_t *const roi_out, const struct dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride)
void *const const size_t width
void dt_iop_clip_and_zoom_mosaic_third_size_xtrans_f(float *const out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride, const uint8_t(*const xtrans)[6])
int dt_iop_clip_and_zoom_cl(int devid, cl_mem dev_out, cl_mem dev_in, const struct dt_iop_roi_t *const roi_out, const struct dt_iop_roi_t *const roi_in)
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
#define __OMP_DECLARE_SIMD__(...)
Definition openmp.h:100
#define __OMP_FOR_SIMD__(...)
Definition openmp.h:97
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
Definition simd.h:53
Region of interest passed through the pixelpipe.
Definition format.h:49