forked from ampas/aces-vwg-gamut-mapping-2020
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGamutCompress_blink.nk
66 lines (66 loc) · 7.33 KB
/
GamutCompress_blink.nk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
set cut_paste_input [stack 0]
push $cut_paste_input
Group {
name GamutCompress_blink
label "\[value direction]"
addUserKnob {20 GamutCompress}
addUserKnob {6 use_gpu l "use gpu" t "use gpu for blinkscript node" -STARTLINE}
use_gpu true
addUserKnob {18 threshold t "Percentage of the gamut protect. A value of 0.8 means 20% of the outer gamut will be utilized for gamut compression." R 0.4 1}
threshold {0.815 0.803 0.88}
addUserKnob {6 threshold_panelDropped l "panel dropped state" -STARTLINE +HIDDEN}
addUserKnob {7 power t "Adjust the aggressiveness of the curve. 1 is equal to reinhard. Higher values bias compressed values closer to the gamut boundary." R 1 3}
power 1.2
addUserKnob {26 distance_limit_label l " " t "Specifies the distance beyond the gamut boundary to map to the gamut boundary for each color component." T "<b>distance limit"}
addUserKnob {7 cyan t "Maximum distance beyond the green-blue gamut boundary to compress to the gamut boundary." R 0.001 1}
cyan 0.147
addUserKnob {7 magenta t "Maximum distance beyond the blue-red gamut boundary to compress to the gamut boundary." R 0.001 1}
magenta 0.264
addUserKnob {7 yellow t "Maximum distance beyond the red-green gamut boundary to compress to the gamut boundary." R 0.001 1}
yellow 0.312
addUserKnob {6 overlay l "graph overlay" +STARTLINE}
addUserKnob {22 reset t "Reset knobs to default values. Distance limits are calculated based on an the average of a selection of digital cinema cameras." T "n = nuke.thisNode()\nnuke.root().begin()\ndefaults = \{\n 'threshold': (0.815, 0.803, 0.88),\n 'power': 1.2,\n 'cyan': 0.147,\n 'magenta':0.264,\n 'yellow': 0.312,\n\}\nfor k, v in defaults.items():\n n\[k].setValue(v)" +STARTLINE}
addUserKnob {26 ""}
addUserKnob {4 direction M {forward inverse}}
addUserKnob {20 info_tab l Info}
addUserKnob {26 info_label l " " T "<style> a:link \{ color: #ccc \}</style>\n<font color=#ccc>\n<b>GamutCompress</b><br>\nmaps out of gamut colors back into gamut.\n<br><br><a href=https://github.com/colour-science/aces-vwg-gamut-mapping-2020/tree/master/model>Documentation</a>"}
addUserKnob {26 about_label l " " T "<style> a:link \{ color: #ccc \}</style>\n<font color=#ccc><br>\n<b>About</b><br>\nWritten by <a href=https://github.com/jedypod color=red>Jed Smith</a> <br> with <a href=https://community.acescentral.com/t/rgb-saturation-gamut-mapping-approach-and-a-comp-vfx-perspective>help</a> from the <a href=https://community.acescentral.com/c/aces-development-acesnext/vwg-aces-gamut-mapping-working-group>ACES Gamut Mapping VWG</a>"}
}
Input {
inputs 0
name Input
xpos -40
ypos -10
}
AddChannels {
name AddChannels
xpos -40
ypos 32
}
BlinkScript {
recompileCount 28
ProgramGroup 1
KernelDescription "2 \"GamutCompression\" iterate pixelWise 6a5f3b89121c42d00e282a3ffdc0045cd9579960f1ad979f0b2b2f4a8f3612db 2 \"src\" Read Point \"dst\" Write Point 8 \"threshold\" Float 3 AAAAAAAAAAAAAAAAAAAAAA== \"p\" Float 1 AAAAAA== \"cyan\" Float 1 AAAAAA== \"magenta\" Float 1 AAAAAA== \"yellow\" Float 1 AAAAAA== \"p_Height\" Float 1 AAAAAA== \"invert\" Bool 1 AA== \"overlay\" Bool 1 AA== 8 \"threshold\" 3 1 \"p\" 1 1 \"cyan\" 1 1 \"magenta\" 1 1 \"yellow\" 1 1 \"p_Height\" 1 1 \"invert\" 1 1 \"overlay\" 1 1 2 \"thr\" Float 3 1 AAAAAAAAAAAAAAAAAAAAAA== \"lim\" Float 3 1 AAAAAAAAAAAAAAAAAAAAAA=="
kernelSource "kernel GamutCompression : public ImageComputationKernel<ePixelWise> \{\n Image<eRead, eAccessPoint, eEdgeClamped> src;\n Image<eWrite> dst;\n\n param:\n float3 threshold;\n float p;\n float cyan;\n float magenta;\n float yellow;\n float p_Height;\n bool invert;\n bool overlay;\n\n local:\n float3 thr;\n float3 lim;\n\n void init() \{\n // thr is the percentage of the core gamut to preserve\n thr = float3(min(0.9999f, threshold.x), min(0.9999f, threshold.y), min(0.9999f, threshold.z));\n\n // lim is the max distance from the gamut boundary that will be compressed\n // 0 is a no-op, 1 will compress colors from a distance of 2.0 from achromatic to the gamut boundary\n lim = float3(cyan+1.0f, magenta+1.0f, yellow+1.0f);\n \}\n\n // calculate compressed distance\n float compress(float x, float l, float t) \{\n float cx, s;\n if (x < t) \{\n cx = x;\n \} else \{\n // power(p) compression function plot https://www.desmos.com/calculator/54aytu7hek\n if (l < 1.0001) \{\n return x; // disable compression, avoid nan\n \}\n s = (l-t)/pow(pow((1.0f-t)/(l-t),-p)-1.0f,1.0f/p); // calc y=1 intersect\n if (invert == 0) \{\n cx = t+s*((x-t)/s)/(pow(1.0f+pow((x-t)/s,p),1.0f/p)); // compress\n \} else \{\n if (x > (t + s)) \{\n cx = x; // avoid singularity\n \} else \{\n cx = t+s*pow(-(pow((x-t)/s,p)/(pow((x-t)/s,p)-1.0f)),1.0f/p); // uncompress\n \}\n \}\n \}\n return cx;\n \}\n\n\n void process(int2 pos) \{\n // source pixels\n SampleType(src) rgba = src();\n float3 rgb = float3(rgba.x, rgba.y, rgba.z);\n\n // normalised pixel coordinates\n float2 fpos = float2((float)pos.x / dst.bounds.width(), (float)pos.y / p_Height);\n\n // achromatic axis \n float ach = max(rgb.x, max(rgb.y, rgb.z));\n\n // distance from the achromatic axis for each color component aka inverse rgb ratios\n // distance is normalized by achromatic, so that 1.0f is at gamut boundary, avoid 0 div\n float3 dist = ach == 0 ? float3(0.0f, 0.0f, 0.0f) : (ach-rgb)/fabs(ach);\n\n // compress distance with user controlled parameterized shaper function\n float sat;\n float3 csat, cdist;\n cdist = float3(\n compress(dist.x, lim.x, thr.x),\n compress(dist.y, lim.y, thr.y),\n compress(dist.z, lim.z, thr.z));\n\n // recalculate rgb from compressed distance and achromatic\n // effectively this scales each color component relative to achromatic axis by the compressed distance\n float3 crgb = ach-cdist*fabs(ach);\n\n // Graph overlay method based on one by Paul Dore\n // https://github.com/baldavenger/DCTLs/tree/master/ACES%20TOOLS\n if (overlay) \{\n float3 cramp = float3(\n compress(2.0f * fpos.x, lim.x, thr.x),\n compress(2.0f * fpos.x, lim.y, thr.y),\n compress(2.0f * fpos.x, lim.z, thr.z));\n bool overlay_r = fabs(2.0f * fpos.y - cramp.x) < 0.004f || fabs(fpos.y - 0.5f) < 0.0005f ? true : false;\n bool overlay_g = fabs(2.0f * fpos.y - cramp.y) < 0.004f || fabs(fpos.y - 0.5f) < 0.0005f ? true : false;\n bool overlay_b = fabs(2.0f * fpos.y - cramp.z) < 0.004f || fabs(fpos.y - 0.5f) < 0.0005f ? true : false;\n crgb.x = overlay_g || overlay_b ? 1.0f : crgb.x;\n crgb.y = overlay_b || overlay_r ? 1.0f : crgb.y;\n crgb.z = overlay_r || overlay_g ? 1.0f : crgb.z;\n \}\n\n // write to output\n dst() = float4(crgb.x, crgb.y, crgb.z, rgba.w);\n \}\n\};"
useGPUIfAvailable {{parent.use_gpu}}
rebuild ""
GamutCompression_threshold {{parent.threshold} {parent.threshold} {parent.threshold}}
GamutCompression_p {{parent.power}}
GamutCompression_cyan {{parent.cyan}}
GamutCompression_magenta {{parent.magenta}}
GamutCompression_yellow {{parent.yellow}}
GamutCompression_p_Height {{height}}
GamutCompression_invert {{parent.direction}}
GamutCompression_overlay {{parent.overlay}}
rebuild_finalise ""
name GamutCompress
selected true
xpos -40
ypos 80
}
Output {
name Output
xpos -40
ypos 134
}
end_group