Skip to content

Commit ace29c1

Browse files
author
Jed Smith
committed
bugfix to preserve negative color components. rename threshold rgb to cmy. default shadow rolloff to 0.0.
1 parent 2f495a2 commit ace29c1

File tree

7 files changed

+133
-86
lines changed

7 files changed

+133
-86
lines changed

GamutCompress.blink

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,19 @@ kernel GamutCompression : public ImageComputationKernel<ePixelWise> {
197197
// achromatic axis
198198
float ach = max(rgb.x, max(rgb.y, rgb.z));
199199

200-
// achromatic with shadow rolloff below shd_rolloff threshold
201-
float ach_shd = 1.0f-( (1.0f-ach)<(1.0f-shd_rolloff)?(1.0f-ach):(1.0f-shd_rolloff)+shd_rolloff*tanh((((1.0f-ach)-(1.0f-shd_rolloff))/shd_rolloff)));
202-
200+
// achromatic shadow rolloff
201+
float ach_shd;
202+
if (shd_rolloff < 0.004f) {
203+
// disable shadow rolloff functionality.
204+
// values below 0.004 cause strange behavior, actually increasing distance in some cases.
205+
// if ach < 0.0 and shd_rolloff is disabled, take absolute value. This preserves negative components after compression.
206+
ach_shd = fabs(ach);
207+
} else {
208+
// lift ach below threshold using a tanh compression function.
209+
// this reduces large distance values in shadow grain, which can cause differences when inverting.
210+
ach_shd = 1.0f-((1.0f-ach)<(1.0f-shd_rolloff)?(1.0f-ach):(1.0f-shd_rolloff)+shd_rolloff*tanh((((1.0f-ach)-(1.0f-shd_rolloff))/shd_rolloff)));
211+
}
212+
203213
// distance from the achromatic axis for each color component aka inverse rgb ratios
204214
// distance is normalized by achromatic, so that 1.0f is at gamut boundary, avoid 0 div
205215
float3 dist = ach_shd == 0 ? float3(0.0f, 0.0f, 0.0f) : (ach-rgb)/ach_shd;

GamutCompress.dctl

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
DEFINE_UI_PARAMS(threshold_r, threshold r, DCTLUI_SLIDER_FLOAT, 0.2f, 0.0f, 0.6f, 0.0f);
2-
DEFINE_UI_PARAMS(threshold_g, threshold g, DCTLUI_SLIDER_FLOAT, 0.2f, 0.0f, 0.6f, 0.0f);
3-
DEFINE_UI_PARAMS(threshold_b, threshold b, DCTLUI_SLIDER_FLOAT, 0.2f, 0.0f, 0.6f, 0.0f);
1+
DEFINE_UI_PARAMS(threshold_c, threshold c, DCTLUI_SLIDER_FLOAT, 0.2f, 0.0f, 0.6f, 0.0f);
2+
DEFINE_UI_PARAMS(threshold_m, threshold m, DCTLUI_SLIDER_FLOAT, 0.2f, 0.0f, 0.6f, 0.0f);
3+
DEFINE_UI_PARAMS(threshold_y, threshold y, DCTLUI_SLIDER_FLOAT, 0.2f, 0.0f, 0.6f, 0.0f);
44
DEFINE_UI_PARAMS(power, power, DCTLUI_SLIDER_FLOAT, 1.2f, 1.0f, 3.0f, 1.0f);
5-
DEFINE_UI_PARAMS(shd_rolloff, shd rolloff, DCTLUI_SLIDER_FLOAT, 0.03f, 0.0f, 0.1f, 0.0f);
5+
DEFINE_UI_PARAMS(shd_rolloff, shd rolloff, DCTLUI_SLIDER_FLOAT, 0.0f, 0.0f, 0.03f, 0.0f);
66
DEFINE_UI_PARAMS(cyan, cyan, DCTLUI_SLIDER_FLOAT, 0.09f, 0.0f, 1.0f, 0.0f);
77
DEFINE_UI_PARAMS(magenta, magenta, DCTLUI_SLIDER_FLOAT, 0.24f, 0.0f, 1.0f, 0.0f);
88
DEFINE_UI_PARAMS(yellow, yellow, DCTLUI_SLIDER_FLOAT, 0.12f, 0.0f, 1.0f, 0.0f);
@@ -224,9 +224,9 @@ __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p
224224

225225
// thr is the percentage of the core gamut to protect: the complement of threshold.
226226
float3 thr = make_float3(
227-
1.0f-_fmaxf(0.00001, threshold_r),
228-
1.0f-_fmaxf(0.00001, threshold_g),
229-
1.0f-_fmaxf(0.00001, threshold_b));
227+
1.0f-_fmaxf(0.00001, threshold_c),
228+
1.0f-_fmaxf(0.00001, threshold_m),
229+
1.0f-_fmaxf(0.00001, threshold_y));
230230

