data/kernels/lut3d.h
Rama master · réplica de lectura del repositorio original.
/*
This file is part of darktable,
Copyright (C) 2026 darktable developers.
darktable is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
darktable is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with darktable. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
/* tetrahedral interpolation in a level^3 color LUT of 3 floats per node,
the first channel varying fastest. The coordinates in rgb must already
lie in [0, 1].
Shared by the lut3d module and the LittleCMS path of color in and color
out. Keep this file in the include list hashed into every kernel cache
key in src/common/opencl.c, or an edit here would leave the cached
binaries of the programs including it stale */
static inline float4 dt_lut3d_tetrahedral(const float4 rgb,
global const float *const clut,
const int level)
{
const int level2 = level * level;
float4 rgbd = rgb * (float)(level - 1);
const int4 rgbi = min(max(convert_int4(rgbd), (int4)0), (int4)(level - 2));
// delta r, g, b
rgbd = rgbd - convert_float4(rgbi);
// indexes of P000 to P111 in clut
const int color = rgbi.x + rgbi.y * level + rgbi.z * level2;
const int i000 = color * 3; // P000
const int i100 = i000 + 3; // P100
const int i010 = (color + level) * 3; // P010
const int i110 = i010 + 3; // P110
const int i001 = (color + level2) * 3; // P001
const int i101 = i001 + 3; // P101
const int i011 = (color + level + level2) * 3; // P011
const int i111 = i011 + 3; // P111
// float3 are 16 bytes aligned. So no way to set clut as an array of float3.
const float4 clut000 = (float4)(clut[i000], clut[i000+1], clut[i000+2], 0.0f);
const float4 clut100 = (float4)(clut[i100], clut[i100+1], clut[i100+2], 0.0f);
const float4 clut010 = (float4)(clut[i010], clut[i010+1], clut[i010+2], 0.0f);
const float4 clut110 = (float4)(clut[i110], clut[i110+1], clut[i110+2], 0.0f);
const float4 clut001 = (float4)(clut[i001], clut[i001+1], clut[i001+2], 0.0f);
const float4 clut101 = (float4)(clut[i101], clut[i101+1], clut[i101+2], 0.0f);
const float4 clut011 = (float4)(clut[i011], clut[i011+1], clut[i011+2], 0.0f);
const float4 clut111 = (float4)(clut[i111], clut[i111+1], clut[i111+2], 0.0f);
if(rgbd.x > rgbd.y)
{
if(rgbd.y > rgbd.z)
return (1.0f-rgbd.x)*clut000 + (rgbd.x-rgbd.y)*clut100 + (rgbd.y-rgbd.z)*clut110 + rgbd.z*clut111;
else if(rgbd.x > rgbd.z)
return (1.0f-rgbd.x)*clut000 + (rgbd.x-rgbd.z)*clut100 + (rgbd.z-rgbd.y)*clut101 + rgbd.y*clut111;
else
return (1.0f-rgbd.z)*clut000 + (rgbd.z-rgbd.x)*clut001 + (rgbd.x-rgbd.y)*clut101 + rgbd.y*clut111;
}
else
{
if(rgbd.z > rgbd.y)
return (1.0f-rgbd.z)*clut000 + (rgbd.z-rgbd.y)*clut001 + (rgbd.y-rgbd.x)*clut011 + rgbd.x*clut111;
else if(rgbd.z > rgbd.x)
return (1.0f-rgbd.y)*clut000 + (rgbd.y-rgbd.z)*clut010 + (rgbd.z-rgbd.x)*clut011 + rgbd.x*clut111;
else
return (1.0f-rgbd.y)*clut000 + (rgbd.y-rgbd.x)*clut010 + (rgbd.x-rgbd.z)*clut110 + rgbd.z*clut111;
}
}