Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
color_conversion.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 copyright (c) 2019 edgardo hoszowski.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include "common.h"
20#include "colorspace.h"
21
22// must be in synch with dt_iop_colorspace_type_t in imageop.h
33
34// must be in synch with dt_colorspaces_iccprofile_info_cl_t
45
46static inline float lerp_lookup_unbounded(const float x, read_only image2d_t lut,
47 constant const float *const unbounded_coeffs,
48 const int n_lut, const int lutsize)
49{
50 // in case the tone curve is marked as linear, return the fast
51 // path to linear unbounded (does not clip x at 1)
52 if(unbounded_coeffs[0] >= 0.0f)
53 {
54 if(x < 1.0f)
55 {
56 const float ft = clamp(x * (float)(lutsize - 1), 0.0f, (float)(lutsize - 1));
57 const int t = ft < lutsize - 2 ? ft : lutsize - 2;
58 const float f = ft - t;
59 const int2 p1 = (int2)((t & 0xff), (t >> 8) + n_lut * 256);
60 const int2 p2 = (int2)(((t + 1) & 0xff), ((t + 1) >> 8) + n_lut * 256);
61 const float l1 = read_imagef(lut, sampleri, p1).x;
62 const float l2 = read_imagef(lut, sampleri, p2).x;
63 return l1 * (1.0f - f) + l2 * f;
64 }
65 else return unbounded_coeffs[1] * native_powr(x*unbounded_coeffs[0], unbounded_coeffs[2]);
66 }
67 else return x;
68}
69
70static inline float lookup(read_only image2d_t lut, const float x)
71{
72 const int xi = clamp((int)(x * 0x10000ul), 0, 0xffff);
73 const int2 p = (int2)((xi & 0xff), (xi >> 8));
74 return read_imagef(lut, sampleri, p).x;
75}
76
77static inline float lookup_unbounded(read_only image2d_t lut, const float x, constant const float *const a)
78{
79 // in case the tone curve is marked as linear, return the fast
80 // path to linear unbounded (does not clip x at 1)
81 if(a[0] >= 0.0f)
82 {
83 if(x < 1.0f)
84 {
85 const int xi = clamp((int)(x * 0x10000ul), 0, 0xffff);
86 const int2 p = (int2)((xi & 0xff), (xi >> 8));
87 return read_imagef(lut, sampleri, p).x;
88 }
89 else return a[1] * native_powr(x*a[0], a[2]);
90 }
91 else return x;
92}
93
94static inline float4 apply_trc_in(const float4 rgb_in,
95 constant const dt_colorspaces_iccprofile_info_cl_t *const profile_info,
96 read_only image2d_t lut)
97{
98 const float R = lerp_lookup_unbounded(rgb_in.x, lut, profile_info->unbounded_coeffs_in[0], 0, profile_info->lutsize);
99 const float G = lerp_lookup_unbounded(rgb_in.y, lut, profile_info->unbounded_coeffs_in[1], 1, profile_info->lutsize);
100 const float B = lerp_lookup_unbounded(rgb_in.z, lut, profile_info->unbounded_coeffs_in[2], 2, profile_info->lutsize);
101 const float a = rgb_in.w;
102 return (float4)(R, G, B, a);
103}
104
105static inline float4 apply_trc_out(const float4 rgb_in,
106 constant const dt_colorspaces_iccprofile_info_cl_t *const profile_info,
107 read_only image2d_t lut)
108{
109 const float R = lerp_lookup_unbounded(rgb_in.x, lut, profile_info->unbounded_coeffs_out[0], 3, profile_info->lutsize);
110 const float G = lerp_lookup_unbounded(rgb_in.y, lut, profile_info->unbounded_coeffs_out[1], 4, profile_info->lutsize);
111 const float B = lerp_lookup_unbounded(rgb_in.z, lut, profile_info->unbounded_coeffs_out[2], 5, profile_info->lutsize);
112 const float a = rgb_in.w;
113 return (float4)(R, G, B, a);
114}
115
116static inline float get_rgb_matrix_luminance(const float4 rgb,
117 constant const dt_colorspaces_iccprofile_info_cl_t *const profile_info,
118 constant const float *const matrix, read_only image2d_t lut)
119{
120 float luminance = 0.f;
121
122 if(profile_info->nonlinearlut)
123 {
124 float4 linear_rgb;
125
126 linear_rgb = apply_trc_in(rgb, profile_info, lut);
127 luminance = matrix[3] * linear_rgb.x + matrix[4] * linear_rgb.y + matrix[5] * linear_rgb.z;
128 }
129 else
130 luminance = matrix[3] * rgb.x + matrix[4] * rgb.y + matrix[5] * rgb.z;
131
132 return luminance;
133}
134
135static inline float4 rgb_matrix_to_xyz(const float4 rgb,
136 constant const dt_colorspaces_iccprofile_info_cl_t *const profile_info,
137 constant const float *const matrix, read_only image2d_t lut)
138{
139 float4 out;
140 if(profile_info->nonlinearlut)
141 {
142 float4 linear_rgb = apply_trc_in(rgb, profile_info, lut);
143 out = matrix_product(linear_rgb, matrix);
144 }
145 else
146 {
147 out = matrix_product(rgb, matrix);
148 }
149 return out;
150}
151
152static inline float dt_camera_rgb_luminance(const float4 rgb)
153{
154 const float4 coeffs = { 0.2225045f, 0.7168786f, 0.0606169f, 0.0f };
155 return dot(rgb, coeffs);
156}
static float4 apply_trc_in(const float4 rgb_in, constant const dt_colorspaces_iccprofile_info_cl_t *const profile_info, read_only image2d_t lut)
Definition color_conversion.h:94
static float4 rgb_matrix_to_xyz(const float4 rgb, constant const dt_colorspaces_iccprofile_info_cl_t *const profile_info, constant const float *const matrix, read_only image2d_t lut)
Definition color_conversion.h:135
static float lookup(read_only image2d_t lut, const float x)
Definition color_conversion.h:70
static float lookup_unbounded(read_only image2d_t lut, const float x, constant const float *const a)
Definition color_conversion.h:77
static float dt_camera_rgb_luminance(const float4 rgb)
Definition color_conversion.h:152
static float get_rgb_matrix_luminance(const float4 rgb, constant const dt_colorspaces_iccprofile_info_cl_t *const profile_info, constant const float *const matrix, read_only image2d_t lut)
Definition color_conversion.h:116
dt_iop_colorspace_type_t
Definition color_conversion.h:24
@ IOP_CS_RAW
Definition color_conversion.h:26
@ IOP_CS_LCH
Definition color_conversion.h:29
@ IOP_CS_JZCZHZ
Definition color_conversion.h:31
@ IOP_CS_RGB
Definition color_conversion.h:28
@ IOP_CS_HSL
Definition color_conversion.h:30
@ IOP_CS_LAB
Definition color_conversion.h:27
@ IOP_CS_NONE
Definition color_conversion.h:25
static float lerp_lookup_unbounded(const float x, read_only image2d_t lut, constant const float *const unbounded_coeffs, const int n_lut, const int lutsize)
Definition color_conversion.h:46
static float4 apply_trc_out(const float4 rgb_in, constant const dt_colorspaces_iccprofile_info_cl_t *const profile_info, read_only image2d_t lut)
Definition color_conversion.h:105
static float4 matrix_product(const float4 xyz, constant const float *const matrix)
Definition colorspace.h:36
#define B(y, x)
Definition colorspaces.c:149
constant sampler_t sampleri
Definition data/kernels/common.h:21
static float f(const float t, const float c, const float x)
Definition graduatednd.c:173
static double dot(int g[], double x, double y, double z)
Definition grain.c:147
#define R
static float clamp(float f, float m, float M)
Definition noiseprofile.c:142
Definition color_conversion.h:36
int lutsize
Definition color_conversion.h:39
float grey
Definition color_conversion.h:43
int nonlinearlut
Definition color_conversion.h:42
float unbounded_coeffs_out[3][3]
Definition color_conversion.h:41
float matrix_out[9]
Definition color_conversion.h:38
float unbounded_coeffs_in[3][3]
Definition color_conversion.h:40
float matrix_in[9]
Definition color_conversion.h:37