231231
// lim is the max distance from the gamut boundary that will be compressed
232232
// 0 is a no-op, 1 will compress colors from a distance of 2.0 from achromatic to the gamut boundary
@@ -249,9 +249,19 @@ __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p
249249
// achromatic axis
250250
float ach = _fmaxf(rgb.x, _fmaxf(rgb.y, rgb.z));
251251

252-
// achromatic with shadow rolloff below shd_rolloff threshold
253-
float ach_shd = 1.0f-( (1.0f-ach)<(1.0f-shd_rolloff)?(1.0f-ach):(1.0f-shd_rolloff)+shd_rolloff*_tanhf((((1.0f-ach)-(1.0f-shd_rolloff))/shd_rolloff)));
254-
252+
// achromatic shadow rolloff
253+
float ach_shd;
254+
if (shd_rolloff < 0.004f) {
255+
// disable shadow rolloff functionality.
256+
// values below 0.004 cause strange behavior, actually increasing distance in some cases.
257+
// if ach < 0.0 and shd_rolloff is disabled, take absolute value. This preserves negative components after compression.
258+
ach_shd = _fabs(ach);
259+
} else {
260+
// lift ach below threshold using a tanh compression function.
261+
// this reduces large distance values in shadow grain, which can cause differences when inverting.
262+
ach_shd = 1.0f-((1.0f-ach)<(1.0f-shd_rolloff)?(1.0f-ach):(1.0f-shd_rolloff)+shd_rolloff*_tanhf((((1.0f-ach)-(1.0f-shd_rolloff))/shd_rolloff)));
263+
}
264+
255265
// distance from the achromatic axis for each color component aka inverse rgb ratios
256266
float3 dist;
257267
dist.x = ach_shd == 0.0f ? 0.0f : (ach-rgb.x)/ach_shd;

GamutCompress.fuse

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,23 +106,23 @@ function Create()
106106
INP_Default = 0.0,
107107
})
108108

109-
InThresholdR = self:AddInput("threshold_r", "threshold_r", {
109+
InThresholdR = self:AddInput("threshold_c", "threshold_c", {
110110
LINKID_DataType = "Number",
111111
INPID_InputControl = "SliderControl",
112112
INP_Default = 0.2,
113113
INP_MinAllowed = 0.0001,
114114
INP_MaxScale = 0.6,
115115
})
116116

117-
InThresholdG = self:AddInput("threshold_g", "threshold_g", {
117+
InThresholdG = self:AddInput("threshold_m", "threshold_m", {
118118
LINKID_DataType = "Number",
119119
INPID_InputControl = "SliderControl",
120120
INP_Default = 0.2,
121121
INP_MinAllowed = 0.0001,
122122
INP_MaxScale = 0.6,
123123
})
124124

125-
InThresholdB = self:AddInput("threshold_b", "threshold_b", {
125+
InThresholdB = self:AddInput("threshold_y", "threshold_y", {
126126
LINKID_DataType = "Number",
127127
INPID_InputControl = "SliderControl",
128128
INP_Default = 0.2,
@@ -141,9 +141,9 @@ function Create()
141141
InShdRolloff = self:AddInput("shd rolloff", "shd rolloff", {
142142
LINKID_DataType = "Number",
143143
INPID_InputControl = "SliderControl",
144-
INP_Default = 0.03,
144+
INP_Default = 0.0,
145145
INP_MinAllowed = 0.0,
146-
INP_MaxScale = 0.1,
146+
INP_MaxScale = 0.03,
147147
})
148148

149149
self:BeginControlNest("distance limits", "distance limits", true, {})
@@ -204,9 +204,9 @@ function Process(req)
204204

205205
params.method = InMethod:GetValue(req).Value
206206
params.hexagonal = InHexagonal:GetValue(req).Value
207-
params.threshold_r = InThresholdR:GetValue(req).Value
208-
params.threshold_g = InThresholdG:GetValue(req).Value
209-
params.threshold_b = InThresholdB:GetValue(req).Value
207+
params.threshold_c = InThresholdR:GetValue(req).Value
208+
params.threshold_m = InThresholdG:GetValue(req).Value
209+
params.threshold_y = InThresholdB:GetValue(req).Value
210210
params.power = InPower:GetValue(req).Value
211211
params.shd_rolloff = InShdRolloff:GetValue(req).Value
212212
params.cyan = InCyan:GetValue(req).Value
@@ -235,9 +235,9 @@ end
235235
SolidParams = [[
236236
int method;
237237
int hexagonal;
238-
float threshold_r;
239-
float threshold_g;
240-
float threshold_b;
238+
float threshold_c;
239+
float threshold_m;
240+
float threshold_y;
241241
float power;
242242
float shd_rolloff;
243243
float cyan;
@@ -410,9 +410,9 @@ SolidKernel = [[
410410

411411
// thr is the percentage of the core gamut to protect: the complement of threshold.
412412
float3 thr = make_float3(
413-
1.0f-_fmaxf(0.0001f, params->threshold_r),
414-
1.0f-_fmaxf(0.0001f, params->threshold_g),
415-
1.0f-_fmaxf(0.0001f, params->threshold_b));
413+
1.0f-_fmaxf(0.0001f, params->threshold_c),
414+
1.0f-_fmaxf(0.0001f, params->threshold_m),
415+
1.0f-_fmaxf(0.0001f, params->threshold_y));
416416

417417
// lim is the max distance from the gamut boundary that will be compressed
418418
// 0 is a no-op, 1 will compress colors from a distance of 2.0 from achromatic to the gamut boundary
@@ -435,8 +435,18 @@ SolidKernel = [[
435435
// achromatic axis
436436
float ach = _fmaxf(rgb.x, _fmaxf(rgb.y, rgb.z));
437437

438-
// achromatic with shadow rolloff below shd_rolloff threshold
439-
float ach_shd = 1.0f-( (1.0f-ach)<(1.0f-params->shd_rolloff)?(1.0f-ach):(1.0f-params->shd_rolloff)+params->shd_rolloff*_tanhf((((1.0f-ach)-(1.0f-params->shd_rolloff))/params->shd_rolloff)));
438+
// achromatic shadow rolloff
439+
float ach_shd;
440+
if (params->shd_rolloff < 0.004f) {
441+
// disable shadow rolloff functionality.
442+
// values below 0.004 cause strange behavior, actually increasing distance in some cases.
443+
// if ach < 0.0 and shd_rolloff is disabled, take absolute value. This preserves negative components after compression.
444+
ach_shd = _fabs(ach);
445+
} else {
446+
// lift ach below threshold using a tanh compression function.
447+
// this reduces large distance values in shadow grain, which can cause differences when inverting.
448+
ach_shd = 1.0f-((1.0f-ach)<(1.0f-params->shd_rolloff)?(1.0f-ach):(1.0f-params->shd_rolloff)+params->shd_rolloff*_tanhf((((1.0f-ach)-(1.0f-params->shd_rolloff))/params->shd_rolloff)));
449+
}
440450

441451
// distance from the achromatic axis for each color component aka inverse rgb ratios
442452
float3 dist;

GamutCompress.glsl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,18 @@ void main() {
236236
// achromatic axis
237237
float ach = max(rgb.x, max(rgb.y, rgb.z));
238238

239-
// achromatic with shadow rolloff below shd_rolloff threshold
240-
float ach_shd = 1.0-((1.0-ach)<(1.0-shd_rolloff)?(1.0-ach):(1.0-shd_rolloff)+shd_rolloff*tanh((((1.0-ach)-(1.0-shd_rolloff))/shd_rolloff)));
239+
// achromatic shadow rolloff
240+
float ach_shd;
241+
if (shd_rolloff < 0.004) {
242+
// disable shadow rolloff functionality.
243+
// values below 0.004 cause strange behavior, actually increasing distance in some cases.
244+
// if ach < 0.0 and shd_rolloff is disabled, take absolute value. This preserves negative components after compression.
245+
ach_shd = abs(ach);
246+
} else {
247+
// lift ach below threshold using a tanh compression function.
248+
// this reduces large distance values in shadow grain, which can cause differences when inverting.
249+
ach_shd = 1.0-((1.0-ach)<(1.0-shd_rolloff)?(1.0-ach):(1.0-shd_rolloff)+shd_rolloff*tanh((((1.0-ach)-(1.0-shd_rolloff))/shd_rolloff)));
250+
}
241251

242252
// distance from the achromatic axis for each color component aka inverse rgb ratios
243253
vec3 dist;

0 commit comments

Comments
 (0)