├── .gitignore ├── LICENSE ├── README.md ├── display-transforms ├── chromagnon │ ├── ChromagnonView.dctl │ └── ChromagnonView.nk ├── jzdrt │ ├── JzDT.dctl │ ├── JzDT.nk │ └── libDRT.h ├── opendrt │ ├── OpenDRT.dctl │ └── OpenDRT.nk └── tesseract │ ├── Tesseract.dctl │ └── Tesseract.nk ├── look-transforms ├── README.md ├── docs │ └── img │ │ └── ui │ │ ├── LinearGrade_ResolveUI.png │ │ ├── NotoriousSix_HueShift_NukeUI.png │ │ ├── NotoriousSix_HueShift_ResolveUI.png │ │ └── ZoneGrade_Nuke.png └── tools │ ├── nuke │ ├── ChromaValue.nk │ ├── HighlightContrast.nk │ ├── HueContrast.nk │ ├── HueShift.nk │ ├── LinearGrade.nk │ ├── MidtoneContrast.nk │ ├── Nayatani_HK.nk │ ├── Purity.nk │ ├── Saturation.nk │ ├── ShadowContrast.nk │ ├── XLog.nk │ ├── ZoneGrade.nk │ ├── n6ChromaValue.nk │ ├── n6CrossTalk.nk │ ├── n6HueShift.nk │ ├── n6Purity.nk │ └── n6Vibrance.nk │ └── resolve │ ├── HighlightContrast.dctl │ ├── HueContrast.dctl │ ├── LinearGrade.dctl │ ├── MidtoneContrast.dctl │ ├── Nayatani_HK.dctl │ ├── Purity.dctl │ ├── Saturation.dctl │ ├── ShadowContrast.dctl │ ├── XLog.dctl │ ├── ZoneExposureHigh.dctl │ ├── ZoneExposureLow.dctl │ ├── ZoneGrade.dctl │ ├── ZoneSaturation.dctl │ ├── libLMT.h │ ├── n6ChromaValue.dctl │ ├── n6CrossTalk.dctl │ ├── n6HueShift.dctl │ ├── n6Purity.dctl │ └── n6Vibrance.dctl └── utilities ├── GamutConvert.dctl ├── GamutConvertFull.dctl ├── LogConvert.dctl └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open Display Transform 2 | 3 | An open collection of tools and experiments for rendering wide-gamut scene-linear data into an image for an SDR or HDR display device. 4 | 5 | Tools are available as a node for Nuke or Nuke Non-Commercial, and as a DCTL for Resolve Studio. 6 | 7 | ## [Display Transforms](display-transforms) 8 | - **OpenDRT** 9 | A simple and robust display transform designed for smooth tonality, neutral appearance, faithful rendering of input colorimetry where possible. 10 | - **JzDT** 11 | Another experiment using the max(r,g,b) norm and the JzAzBz LMS space. 12 | 13 | ## [Look Transforms](look-transforms) 14 | A collection of tools designed to creatively adjust image appearance. 15 | 16 | 17 | # [Documentation](https://github.com/jedypod/open-display-transform/wiki) 18 | There is a collection of documentation [available on the wiki](https://github.com/jedypod/open-display-transform/wiki). 19 | -------------------------------------------------------------------------------- /display-transforms/jzdrt/JzDT.dctl: -------------------------------------------------------------------------------- 1 | /* JzDT 2 | A simple display transform based on JzAzBz LMS. 3 | Uses a chromaticity-linear rendering, with perceptual chroma compression 4 | hue-path compensation using the JzAzBz perceptual color model. 5 | Uses a max(r,g,b) norm, and a simple tonescale based on the 6 | Michaelis-Menten model of enzyme kinetics, which has been shown to 7 | describe the response of photoreceptor cells to stimulus. 8 | --------------------------------------------------------------------------- 9 | v0.0.1 10 | Written by Jed Smith 11 | https://github.com/jedypod/open-display-transform 12 | 13 | Requires ./libDRT.h 14 | ------------------------------------------------- 15 | */ 16 | 17 | 18 | DEFINE_UI_PARAMS(in_gamut, input gamut, DCTLUI_COMBO_BOX, 1, {ap0, ap1, p3d65, rec2020, rec709, awg, rwg, sgamut3, blackmagicwg, egamut, davinciwg}, {ACES, ACEScg, P3D65, Rec.2020, Rec.709, Alexa Wide Gamut, Red Wide Gamut RGB, Sony SGamut3, Blackmagic Wide Gamut, Filmlight E - Gamut, DaVinci Wide Gamut}) 19 | DEFINE_UI_PARAMS(in_curve, input curve, DCTLUI_COMBO_BOX, 0, {linear, acescct, arri_logc, red_log3g10, sony_slog3, blackmagic_film_gen5, filmlight_tlog, davinci_intermediate}, {Linear, ACEScct, Arri V3LogC, Red Log3G10, Sony SLog3, Blackmagic Film Gen5, Filmlight TLog, DaVinci Intermediate}) 20 | DEFINE_UI_PARAMS(Lw, Lw, DCTLUI_SLIDER_FLOAT, 100.0, 100.0, 4000.0, 10.0) 21 | DEFINE_UI_PARAMS(dch, dechroma, DCTLUI_SLIDER_FLOAT, 0.5, 0.0, 1.0, 0.0) 22 | DEFINE_UI_PARAMS(sat, saturation, DCTLUI_SLIDER_FLOAT, 1.2, 0.5, 1.5, 0.0) 23 | DEFINE_UI_PARAMS(EOTF, inverse eotf, DCTLUI_COMBO_BOX, 2, {lin, srgb, rec1886, dci, pq, hlg}, {Linear, 2.2 Power sRGB Display, 2.4 Power Rec .1886, 2.6 Power DCI, ST 2084 PQ, HLG}) 24 | DEFINE_UI_PARAMS(display_gamut, display gamut, DCTLUI_COMBO_BOX, 4, {Rec2020, P3D65, P3D60, P3DCI, Rec709, DCDM}, {Rec.2020, P3 D65, P3 D60, P3 DCI, Rec.709, DCDM XYZ}) 25 | DEFINE_UI_PARAMS(surround, surround, DCTLUI_COMBO_BOX, 1, {average, dim, dark}, {average, dim, dark}) 26 | DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0) 27 | // DEFINE_UI_PARAMS(euc, euclidean, DCTLUI_CHECK_BOX, 0) // euclidean distance norm 28 | DEFINE_UI_PARAMS(pdch, perceptual dechroma, DCTLUI_CHECK_BOX, 1) 29 | DEFINE_UI_PARAMS(gcmp, gamut compress, DCTLUI_CHECK_BOX, 1) 30 | 31 | #include "libDRT.h" 32 | 33 | 34 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 35 | { 36 | 37 | float3x3 in_to_xyz; 38 | if (in_gamut == ap0) in_to_xyz = matrix_ap0_to_xyz; 39 | else if (in_gamut == ap1) in_to_xyz = matrix_ap1_to_xyz; 40 | else if (in_gamut == p3d65) in_to_xyz = matrix_p3d65_to_xyz; 41 | else if (in_gamut == rec2020) in_to_xyz = matrix_rec2020_to_xyz; 42 | else if (in_gamut == rec709) in_to_xyz = matrix_rec709_to_xyz; 43 | else if (in_gamut == awg) in_to_xyz = matrix_arriwg_to_xyz; 44 | else if (in_gamut == rwg) in_to_xyz = matrix_redwg_to_xyz; 45 | else if (in_gamut == sgamut3) in_to_xyz = matrix_sonysgamut3; 46 | else if (in_gamut == blackmagicwg) in_to_xyz = matrix_blackmagicwg_to_xyz; 47 | else if (in_gamut == egamut) in_to_xyz = matrix_egamut_to_xyz; 48 | else if (in_gamut == davinciwg) in_to_xyz = matrix_davinciwg_to_xyz; 49 | 50 | const float3x3 xyz_to_in = inv_f33(in_to_xyz); 51 | 52 | int tf; 53 | if (in_curve == linear) tf = 0; 54 | else if (in_curve == acescct) tf = 1; 55 | else if (in_curve == arri_logc) tf = 2; 56 | else if (in_curve == red_log3g10) tf = 3; 57 | else if (in_curve == sony_slog3) tf = 4; 58 | else if (in_curve == filmlight_tlog) tf = 5; 59 | else if (in_curve == davinci_intermediate) tf = 6; 60 | else if (in_curve == blackmagic_film_gen5) tf = 7; 61 | 62 | float3x3 xyz_to_display; 63 | if (display_gamut == Rec2020) xyz_to_display = inv_f33(matrix_rec2020_to_xyz); 64 | else if (display_gamut == P3D65) xyz_to_display = inv_f33(matrix_p3d65_to_xyz); 65 | else if (display_gamut == P3D60) xyz_to_display = inv_f33(matrix_p3d60_to_xyz); 66 | else if (display_gamut == P3DCI) xyz_to_display = inv_f33(matrix_p3dci_to_xyz); 67 | else if (display_gamut == Rec709) xyz_to_display = inv_f33(matrix_rec709_to_xyz); 68 | else if (display_gamut == DCDM) xyz_to_display = identity_mtx; 69 | 70 | const float3x3 display_to_xyz = inv_f33(xyz_to_display); 71 | 72 | // Surround compensation 73 | float ps; 74 | if (surround == average) ps = 0.9f; 75 | else if (surround == dim) ps = 0.95f; 76 | else if (surround == dark) ps = 1.0f; 77 | 78 | int eotf; 79 | if (EOTF == lin) eotf = 0; 80 | else if (EOTF == srgb) eotf = 1; 81 | else if (EOTF == rec1886) eotf = 2; 82 | else if (EOTF == dci) eotf = 3; 83 | else if (EOTF == pq) eotf = 4; 84 | else if (EOTF == hlg) eotf = 5; 85 | 86 | const float ds = eotf == 4 ? Lw / 10000.0f : eotf == 5 ? Lw / 1000.0f : 1.0f; 87 | 88 | // Calculate tonescale parameters 89 | const float c = 12.0f * _powf(Lw, -0.86f) + 1.17f; 90 | const float p = c * ps; 91 | const float fl = 1.0f / Lw; 92 | const float sx = 0.016f * _powf(Lw, 0.87f) - 0.17f; 93 | const float sy = 1.036f + 0.00005f * Lw; 94 | 95 | 96 | float3 rgb = make_float3(p_R, p_G, p_B); 97 | 98 | 99 | /* Forward Display Rendering 100 | ----------------------------------------------------------- */ 101 | 102 | if (invert == 0) { 103 | rgb = log2lin(rgb, tf); 104 | float3 xyz = mult_f3_f33(rgb, in_to_xyz); 105 | float3 lms = xyz_to_jzlms(xyz); 106 | 107 | // Tonescale: https://www.desmos.com/calculator/ssx2a1bpsz 108 | float n = _fmaxf(lms.x, _fmaxf(lms.y, lms.z)); 109 | n = _fmaxf(1e-12f, n); 110 | 111 | // if (euc == 1) n = _sqrtf(lms.x * lms.x + lms.y*lms.y+lms.z*lms.z)/_sqrtf(3.0f); 112 | float ns = sy * _powf(n / (n + sx), p); 113 | float nt = ns * ns / (ns + fl); 114 | float ccf = _powf(sx / (n + sx), dch) * sat; 115 | float3 dlms = lms * nt / n; 116 | dlms = nt * (1.0f - ccf) + dlms * ccf; 117 | xyz = jzlms_to_xyz(dlms); 118 | 119 | if (pdch == 1) { 120 | float3 jz = xyz_to_jzazbz(xyz, 1); 121 | if (gcmp == 1) jz.y = compress_parabolic(jz.y, 0.015f, 0.05f, 0.03f); 122 | float3 xyz_ndc = jzlms_to_xyz(lms); 123 | float3 jz_ndc = xyz_to_jzazbz(xyz_ndc, 1); 124 | jz.z = jz_ndc.z; 125 | xyz = jzazbz_to_xyz(jz, 1); 126 | } 127 | 128 | rgb = mult_f3_f33(xyz, xyz_to_display); 129 | rgb *= ds; 130 | 131 | rgb = clampf3(rgb, 0.0f, 1.0f); 132 | float eotf_p = 2.0f + eotf * 0.2f; 133 | if ((eotf > 0) && (eotf < 4)) { 134 | rgb = powf3(rgb, 1.0f / eotf_p); 135 | } else if (eotf == 4) { 136 | rgb = eotf_pq(rgb, 1, 0); 137 | } else if (eotf == 5) { 138 | rgb = eotf_hlg(rgb, 1); 139 | } 140 | } else { 141 | rgb = clampf3(rgb, 0.0f, 1.0f); 142 | float eotf_p = 2.0f + eotf * 0.2f; 143 | if ((eotf > 0) && (eotf < 4)) { 144 | rgb = powf3(rgb, eotf_p); 145 | } else if (eotf == 4) { 146 | rgb = eotf_pq(rgb, 0, 0); 147 | } else if (eotf == 5) { 148 | rgb = eotf_hlg(rgb, 0); 149 | } 150 | rgb /= ds; 151 | float3 xyz = mult_f3_f33(rgb, display_to_xyz); 152 | float3 lms = xyz_to_jzlms(xyz); 153 | 154 | // Inverse Tonescale 155 | float n = _fmaxf(lms.x, _fmaxf(lms.y, lms.z)); 156 | n = _fmaxf(1e-12f, _fminf(0.999f, n)); 157 | float nt = (n + _sqrtf(n * (4.0f * fl + n))) / 2.0f; 158 | float np = _powf(nt / sy, 1.0f / p); 159 | float ns = (np / (1.0f - np)) * sx; 160 | float ccf = ns == 0.0f ? 0.0f : _powf(_powf(nt, 1.0f / p) / (ns / sx), dch) * sat; 161 | float3 dlms = (n * (ccf - 1.0f) + lms) / ccf * ns / n; 162 | 163 | xyz = jzlms_to_xyz(dlms); 164 | if (pdch == 1) { 165 | float3 jz = xyz_to_jzazbz(xyz, 1); 166 | float3 xyz_ndc = jzlms_to_xyz(lms); 167 | float3 jz_ndc = xyz_to_jzazbz(xyz_ndc, 1); 168 | jz.z = jz_ndc.z; 169 | xyz = jzazbz_to_xyz(jz, 1); 170 | } 171 | rgb = mult_f3_f33(xyz, xyz_to_in); 172 | rgb = lin2log(rgb, tf); 173 | } 174 | return rgb; 175 | } -------------------------------------------------------------------------------- /look-transforms/README.md: -------------------------------------------------------------------------------- 1 | # Look Modification 2 | Here you will find some tools to create look modification transforms, as well as some pre-built look presets. 3 | 4 | ## Tools 5 | - **LinearGrade** : [Nuke](tools/nuke/LinearGrade.nk) | [Resolve](tools/resolve/LinearGrade.dctl) 6 | Very simple chromaticity-preserving scene-linear grade operator: `offset -> pivoted contrast -> exposure` 7 | ![LinearGrade UI](docs/img/ui/LinearGrade_ResolveUI.png) 8 | - **ZoneGrade** : [Nuke](tools/nuke/ZoneGrade.nk) | [Resolve](tools/resolve/ZoneGrade.dctl) 9 | A more sophisticated grading tool which allows exposure adjustments over select portions of the input luminance range. Designed for grading in scene-linear, controls are in exposure units around 18% grey. Includes 4 zones: 2 high, 2 low. Named after the Ansel Adams zone system which I remember so well from black and white darkroom photography! 10 | ![ZoneGrade UI](docs/img/ui/ZoneGrade_Nuke.png) 11 | - **NotoriousSix HueShift** : [Nuke](tools/nuke/n6HueShift.nk) | [Resolve](tools/resolve/n6HueShift.dctl) 12 | Hue shift tool. Allows smooth shifts of hue per hue angle, for each of the primary and secondary colors: RGB, CMY. With an additional hue shift for a custom angle and width. Preset is for orange. You can also enable a zoned range selection, which will limit the hue shift to a range of input luminance, depending on how you set the zone range slider. Lower values include more midtones and shadows, higher less. 13 | ![HueShift UI](docs/img/ui/NotoriousSix_HueShift_ResolveUI.png) 14 | - **NotoriousSix Value** : [Nuke](tools/nuke/n6ChromaValue.nk) | [Resolve](tools/resolve/n6ChromaValue.dctl) 15 | Adjusts brightness of color by hue angle. 16 | - **NotoriousSix Vibrance** : [Nuke](tools/nuke/n6Vibrance.nk) | [Resolve](tools/resolve/n6Vibrance.dctl) 17 | Vibrance emulates what happens to hue and chroma in the bottom end of a per-channel contrast increase: Chroma is increased and secondary hues are bent towards primary hues. Image "richness" is increased without slamming into the gamut boundary as with a traditional saturation adjustment. 18 | - **Nayatani_HK** : [Nuke](tools/nuke/Nayatani_HK.nk) | [Resolve](tools/resolve/Nayatani_HK.dctl) 19 | Implements the [Nayatani (1997) model](https://doi.org/10.1002/(SICI)1520-6378(199608)21:4<252::AID-COL1>3.0.CO;2-P) for [Helmholtz-Kohlrausch effect](https://en.wikipedia.org/wiki/Helmholtz%E2%80%93Kohlrausch_effect) compensation. 20 | 21 | ## Look Presets 22 | - Stay tuned ... 23 | -------------------------------------------------------------------------------- /look-transforms/docs/img/ui/LinearGrade_ResolveUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedypod/open-display-transform/ca91e7708dcdfaf47a2a601c241b850effc6dceb/look-transforms/docs/img/ui/LinearGrade_ResolveUI.png -------------------------------------------------------------------------------- /look-transforms/docs/img/ui/NotoriousSix_HueShift_NukeUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedypod/open-display-transform/ca91e7708dcdfaf47a2a601c241b850effc6dceb/look-transforms/docs/img/ui/NotoriousSix_HueShift_NukeUI.png -------------------------------------------------------------------------------- /look-transforms/docs/img/ui/NotoriousSix_HueShift_ResolveUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedypod/open-display-transform/ca91e7708dcdfaf47a2a601c241b850effc6dceb/look-transforms/docs/img/ui/NotoriousSix_HueShift_ResolveUI.png -------------------------------------------------------------------------------- /look-transforms/docs/img/ui/ZoneGrade_Nuke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedypod/open-display-transform/ca91e7708dcdfaf47a2a601c241b850effc6dceb/look-transforms/docs/img/ui/ZoneGrade_Nuke.png -------------------------------------------------------------------------------- /look-transforms/tools/nuke/ChromaValue.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name ChromaValue 5 | tile_color 0x536177ff 6 | addUserKnob {20 ChromaValue_tab l ChromaValue} 7 | addUserKnob {26 about_label l " " T "\n\nChroma Value created by Jed Smith\n
v0.1.1 | documentation
"} 8 | addUserKnob {41 ex l exposure T Multiply.ex} 9 | addUserKnob {26 ""} 10 | addUserKnob {32 sr l "R" T "knobs this \{o 2\}" +STARTLINE} 11 | addUserKnob {32 sg l "G" -STARTLINE T "knobs this \{o 6\}"} 12 | addUserKnob {32 sb l "B" -STARTLINE T "knobs this \{o 4\}"} 13 | addUserKnob {32 sc l "C" -STARTLINE T "knobs this \{o 5\}"} 14 | addUserKnob {32 sm l "M" -STARTLINE T "knobs this \{o 3\}"} 15 | addUserKnob {32 sy l "Y" -STARTLINE T "knobs this \{o 1\}"} 16 | addUserKnob {41 o l hue T HueAngle.o} 17 | addUserKnob {41 w l width T HueAngle.w} 18 | addUserKnob {26 chroma_lbl l " " T chroma} 19 | addUserKnob {41 chs l "chroma strength" t "How much to affect mid-range purity" T ChromaFactor.chs} 20 | addUserKnob {41 chl l "chroma limit" t "Reduce effect at maximal purity" T ChromaFactor.chl} 21 | addUserKnob {41 estr l "hue strength" t "Adjust falloff from center of hue slice." T Multiply.w} 22 | addUserKnob {26 ""} 23 | addUserKnob {6 ze l zoned t "enable zone limiting." +STARTLINE} 24 | addUserKnob {83 zr l "" -STARTLINE M {low high}} 25 | zr high 26 | addUserKnob {7 zp l "zone range" t "set range affected: higher values affect a larger range" R -4 4} 27 | addUserKnob {41 invert T MultiplyMix.invert} 28 | addUserKnob {26 ""} 29 | addUserKnob {41 maskChannelMask l mask -STARTLINE T NodeWrapper1.maskChannelMask} 30 | addUserKnob {41 invert_mask l invert -STARTLINE T NodeWrapper1.invert_mask} 31 | addUserKnob {41 mix T NodeWrapper1.mix} 32 | } 33 | Input { 34 | inputs 0 35 | name Inputmask 36 | xpos -40 37 | ypos -514 38 | number 1 39 | } 40 | Input { 41 | inputs 0 42 | name Input 43 | xpos -150 44 | ypos -754 45 | } 46 | Dot { 47 | name Dot2 48 | xpos -116 49 | ypos -678 50 | } 51 | set Nc5615a90 [stack 0] 52 | Dot { 53 | name Dot1 54 | xpos -6 55 | ypos -678 56 | } 57 | Expression { 58 | temp_name0 n 59 | temp_expr0 max(1e-12,max(r,g,b)) 60 | temp_name1 to 61 | temp_expr1 (n*n/(n+fl)) 62 | temp_name2 flow 63 | temp_expr2 pow((to/(to+1))/n,p) 64 | temp_name3 fhi 65 | temp_expr3 1-pow((n/(n+1))/n,p) 66 | channel0 {rgba.red -rgba.green -rgba.blue none} 67 | expr0 r 68 | expr1 g 69 | expr2 b 70 | expr3 zr?fhi:flow 71 | name Extract 72 | xpos -40 73 | ypos -562 74 | addUserKnob {20 Params} 75 | addUserKnob {7 fl R 0 0.02} 76 | fl 0.01 77 | addUserKnob {7 p R 0 64} 78 | p {{pow(2,-zp+1)}} 79 | } 80 | push $Nc5615a90 81 | Expression { 82 | temp_name0 M 83 | temp_expr0 max(r,g,b) 84 | temp_name1 C 85 | temp_expr1 M-min(r,g,b) 86 | temp_name2 H 87 | temp_expr2 (C==0?0:r==M?((g-b)/C+6)%6:g==M?(b-r)/C+2:b==M?(r-g)/C+4:0) 88 | temp_name3 h 89 | temp_expr3 (H+o)%6 90 | channel0 {rgba.red rgba.green rgba.blue none} 91 | expr0 h a:link \{ color: #ccc \}\n\nHueContrast v0.0.3
| Part of open-display-transform"} 7 | addUserKnob {26 ""} 8 | addUserKnob {41 m0r l "R low" T Focus.m0r} 9 | addUserKnob {41 m1r l "R high" T Focus.m1r} 10 | addUserKnob {41 m0g l "G low" T Focus.m0g} 11 | addUserKnob {41 m1g l "G high" T Focus.m1g} 12 | addUserKnob {41 m0b l "B low" T Focus.m0b} 13 | addUserKnob {41 m1b l "B high" T Focus.m1b} 14 | addUserKnob {41 sr l "strength r" T Power.sr} 15 | addUserKnob {41 sg l "strength g" T Power.sg} 16 | addUserKnob {41 sb l "strength b" T Power.sb} 17 | addUserKnob {41 wr l "width r" T NarrowRGB.wr} 18 | addUserKnob {41 wg l "width g" T NarrowRGB.wg} 19 | addUserKnob {41 wb l "width b" T NarrowRGB.wb} 20 | addUserKnob {41 ex l bias T Bias.ex} 21 | addUserKnob {26 ""} 22 | addUserKnob {41 maskChannelMask l mask -STARTLINE T NodeWrapper1.maskChannelMask} 23 | addUserKnob {41 invert_mask l invert -STARTLINE T NodeWrapper1.invert_mask} 24 | addUserKnob {41 mix T NodeWrapper1.mix} 25 | } 26 | Input { 27 | inputs 0 28 | name Inputmask 29 | xpos 180 30 | ypos 902 31 | number 1 32 | } 33 | Input { 34 | inputs 0 35 | name Input 36 | xpos 70 37 | ypos 614 38 | } 39 | Dot { 40 | name Dot259 41 | xpos 104 42 | ypos 666 43 | } 44 | set N8be81860 [stack 0] 45 | Dot { 46 | name Dot263 47 | xpos 214 48 | ypos 666 49 | } 50 | Expression { 51 | temp_name0 n 52 | temp_expr0 max(1e-12,max(r,g,b)) 53 | temp_name1 n0 54 | temp_expr1 n<0.18?s0*n**p:p*(n-0.18)+0.18 55 | channel0 rgba 56 | expr0 (n0/(n0+0.66)) 57 | name Bias 58 | xpos 180 59 | ypos 806 60 | addUserKnob {20 Params} 61 | addUserKnob {7 ex l bias t "bias to the extraction range" R -3 3} 62 | addUserKnob {7 p R 0 4} 63 | p {{2**ex}} 64 | addUserKnob {7 s0 R 0 4} 65 | s0 {{pow(0.18,1-p)}} 66 | } 67 | push $N8be81860 68 | Expression { 69 | temp_name0 mx 70 | temp_expr0 max(r,g,b) 71 | expr0 mx==0?0:r/mx 72 | expr1 mx==0?0:g/mx 73 | expr2 mx==0?0:b/mx 74 | name RGBRatios 75 | xpos -40 76 | ypos 662 77 | } 78 | Expression { 79 | temp_name0 mn 80 | temp_expr0 max(0,min(r,g,b)) 81 | expr0 r-mn 82 | expr1 g-mn 83 | expr2 b-mn 84 | name HueChromaRGB 85 | xpos -40 86 | ypos 686 87 | } 88 | Expression { 89 | expr0 r-(g+b)*w.0 90 | expr1 g-(r+b)*w.1 91 | expr2 b-(r+g)*w.2 92 | name NarrowRGB 93 | xpos -40 94 | ypos 710 95 | addUserKnob {20 Params} 96 | addUserKnob {7 wr l "width r"} 97 | wr 0.5 98 | addUserKnob {7 wg l "width g"} 99 | wg 0.5 100 | addUserKnob {7 wb l "width b"} 101 | wb 0.5 102 | addUserKnob {78 w n 3} 103 | w {{1-wr} {1-wg} {1-wb}} 104 | } 105 | Expression { 106 | expr0 r<=0?r:r**(1/sr) 107 | expr1 g<=0?g:g**(1/sg) 108 | expr2 b<=0?b:b**(1/sb) 109 | name Power 110 | xpos -40 111 | ypos 734 112 | addUserKnob {20 Params} 113 | addUserKnob {7 sr l "strength r"} 114 | sr 0.5 115 | addUserKnob {7 sg l "strength g"} 116 | sg 0.5 117 | addUserKnob {7 sb l "strength b"} 118 | sb 0.5 119 | } 120 | Clamp { 121 | channels rgba 122 | name Clamp 123 | xpos -40 124 | ypos 758 125 | } 126 | Copy { 127 | inputs 2 128 | from0 rgba.alpha 129 | to0 rgba.alpha 130 | name Copy16 131 | note_font Helvetica 132 | xpos -40 133 | ypos 801 134 | } 135 | push $N8be81860 136 | MergeExpression { 137 | inputs 2 138 | temp_name0 f0 139 | temp_expr0 Aa*(m1.0-m0.0)+m0.0 140 | temp_name1 f1 141 | temp_expr1 Aa*(m1.1-m0.1)+m0.1 142 | temp_name2 f2 143 | temp_expr2 Aa*(m1.2-m0.2)+m0.2 144 | expr0 r*f1*Ag+r*f2*Ab+r*(1-(Ag+Ab)) 145 | expr1 g*f0*Ar+g*f2*Ab+g*(1-(Ar+Ab)) 146 | expr2 b*f0*Ar+b*f1*Ag+b*(1-(Ar+Ag)) 147 | expr3 f0 148 | maskChannelMask rgba.red 149 | name Focus 150 | xpos 70 151 | ypos 851 152 | addUserKnob {20 Params} 153 | addUserKnob {7 m0r l "R low" R -1 1} 154 | addUserKnob {7 m1r l "R high" R -1 1} 155 | addUserKnob {7 m0g l "G low" R -1 1} 156 | addUserKnob {7 m1g l "G high" R -1 1} 157 | addUserKnob {7 m0b l "B low" R -1 1} 158 | addUserKnob {7 m1b l "B high" R -1 1} 159 | addUserKnob {78 m0 n 3} 160 | m0 {{1-m0r} {1-m0g} {1-m0b}} 161 | addUserKnob {78 m1 n 3} 162 | m1 {{1-m1r} {1-m1g} {1-m1b}} 163 | } 164 | push $N8be81860 165 | NodeWrapper { 166 | inputs 2+1 167 | channels rgb 168 | name NodeWrapper1 169 | xpos 70 170 | ypos 902 171 | } 172 | Output { 173 | name Output 174 | xpos 70 175 | ypos 950 176 | } 177 | end_group 178 | -------------------------------------------------------------------------------- /look-transforms/tools/nuke/HueShift.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name HueShift 5 | tile_color 0x536177ff 6 | addUserKnob {20 ChromaValue_tab l ChromaValue} 7 | addUserKnob {7 sh l shift R -1 1} 8 | addUserKnob {7 str l strength R 0.1 1} 9 | str 0.33 10 | addUserKnob {7 chl l "chroma limit"} 11 | chl 0.33 12 | addUserKnob {26 ""} 13 | addUserKnob {32 sr l "R" T "knobs this \{ho 2\}" +STARTLINE} 14 | addUserKnob {32 sg l "G" -STARTLINE T "knobs this \{ho 6\}"} 15 | addUserKnob {32 sb l "B" -STARTLINE T "knobs this \{ho 4\}"} 16 | addUserKnob {32 sc l "C" -STARTLINE T "knobs this \{ho 5\}"} 17 | addUserKnob {32 sm l "M" -STARTLINE T "knobs this \{ho 3\}"} 18 | addUserKnob {32 sy l "Y" -STARTLINE T "knobs this \{ho 1\}"} 19 | addUserKnob {41 ho l hue T HueAngle.ho} 20 | addUserKnob {41 hw l width T HueAngle.hw} 21 | addUserKnob {26 ""} 22 | addUserKnob {6 ze l zoned t "enable zone limiting." +STARTLINE} 23 | addUserKnob {83 zr l "" -STARTLINE M {low high}} 24 | zr high 25 | addUserKnob {7 zp l "zone range" t "set range affected: higher values affect a larger range" R -4 4} 26 | addUserKnob {6 invert +STARTLINE} 27 | addUserKnob {26 ""} 28 | addUserKnob {41 maskChannelMask l mask -STARTLINE T NodeWrapper1.maskChannelMask} 29 | addUserKnob {41 invert_mask l invert -STARTLINE T NodeWrapper1.invert_mask} 30 | addUserKnob {41 mix T NodeWrapper1.mix} 31 | } 32 | Input { 33 | inputs 0 34 | name Inputmask 35 | xpos 290 36 | ypos -394 37 | number 1 38 | } 39 | Input { 40 | inputs 0 41 | name Input 42 | xpos 180 43 | ypos -754 44 | } 45 | Dot { 46 | name Dot7 47 | xpos 214 48 | ypos -678 49 | } 50 | set N6b65dd00 [stack 0] 51 | Dot { 52 | name Dot5 53 | xpos 104 54 | ypos -678 55 | } 56 | set N6b65d600 [stack 0] 57 | Dot { 58 | name Dot9 59 | xpos -6 60 | ypos -678 61 | } 62 | Expression { 63 | channel0 rgba 64 | expr0 max(r,g,b) 65 | channel3 none 66 | name norm 67 | xpos -40 68 | ypos -634 69 | } 70 | set N6b65c800 [stack 0] 71 | Dot { 72 | name Dot6 73 | xpos -6 74 | ypos -486 75 | } 76 | set N6b65c100 [stack 0] 77 | push $N6b65d600 78 | Dot { 79 | name Dot27 80 | xpos 104 81 | ypos -582 82 | } 83 | set N6b62f900 [stack 0] 84 | MergeExpression { 85 | inputs 2 86 | temp_name0 n 87 | temp_expr0 max(1e-12,Ar) 88 | temp_name1 to 89 | temp_expr1 (n*n/(n+fl)) 90 | temp_name2 flow 91 | temp_expr2 pow((to/(to+1))/n,p) 92 | temp_name3 fhi 93 | temp_expr3 1-pow((n/(n+1))/n,p) 94 | channel0 {rgba.red -rgba.green -rgba.blue none} 95 | expr0 r 96 | expr1 g 97 | expr2 b 98 | expr3 zr?fhi:flow 99 | name Extract 100 | xpos 70 101 | ypos -442 102 | addUserKnob {20 Params} 103 | addUserKnob {7 fl R 0 0.02} 104 | fl 0.01 105 | addUserKnob {7 p R 0 64} 106 | p {{pow(2,-zp+1)}} 107 | } 108 | push $N6b65c100 109 | push $N6b65c800 110 | push $N6b65dd00 111 | MergeExpression { 112 | inputs 2 113 | temp_name0 n 114 | temp_expr0 Ar+o 115 | expr0 n==0?0:r/n 116 | expr1 n==0?0:g/n 117 | expr2 n==0?0:b/n 118 | name RGBRatios 119 | xpos 180 120 | ypos -634 121 | addUserKnob {20 Params} 122 | addUserKnob {7 o l offset R 0 0.02} 123 | } 124 | set N6b62eb00 [stack 0] 125 | Dot { 126 | name Dot1 127 | note_font "Helvetica Bold" 128 | note_font_size 24 129 | note_font_color 0xff 130 | selected true 131 | xpos 324 132 | ypos -630 133 | } 134 | set N6b62e400 [stack 0] 135 | Expression { 136 | temp_name0 ch 137 | temp_expr0 min(r,g,b)*(1-f)+f 138 | temp_name1 c 139 | temp_expr1 ch==0?0:min(1,1-min(r/ch,g/ch,b/ch)) 140 | temp_name2 cl 141 | temp_expr2 chl<0.5?c*f0+c*(1-c)*(1-f0):c*pow(1-c,f0) 142 | channel0 rgba 143 | expr0 cl 144 | name hch 145 | xpos 290 146 | ypos -586 147 | addUserKnob {20 Params} 148 | addUserKnob {7 f} 149 | f {{str}} 150 | addUserKnob {7 f0 R 0 10} 151 | f0 {{chl<0.5?max(0,0.5-chl)*2:1/max(1e-3,((1-chl)*2))}} 152 | } 153 | push $N6b62e400 154 | Expression { 155 | temp_name0 M 156 | temp_expr0 max(r,g,b) 157 | temp_name1 C 158 | temp_expr1 M-min(r,g,b) 159 | temp_name2 H 160 | temp_expr2 (C==0?0:r==M?((g-b)/C+6)%6:g==M?(b-r)/C+2:b==M?(r-g)/C+4:0) 161 | temp_name3 h 162 | temp_expr3 (H+ho)%6 163 | channel0 rgba 164 | expr0 h0?pow(m,c-1)*ex:1 30 | expr0 (r+o)*s 31 | expr1 (g+o)*s 32 | expr2 (b+o)*s 33 | name Expression 34 | selected true 35 | xpos -150 36 | ypos -202 37 | addUserKnob {20 Params} 38 | addUserKnob {7 exposure R -6 6} 39 | addUserKnob {7 c l contrast R 0.1 2} 40 | c 1 41 | addUserKnob {7 pivot R -4 4} 42 | addUserKnob {7 off l offset R -0.02 0.02} 43 | addUserKnob {7 ex R 0 10} 44 | ex {{pow(2,exposure)}} 45 | addUserKnob {7 p R 0 4} 46 | p {{0.18*pow(2,pivot)}} 47 | addUserKnob {7 o R -0.02 0.02} 48 | o {{this.off}} 49 | } 50 | Output { 51 | name Output 52 | xpos -150 53 | ypos -154 54 | } 55 | end_group -------------------------------------------------------------------------------- /look-transforms/tools/nuke/MidtoneContrast.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name MidtoneContrast 5 | addUserKnob {20 MidtoneContrast} 6 | addUserKnob {26 about_label l " " T "\n\nMidtoneContrast v0.0.1
| Part of open-display-transform"} 7 | addUserKnob {41 con l contrast T ContrastLinearToeShoulder.con} 8 | addUserKnob {41 pv l pivot T ContrastLinearToeShoulder.pv} 9 | addUserKnob {41 sh l shoulder T ContrastLinearToeShoulder.sh} 10 | addUserKnob {41 toe T ContrastLinearToeShoulder.toe} 11 | addUserKnob {41 rp l "preserve ratios" T MergeExpression1.rp} 12 | addUserKnob {41 invert T ContrastLinearToeShoulder.invert} 13 | addUserKnob {26 "" +STARTLINE} 14 | addUserKnob {41 maskChannelMask l mask -STARTLINE T NodeWrapper1.maskChannelMask} 15 | addUserKnob {41 invert_mask l invert -STARTLINE T NodeWrapper1.invert_mask} 16 | addUserKnob {41 mix T NodeWrapper1.mix} 17 | } 18 | Input { 19 | inputs 0 20 | name Inputmask 21 | xpos 180 22 | ypos 855 23 | number 1 24 | } 25 | Input { 26 | inputs 0 27 | name Input 28 | xpos 70 29 | ypos 710 30 | } 31 | set N70523290 [stack 0] 32 | Expression { 33 | temp_name0 mx 34 | temp_expr0 min(r,g,b) 35 | expr0 invert?r
\nReferences\nSimple estimation methods for the Helmholtz—Kohlrausch effect\nYoshinobu Nayatani\nhttps://doi.org/10.1002/(SICI)1520-6378(199712)22:6<385::AID-COL6>3.0.CO;2-R\n\nClarification of differences between variable achromatic color and variable chromatic color methods in the Helmholtz–Kohlrausch effect\nYoshinobu Nayatani, Hideki Sakai\nhttps://doi.org/10.1002/col.20194\n\nPrediction of the Helmholtz-Kohlrausch effect using the CIELUV formula\nYoshinobu Nayatani, Motohiro Nakajima\nhttps://doi.org/10.1002/(SICI)1520-6378(199608)21:4<252::AID-COL1>3.0.CO;2-P"
 17 |   note_font_size 14
 18 |   note_font_color 0xa8a8a8ff
 19 |   xpos 115
 20 |   ypos -119
 21 |  }
 22 |  Input {
 23 |   inputs 0
 24 |   name Input
 25 |   xpos -40
 26 |   ypos -154
 27 |  }
 28 |  Dot {
 29 |   name Dot1
 30 |   xpos -6
 31 |   ypos -78
 32 |  }
 33 | set N9a8c2b00 [stack 0]
 34 |  Group {
 35 |   name InGamut_to_XYZ
 36 |   tile_color 0x429940ff
 37 |   xpos -150
 38 |   ypos -82
 39 |   addUserKnob {20 InputGamut_to_XYZ_tab l InputGamut_to_XYZ}
 40 |   addUserKnob {4 gamut l "input gamut" M {ACES ACEScg P3D65 Rec.2020 Rec.709 "Alexa WideGamut" "Red WideGamutRGB" "Sony SGamut3" "Filmlight E-Gamut" "DaVinci Wide Gamut" "" ""}}
 41 |   gamut ACEScg
 42 |   addUserKnob {41 matrix T ColorMatrix.matrix}
 43 |   addUserKnob {41 invert -STARTLINE T ColorMatrix.invert}
 44 |  }
 45 |   Input {
 46 |    inputs 0
 47 |    name Input
 48 |    xpos 290
 49 |    ypos -610
 50 |   }
 51 |   Dot {
 52 |    name Dot1
 53 |    xpos 324
 54 |    ypos -546
 55 |   }
 56 | set N9a8c1600 [stack 0]
 57 |   ColorMatrix {
 58 |    matrix {
 59 |        {{"SwitchGamut.input\[value SwitchGamut.which].matrix"} {"SwitchGamut.input\[value SwitchGamut.which].matrix"} {"SwitchGamut.input\[value SwitchGamut.which].matrix"}}
 60 |        {{"SwitchGamut.input\[value SwitchGamut.which].matrix"} {"SwitchGamut.input\[value SwitchGamut.which].matrix"} {"SwitchGamut.input\[value SwitchGamut.which].matrix"}}
 61 |        {{"SwitchGamut.input\[value SwitchGamut.which].matrix"} {"SwitchGamut.input\[value SwitchGamut.which].matrix"} {"SwitchGamut.input\[value SwitchGamut.which].matrix"}}
 62 |      }
 63 |    name ColorMatrix
 64 |    xpos 290
 65 |    ypos -370
 66 |   }
 67 |   Output {
 68 |    name Output
 69 |    xpos 290
 70 |    ypos -250
 71 |   }
 72 | push $N9a8c1600
 73 |   Dot {
 74 |    name Dot391
 75 |    label " *RGB to XYZ D65 CAT: XYZ Scaling"
 76 |    xpos 434
 77 |    ypos -546
 78 |   }
 79 | set N9a8c0100 [stack 0]
 80 |   ColorMatrix {
 81 |    matrix {
 82 |        {0.7006223202 0.1487748027 0.101058729}
 83 |        {0.2741184831 0.8736317754 -0.1477504224}
 84 |        {-0.09896290302 -0.1378953159 1.325916052}
 85 |      }
 86 |    name ColorMatrix30
 87 |    label "DaVinci WG to XYZ D65"
 88 |    xpos 1390
 89 |    ypos -466
 90 |   }
 91 | push $N9a8c0100
 92 |   ColorMatrix {
 93 |    matrix {
 94 |        {0.705396831 0.1640413404 0.08101775497}
 95 |        {0.2801307142 0.8202067018 -0.1003373787}
 96 |        {-0.1037815139 -0.07290726155 1.265746593}
 97 |      }
 98 |    name ColorMatrix29
 99 |    label "Filmlight E-Gamut to XYZ D65"
100 |    xpos 1280
101 |    ypos -466
102 |   }
103 | push $N9a8c0100
104 |   ColorMatrix {
105 |    matrix {
106 |        {0.5990839005 0.2489254922 0.1024464965}
107 |        {0.2150758207 0.8850684166 -0.1001443192}
108 |        {-0.03206584975 -0.02765838802 1.148782015}
109 |      }
110 |    name ColorMatrix31
111 |    label "SonySGamut3 to XYZ D65"
112 |    xpos 1170
113 |    ypos -465
114 |   }
115 | push $N9a8c0100
116 |   ColorMatrix {
117 |    matrix {
118 |        {0.735275209 0.06860940903 0.1465712786}
119 |        {0.2866940796 0.8429790735 -0.1296732426}
120 |        {-0.07968084514 -0.3473432064 1.516081929}
121 |      }
122 |    name ColorMatrix22
123 |    label "REDWideGamutRGB to XYZ D65"
124 |    xpos 1060
125 |    ypos -466
126 |   }
127 | push $N9a8c0100
128 |   ColorMatrix {
129 |    matrix {
130 |        {0.6380076408 0.2147038132 0.09774445742}
131 |        {0.2919537723 0.8238408566 -0.1157948226}
132 |        {0.002798279049 -0.06703422219 1.153293848}
133 |      }
134 |    name ColorMatrix21
135 |    label "Arri AlexaWideGamut to XYZ D65"
136 |    xpos 950
137 |    ypos -466
138 |   }
139 | push $N9a8c0100
140 |   ColorMatrix {
141 |    matrix {
142 |        {0.4123909175 0.3575843573 0.1804807931}
143 |        {0.2126390785 0.7151687145 0.07219231129}
144 |        {0.01933082566 0.1191947833 0.9505321383}
145 |      }
146 |    name ColorMatrix18
147 |    label "Rec709 to XYZ D65"
148 |    xpos 840
149 |    ypos -466
150 |   }
151 | push $N9a8c0100
152 |   ColorMatrix {
153 |    matrix {
154 |        {0.6369581223 0.1446169168 0.1688809693}
155 |        {0.2627002299 0.6779981256 0.05930171534}
156 |        {4.99410725e-17 0.02807269618 1.060985088}
157 |      }
158 |    name ColorMatrix17
159 |    label "Rec2020 to XYZ D65"
160 |    xpos 730
161 |    ypos -466
162 |   }
163 | push $N9a8c0100
164 |   ColorMatrix {
165 |    matrix {
166 |        {0.4865711331 0.2656677067 0.1982173175}
167 |        {0.2289746404 0.6917386055 0.07928691804}
168 |        {-3.972076965e-17 0.04511338845 1.043944478}
169 |      }
170 |    name ColorMatrix16
171 |    label "P3D65 to XYZ D65"
172 |    xpos 620
173 |    ypos -466
174 |   }
175 | push $N9a8c0100
176 |   ColorMatrix {
177 |    matrix {
178 |        {0.6609312296 0.1336961389 0.1558285803}
179 |        {0.2722287476 0.6740817428 0.05368950963}
180 |        {-0.006018006243 0.004383686464 1.090692043}
181 |      }
182 |    name ColorMatrix1
183 |    label "ACEScg to XYZ D65"
184 |    xpos 510
185 |    ypos -466
186 |   }
187 | push $N9a8c0100
188 |   ColorMatrix {
189 |    matrix {
190 |        {0.9503623843 0 9.346324805e-05}
191 |        {0.3439664543 0.728166163 -0.07213254273}
192 |        {0 0 1.089057803}
193 |      }
194 |    name ColorMatrix2
195 |    label "ACES to XYZ D65"
196 |    xpos 400
197 |    ypos -466
198 |   }
199 |   Switch {
200 |    inputs 10
201 |    which {{gamut}}
202 |    name SwitchGamut
203 |    xpos 400
204 |    ypos -370
205 |   }
206 |  end_group
207 |  Expression {
208 |   temp_name0 f
209 |   temp_expr0 0
210 |   expr0 max(0,r+f)
211 |   expr1 max(0,g+f)
212 |   expr2 max(0,b+f)
213 |   name Clamp
214 |   xpos -150
215 |   ypos -57
216 |  }
217 |  Expression {
218 |   temp_name0 d
219 |   temp_expr0 (r+15*g+3*b)
220 |   temp_name1 L
221 |   temp_expr1 g>_e?116*pow(g,1/3)-16:g*_k
222 |   expr0 L/(n?100:1)
223 |   expr1 d==0?0:4*r/d
224 |   expr2 d==0?0:9*g/d
225 |   name XYZ_to_Luv
226 |   label "XYZ to L*u'v'"
227 |   xpos -150
228 |   ypos -15
229 |   addUserKnob {20 Params}
230 |   addUserKnob {7 _e}
231 |   _e {{216/24389}}
232 |   addUserKnob {7 _k}
233 |   _k {{24389/27}}
234 |   addUserKnob {6 n l normalize +STARTLINE}
235 |   n true
236 |  }
237 |  Expression {
238 |   temp_name0 h
239 |   temp_expr0 atan2(b-w_uv.1,g-w_uv.0)
240 |   temp_name1 th
241 |   temp_expr1 h<0?h+radians(360):h
242 |   temp_name2 q
243 |   temp_expr2 -0.01585-0.03017*cos(th)-0.04556*cos(2*th)-0.02667*cos(3*th)-0.00295*cos(4*th)+0.14592*sin(th)+0.05084*sin(2*th)-0.01900*sin(3*th)-0.00764*sin(4*th)
244 |   temp_name3 S_uv
245 |   temp_expr3 13*hypot(g-w_uv.0,b-w_uv.1)
246 |   channel0 {rgba.red rgba.green rgba.blue none}
247 |   expr0 1/(1+(m*q+0.0872*K_Br)*S_uv)
248 |   name Nayatani1997_
249 |   label "object colors"
250 |   xpos -150
251 |   ypos 33
252 |   addUserKnob {20 Params_tab l Params}
253 |   addUserKnob {4 illum M {D50 D55 D60 D65}}
254 |   illum D65
255 |   addUserKnob {78 w_xy n 2}
256 |   w_xy {{curve(illum) 0.3457 0.33243 0.321626 0.3127} {curve(illum) 0.3585 0.34744 0.337737 0.329}}
257 |   addUserKnob {78 w_uv n 2}
258 |   w_uv {{4*w_xy.0/(-2*w_xy.0+12*w_xy.1+3)} {9*w_xy.1/(-2*w_xy.0+12*w_xy.1+3)}}
259 |   addUserKnob {7 La t "adapting luminance" R 0 200}
260 |   La 63.61
261 |   addUserKnob {4 meth l method M {VAC VCC}}
262 |   meth VCC
263 |   addUserKnob {7 m R -4 4}
264 |   m {{meth?-0.134:-0.866}}
265 |   addUserKnob {7 K_Br R 0 10}
266 |   K_Br {{0.2717*(6.469+6.362*pow(La,0.4495))/(6.469+pow(La,0.4495))}}
267 |  }
268 | push $N9a8c2b00
269 |  MergeExpression {
270 |   inputs 2
271 |   expr0 invert?Br/Ar:Ar*Br
272 |   expr1 invert?Bg/Ag:Ag*Bg
273 |   expr2 invert?Bb/Ab:Ab*Bb
274 |   name MergeExpression1
275 |   xpos -40
276 |   ypos 39
277 |  }
278 |  Output {
279 |   name Output
280 |   xpos -40
281 |   ypos 110
282 |  }
283 | end_group
284 | 


--------------------------------------------------------------------------------
/look-transforms/tools/nuke/Purity.nk:
--------------------------------------------------------------------------------
  1 | set cut_paste_input [stack 0]
  2 | push $cut_paste_input
  3 | Group {
  4 |  name Purity
  5 |  tile_color 0x536177ff
  6 |  addUserKnob {20 Params_tab l Params}
  7 |  addUserKnob {26 about_label l " " T "\n\nPurity created by Jed Smith\n
v0.0.1 | documentation
"} 8 | addUserKnob {41 purity T PivotedPowerCubic.purity} 9 | addUserKnob {41 p l strength T PivotedPowerCubic.p} 10 | addUserKnob {26 ""} 11 | addUserKnob {41 rw l "red weight" T Weights.rw} 12 | addUserKnob {41 bw l "blue weight" T Weights.bw} 13 | } 14 | Input { 15 | inputs 0 16 | name Input 17 | xpos 840 18 | ypos 518 19 | } 20 | Dot { 21 | name Dot3 22 | xpos 874 23 | ypos 570 24 | } 25 | set N905fd3b0 [stack 0] 26 | Expression { 27 | channel0 rgba 28 | expr0 max(r,g,b) 29 | name MaxRGB 30 | xpos 950 31 | ypos 566 32 | } 33 | set N8a410980 [stack 0] 34 | Dot { 35 | name Dot4 36 | xpos 984 37 | ypos 738 38 | } 39 | push $N8a410980 40 | push $N905fd3b0 41 | MergeExpression { 42 | inputs 2 43 | expr0 Ar==0?0:max(-2,Br/Ar) 44 | expr1 Ag==0?0:max(-2,Bg/Ag) 45 | expr2 Ab==0?0:max(-2,Bb/Ab) 46 | name MergeDivideReverse 47 | xpos 840 48 | ypos 590 49 | } 50 | set N49773530 [stack 0] 51 | Expression { 52 | expr0 1-r 53 | expr1 1-g 54 | expr2 1-b 55 | expr3 1-a 56 | name invert 57 | xpos 730 58 | ypos 590 59 | } 60 | Expression { 61 | temp_name2 L 62 | temp_expr2 (r*rw+g*gw+b*bw) 63 | temp_name3 c 64 | temp_expr3 max(r,g,b) 65 | channel0 {rgba.red -rgba.green -rgba.blue none} 66 | expr0 c==0?L:L/c 67 | expr1 max(0,1-L) 68 | expr3 c 69 | name Weights 70 | label "\n" 71 | xpos 730 72 | ypos 614 73 | addUserKnob {20 Params} 74 | addUserKnob {7 rw R 0.05 0.6} 75 | rw 0.25 76 | addUserKnob {7 gw} 77 | gw {{1-(rw+bw)}} 78 | addUserKnob {7 bw R 0.05 0.6} 79 | bw 0.1 80 | } 81 | Expression { 82 | temp_name0 c 83 | temp_expr0 a 84 | temp_name1 cc 85 | temp_expr1 1-c 86 | temp_name2 f0 87 | temp_expr2 c**p*(a0*c+b0)+m 88 | temp_name3 f1 89 | temp_expr3 c<=0?1:(1-cc*(cc**p*(a0*cc+b0)+m))/c 90 | channel0 rgb 91 | expr3 max(0,purity>0?(r*f1+(1-r)):((1-r)*f0+r)) 92 | name PivotedPowerCubic 93 | label https://www.desmos.com/calculator/bdbstdsvvv 94 | xpos 730 95 | ypos 656 96 | addUserKnob {20 Params} 97 | addUserKnob {7 purity R -1 1} 98 | addUserKnob {7 p l power R 0 4} 99 | p 2 100 | addUserKnob {7 m} 101 | m {{1-fabs(purity)}} 102 | addUserKnob {26 ""} 103 | addUserKnob {7 a0 R -10 10} 104 | a0 {{p*(m-1)}} 105 | addUserKnob {7 b0 R -10 10} 106 | b0 {{(1-m)*(p+1)}} 107 | } 108 | push $N49773530 109 | MergeExpression { 110 | inputs 2 111 | temp_name0 f 112 | temp_expr0 Aa 113 | temp_name1 L 114 | temp_expr1 Ag 115 | expr0 L*(1-f)+r*f 116 | expr1 L*(1-f)+g*f 117 | expr2 L*(1-f)+b*f 118 | name ChromaLerp 119 | xpos 840 120 | ypos 686 121 | } 122 | Merge2 { 123 | inputs 2 124 | operation multiply 125 | bbox B 126 | output rgb 127 | name MergeMultiply 128 | xpos 840 129 | ypos 734 130 | } 131 | Output { 132 | name Output 133 | xpos 840 134 | ypos 782 135 | } 136 | end_group 137 | -------------------------------------------------------------------------------- /look-transforms/tools/nuke/Saturation.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name Saturation 5 | tile_color 0x536177ff 6 | addUserKnob {20 Saturation_tab l Saturation} 7 | addUserKnob {26 global_label l " " T global} 8 | addUserKnob {41 sag l sat T Saturation.sag} 9 | addUserKnob {26 huesat_label l " " T hue} 10 | addUserKnob {41 sah l sat T Saturation.sah} 11 | addUserKnob {32 sr l "R" T "knobs this \{ho 2\}" +STARTLINE} 12 | addUserKnob {32 sg l "G" -STARTLINE T "knobs this \{ho 6\}"} 13 | addUserKnob {32 sb l "B" -STARTLINE T "knobs this \{ho 4\}"} 14 | addUserKnob {32 sc l "C" -STARTLINE T "knobs this \{ho 5\}"} 15 | addUserKnob {32 sm l "M" -STARTLINE T "knobs this \{ho 3\}"} 16 | addUserKnob {32 sy l "Y" -STARTLINE T "knobs this \{ho 1\}"} 17 | addUserKnob {41 ho l hue T HueAngle.ho} 18 | addUserKnob {41 w l width T HueAngle.w} 19 | addUserKnob {26 luminance_weights_label l " " T "luminance weights"} 20 | addUserKnob {35 lw_presets l " " t "select luminance weight preset" -STARTLINE M {preset/ACEScg "knobs this \{wr 0.26806405 wb 0.05947147\}" preset/Rec.2020 "knobs this \{wr 0.26270026 wb 0.05930173\}" preset/P3D65 "knobs this \{wr 0.22897467 wb 0.07928693\}" preset/Rec.709 "knobs this \{wr 0.21263911 wb 0.07219233\}"}} 21 | addUserKnob {41 wr T Saturation.wr} 22 | addUserKnob {41 wb T Saturation.wb} 23 | addUserKnob {6 lg l "in log" t "applies saturation in -7 +7 stop lg2 " +STARTLINE} 24 | addUserKnob {41 invert t "invert the saturation adjustment. Warning: not supported with zone limiting, nor with log" T Saturation.invert} 25 | addUserKnob {26 ""} 26 | addUserKnob {26 zonelimit_label l " " T "zone limiting"} 27 | addUserKnob {6 ze l zoned t "enable zone limiting." +STARTLINE} 28 | addUserKnob {83 zr l "" -STARTLINE M {low high}} 29 | addUserKnob {7 zp l "zone range" t "set range affected: higher values affect a larger range" R -4 4} 30 | addUserKnob {26 ""} 31 | addUserKnob {41 maskChannelMask l mask -STARTLINE T NodeWrapper1.maskChannelMask} 32 | addUserKnob {41 invert_mask l invert -STARTLINE T NodeWrapper1.invert_mask} 33 | addUserKnob {41 mix T NodeWrapper1.mix} 34 | } 35 | Input { 36 | inputs 0 37 | name Inputmask 38 | xpos 290 39 | ypos -514 40 | number 1 41 | } 42 | Input { 43 | inputs 0 44 | name Input 45 | xpos 180 46 | ypos -730 47 | } 48 | Dot { 49 | name Dot7 50 | xpos 214 51 | ypos -702 52 | } 53 | set N2adc9910 [stack 0] 54 | Expression { 55 | temp_name0 n 56 | temp_expr0 max(1e-12,max(r,g,b)) 57 | temp_name1 to 58 | temp_expr1 (n*n/(n+fl)) 59 | temp_name2 flow 60 | temp_expr2 pow((to/(to+1))/n,p) 61 | temp_name3 fhi 62 | temp_expr3 1-pow((n/(n+1))/n,p) 63 | channel0 {rgba.red -rgba.green -rgba.blue none} 64 | expr0 r 65 | expr1 g 66 | expr2 b 67 | expr3 zr?fhi:flow 68 | name Extract 69 | xpos 70 70 | ypos -634 71 | addUserKnob {20 Params} 72 | addUserKnob {7 fl R 0 0.02} 73 | fl 0.01 74 | addUserKnob {7 p R 0 64} 75 | p {{pow(2,-zp)}} 76 | } 77 | push $N2adc9910 78 | Expression { 79 | temp_name0 M 80 | temp_expr0 max(r,g,b) 81 | temp_name1 C 82 | temp_expr1 M-min(r,g,b) 83 | temp_name2 H 84 | temp_expr2 (C==0?0:r==M?((g-b)/C+6)%6:g==M?(b-r)/C+2:b==M?(r-g)/C+4:0) 85 | temp_name3 h 86 | temp_expr3 (H+ho)%6 87 | channel0 rgba 88 | expr0 hsp?(log(dr/0.18)/log(2)-mn)/(mx-mn):(dr-sp)/ls+lo 115 | expr1 dg>sp?(log(dg/0.18)/log(2)-mn)/(mx-mn):(dg-sp)/ls+lo 116 | expr2 db>sp?(log(db/0.18)/log(2)-mn)/(mx-mn):(db-sp)/ls+lo 117 | name lin_to_log_lx 118 | xpos 180 119 | ypos -658 120 | disable {{!lg}} 121 | addUserKnob {20 Params} 122 | addUserKnob {7 mn R -12 0} 123 | mn -7 124 | addUserKnob {7 mx R 0 12} 125 | mx 7 126 | addUserKnob {7 sp t "splice point"} 127 | sp {{2**-7}} 128 | addUserKnob {7 lo t "linear offset"} 129 | lo {{(log(sp/0.18)/log(2)-mn)/(mx-mn)}} 130 | addUserKnob {7 ls t "linear slope"} 131 | ls {{sp*(mx-mn)*log(2)}} 132 | } 133 | MergeExpression { 134 | inputs 2 135 | temp_name0 L 136 | temp_expr0 wr*r+wg*g+wb*b 137 | temp_name1 f 138 | temp_expr1 (1-Ar+sah*Ar)*sag 139 | expr0 invert?(L*(f-1)+r)/f:L*(1-f)+r*f 140 | expr1 invert?(L*(f-1)+g)/f:L*(1-f)+g*f 141 | expr2 invert?(L*(f-1)+b)/f:L*(1-f)+b*f 142 | expr3 f 143 | name Saturation 144 | selected true 145 | xpos 180 146 | ypos -634 147 | addUserKnob {20 Params} 148 | addUserKnob {7 sag l saturation R 0 2} 149 | sag 1 150 | addUserKnob {7 sah l saturation R 0 2} 151 | sah 1 152 | addUserKnob {7 wr} 153 | wr 0.23 154 | addUserKnob {7 wg} 155 | wg {{1-(wr+wb)}} 156 | addUserKnob {7 wb} 157 | wb 0.08 158 | addUserKnob {6 invert +STARTLINE} 159 | } 160 | Expression { 161 | temp_name0 dr 162 | temp_expr0 r>lo?0.18*pow(2,(r*(mx-mn)+mn)):ls*(r-lo)+sp 163 | temp_name1 dg 164 | temp_expr1 g>lo?0.18*pow(2,(g*(mx-mn)+mn)):ls*(g-lo)+sp 165 | temp_name2 db 166 | temp_expr2 b>lo?0.18*pow(2,(b*(mx-mn)+mn)):ls*(b-lo)+sp 167 | temp_name3 n 168 | temp_expr3 max(dr,dg,db) 169 | expr0 dr*1.25-n/4 170 | expr1 dg*1.25-n/4 171 | expr2 db*1.25-n/4 172 | name log_to_lin_lx 173 | xpos 180 174 | ypos -610 175 | disable {{!lg}} 176 | addUserKnob {20 Params} 177 | addUserKnob {7 mn R -12 0} 178 | mn -7 179 | addUserKnob {7 mx R 0 12} 180 | mx 7 181 | addUserKnob {7 sp t "splice point"} 182 | sp {{2**-7}} 183 | addUserKnob {7 lo t "linear offset"} 184 | lo {{(log(sp/0.18)/log(2)-mn)/(mx-mn)}} 185 | addUserKnob {7 ls t "linear slope"} 186 | ls {{sp*(mx-mn)*log(2)}} 187 | } 188 | MergeExpression { 189 | inputs 2 190 | temp_name0 f 191 | temp_expr0 ze?Aa:1 192 | expr0 Ar*(1-f)+Br*f 193 | expr1 Ag*(1-f)+Bg*f 194 | expr2 Ab*(1-f)+Bb*f 195 | name Mix1 196 | xpos 180 197 | ypos -561 198 | } 199 | push $N2adc9910 200 | NodeWrapper { 201 | inputs 2+1 202 | channels rgb 203 | name NodeWrapper1 204 | xpos 180 205 | ypos -514 206 | } 207 | Output { 208 | name Output 209 | xpos 180 210 | ypos -466 211 | } 212 | end_group -------------------------------------------------------------------------------- /look-transforms/tools/nuke/ShadowContrast.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name ShadowContrast 5 | addUserKnob {20 ShadowContrast_tab l ShadowContrast} 6 | addUserKnob {41 ex l exposure T expr_ShadowContrast.ex} 7 | addUserKnob {41 str l strength T expr_ShadowContrast.str} 8 | addUserKnob {41 invert T expr_ShadowContrast.invert} 9 | addUserKnob {26 ""} 10 | addUserKnob {41 maskChannelMask l mask -STARTLINE T expr_ShadowContrast.maskChannelMask} 11 | addUserKnob {41 invert_mask l invert -STARTLINE T expr_ShadowContrast.invert_mask} 12 | addUserKnob {41 mix T expr_ShadowContrast.mix} 13 | } 14 | Input { 15 | inputs 0 16 | name Inputmask 17 | xpos -1140 18 | ypos -106 19 | number 1 20 | } 21 | Input { 22 | inputs 0 23 | name Input 24 | xpos -1250 25 | ypos -154 26 | } 27 | Expression { 28 | inputs 1+1 29 | temp_name0 p0 30 | temp_expr0 max(r,g,b)**2-3*_m*w 31 | temp_name1 p1 32 | temp_expr1 2*max(r,g,b)**2+27*w-9*_m*w 33 | temp_name2 p2 34 | temp_expr2 pow(sqrt(max(r,g,b)**2*p1*p1-4*p0*p0*p0)/2+max(r,g,b)*p1/2,1/3) 35 | temp_name3 s 36 | temp_expr3 invert?((max(r,g,b)**2-3*_m*w)/(3*p2)+p2/3+max(r,g,b)/3)/max(r,g,b):(max(r,g,b)**2+_m*w)/(max(r,g,b)**2+w) 37 | expr0 r*s 38 | expr1 g*s 39 | expr2 b*s 40 | name expr_ShadowContrast 41 | label "https://www.desmos.com/calculator/ubgteikoke\nhttps://colab.research.google.com/drive/1JT_-S96RZyfHPkZ620QUPIRfxmS_rKlx" 42 | xpos -1250 43 | ypos -118 44 | addUserKnob {20 Params} 45 | addUserKnob {7 ex l exposure R -6 0} 46 | addUserKnob {7 str l strength} 47 | str 0.5 48 | addUserKnob {7 _m R 0 4} 49 | _m {{2**ex}} 50 | addUserKnob {7 w} 51 | w {{str**3}} 52 | addUserKnob {6 invert +STARTLINE} 53 | } 54 | Output { 55 | name Output 56 | xpos -1250 57 | ypos -58 58 | } 59 | end_group -------------------------------------------------------------------------------- /look-transforms/tools/nuke/XLog.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Expression { 4 | expr0 invert?rxlog
\nClassic Cineon style log space for grading, similar to Filmlight's T-Log.\nxloghalf
\nCineon style log space with less dynamic range up to 16. suitable for log grading in half float maybe?\nxlogc
\nCamera encoding style log curve with an extended linear section in in the shadows.\n\n" M {presets/xlog "knobs this \{w0 128 w1 1 o 7.5 k 0.06 x0 0 y0 0.075\}" presets/xloghalf "knobs this \{w0 16 w1 1 o 6.7 k 0.05 x0 0 y0 0.092\}" presets/xlogc "knobs this \{w0 64 w1 1 o 7 k 0.18 x0 0.01 y0 0.15\}" ""}} 11 | addUserKnob {7 w0 t "w0 defines the x intersection point at y=w1" R 10 256} 12 | w0 16 13 | addUserKnob {7 w1 R 0 2} 14 | w1 1 15 | addUserKnob {7 o R 0 12} 16 | o 6.7 17 | addUserKnob {7 k t "k = slope on log function at linear extension point (x1, y1)" R 0 0.2} 18 | k 0.05 19 | addUserKnob {7 x0 t "intersection constraint for lower x coordinate" R 0 0.5} 20 | addUserKnob {7 y0 t "intersection constraint for lower y coordinate" R 0 0.5} 21 | y0 0.092 22 | addUserKnob {7 o0 t "x offset: the y asymptote of the log curve" R -0.1 0} 23 | o0 {{-(2**-o)}} 24 | addUserKnob {7 s0 t "s0 = scale factor to satisfy intersection constraint at (x0, y0)" R 0 4} 25 | s0 {{(w1-y0)/log((w0-o0)/(x0-o0))}} 26 | addUserKnob {7 o1 t "y offset to satisfy intersection constraint at (w0, w1)" R -1 1} 27 | o1 {{w1-s0*log(w0-o0)}} 28 | addUserKnob {7 x1 t "x1 is x coordinate of linear extension intercept (controlled by user-specified slope k)" R -1 1} 29 | x1 {{s0*log(k*s0*exp(o1/s0))}} 30 | addUserKnob {7 y1 t "y1 is y coordinate of linear extension intercept" R -1 1} 31 | y1 {{exp((x1-o1)/s0)+o0}} 32 | addUserKnob {7 y2 t "y (x=0) intercept of linear equation" R -1 1} 33 | y2 {{y1-k*x1}} 34 | addUserKnob {6 invert +STARTLINE} 35 | } -------------------------------------------------------------------------------- /look-transforms/tools/nuke/ZoneGrade.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name ZoneGrade 5 | addUserKnob {20 ZoneGrade_tab l ZoneGrade} 6 | addUserKnob {26 global_label l " @b;global" T " \n"} 7 | addUserKnob {7 ge l exposure R -4 4} 8 | addUserKnob {7 go l offset R -0.02 0.02} 9 | addUserKnob {7 gc l contrast R 0.1 2} 10 | gc 1 11 | addUserKnob {7 gcp l pivot R -4 4} 12 | addUserKnob {26 zones_label l "@b;zones" T "\n"} 13 | addUserKnob {20 zones_grp l "" +STARTLINE n -2} 14 | addUserKnob {20 z1_grp l "high / low"} 15 | addUserKnob {26 zone_high_label l " " T high} 16 | addUserKnob {7 he l exposure R -4 4} 17 | addUserKnob {7 hp l pivot R -4 4} 18 | hp -1 19 | addUserKnob {7 hf l falloff} 20 | hf 0.6 21 | addUserKnob {26 zone_low_label l " " T low} 22 | addUserKnob {7 le l exposure R -4 4} 23 | addUserKnob {6 lo_panelDropped l "panel dropped state" -STARTLINE +HIDDEN} 24 | addUserKnob {7 lp l pivot R -4 4} 25 | lp 1 26 | addUserKnob {7 lf l falloff} 27 | lf 0.6 28 | addUserKnob {20 z2_grp l "higher / lower"} 29 | addUserKnob {26 zone_higher_label l " " T higher} 30 | addUserKnob {7 he2 l exposure R -4 4} 31 | addUserKnob {7 hp2 l pivot R -4 4} 32 | hp2 1 33 | addUserKnob {7 hf2 l falloff} 34 | hf2 0.6 35 | addUserKnob {26 zone_lower_label l " " T lower} 36 | addUserKnob {7 le2 l exposure R -4 4} 37 | addUserKnob {6 lo2_panelDropped l "panel dropped state" -STARTLINE +HIDDEN} 38 | addUserKnob {7 lp2 l pivot R -4 4} 39 | lp2 -1 40 | addUserKnob {7 lf2 l falloff} 41 | lf2 0.6 42 | addUserKnob {20 endGroup n -3} 43 | addUserKnob {26 ""} 44 | addUserKnob {41 maskChannelMask l mask T NodeWrapper.maskChannelMask} 45 | addUserKnob {41 invert_mask l invert -STARTLINE T NodeWrapper.invert_mask} 46 | addUserKnob {41 mix T NodeWrapper.mix} 47 | } 48 | Input { 49 | inputs 0 50 | name Inputmask 51 | xpos -40 52 | ypos 62 53 | number 1 54 | } 55 | Input { 56 | inputs 0 57 | name Input 58 | xpos -260 59 | ypos -130 60 | } 61 | set Nd7e1600 [stack 0] 62 | Expression { 63 | temp_name0 n 64 | temp_expr0 max(r,g,b)/p 65 | temp_name1 s 66 | temp_expr1 co==1?_m:n>0?pow(n,co-1)*_m:1 67 | expr0 (r+o)*s 68 | expr1 (g+o)*s 69 | expr2 (b+o)*s 70 | name expr_global 71 | xpos -260 72 | ypos -82 73 | addUserKnob {20 Params} 74 | addUserKnob {7 off l offset R -0.1 0.1} 75 | off {{go}} 76 | addUserKnob {7 ex l exposure R -4 4} 77 | ex {{ge}} 78 | addUserKnob {7 co l contrast R 0.1 2} 79 | co {{gc}} 80 | addUserKnob {7 pv l pivot R -4 4} 81 | pv {{gcp}} 82 | addUserKnob {7 _m R 0 10} 83 | _m {{pow(2,ex)}} 84 | addUserKnob {7 p R 0 4} 85 | p {{0.18*pow(2,pv)}} 86 | addUserKnob {7 o R -0.1 0.1} 87 | o {{this.off}} 88 | } 89 | Expression { 90 | temp_name0 n 91 | temp_expr0 max(r,g,b) 92 | temp_name1 s 93 | temp_expr1 nx1?(_m*(n-x1)+y1)/n:(_a*pow(n,p)+_b)/n 94 | expr0 r*s 95 | expr1 g*s 96 | expr2 b*s 97 | name exp_high 98 | xpos -260 99 | ypos -34 100 | addUserKnob {20 Params} 101 | addUserKnob {7 ex l exposure R -4 4} 102 | ex {{he}} 103 | addUserKnob {7 pv l pivot R -4 4} 104 | pv {{hp}} 105 | addUserKnob {7 fa l falloff} 106 | fa {{hf}} 107 | addUserKnob {7 f R 0 4} 108 | f {{5*pow(fa,1.6)+1}} 109 | addUserKnob {7 p R 0 10} 110 | p {{fabs(ex+f)<1e-8?1e-8:(ex+f)/f}} 111 | addUserKnob {7 _m R 0 10} 112 | _m {{pow(2,ex)}} 113 | addUserKnob {7 t0} 114 | t0 {{0.18*pow(2,pv)}} 115 | addUserKnob {7 _a R -10 10} 116 | _a {{pow(t0,1-p)/p}} 117 | addUserKnob {7 _b R -10 10} 118 | _b {{t0*(1-1/p)}} 119 | addUserKnob {7 x1 R -10 10} 120 | x1 {{t0*pow(2,f)}} 121 | addUserKnob {7 y1 R -10 10} 122 | y1 {{_a*pow(x1,p)+_b}} 123 | } 124 | Expression { 125 | temp_name0 n 126 | temp_expr0 max(r,g,b) 127 | temp_name1 s 128 | temp_expr1 nx1?(_m*(n-x1)+y1)/n:(_a*pow(n,p)+_b)/n 129 | expr0 r*s 130 | expr1 g*s 131 | expr2 b*s 132 | name exp_higher 133 | xpos -260 134 | ypos -10 135 | addUserKnob {20 Params} 136 | addUserKnob {7 ex l exposure R -4 4} 137 | ex {{he2}} 138 | addUserKnob {7 pv l pivot R -4 4} 139 | pv {{hp2}} 140 | addUserKnob {7 fa l falloff} 141 | fa {{hf2}} 142 | addUserKnob {7 f R 0 4} 143 | f {{5*pow(fa,1.6)+1}} 144 | addUserKnob {7 p R 0 10} 145 | p {{fabs(ex+f)<1e-8?1e-8:(ex+f)/f}} 146 | addUserKnob {7 _m R 0 10} 147 | _m {{pow(2,ex)}} 148 | addUserKnob {7 t0} 149 | t0 {{0.18*pow(2,pv)}} 150 | addUserKnob {7 _a R -10 10} 151 | _a {{pow(t0,1-p)/p}} 152 | addUserKnob {7 _b R -10 10} 153 | _b {{t0*(1-1/p)}} 154 | addUserKnob {7 x1 R -10 10} 155 | x1 {{t0*pow(2,f)}} 156 | addUserKnob {7 y1 R -10 10} 157 | y1 {{_a*pow(x1,p)+_b}} 158 | } 159 | Expression { 160 | temp_name0 m 161 | temp_expr0 max(r,g,b) 162 | temp_name1 s 163 | temp_expr1 m>t0?1:pow(m,p)*(_a*m+_b)+_c 164 | expr0 r*s 165 | expr1 g*s 166 | expr2 b*s 167 | name exp_low 168 | xpos -260 169 | ypos 38 170 | addUserKnob {20 Params} 171 | addUserKnob {7 ex l exposure R -4 4} 172 | ex {{le}} 173 | addUserKnob {7 pv l pivot R -3 3} 174 | pv {{lp}} 175 | addUserKnob {7 fa l falloff} 176 | fa {{lf}} 177 | addUserKnob {7 f} 178 | f {{6-5*fa}} 179 | addUserKnob {7 p R 0 10} 180 | p {{min(f/2,f/2*pow(0.5,ex))}} 181 | addUserKnob {7 t0} 182 | t0 {{0.18*pow(2,pv)}} 183 | addUserKnob {7 _a R -10 10} 184 | _a {{p*(_c-1)/(t0**(p+1))}} 185 | addUserKnob {7 _b R -10 10} 186 | _b {{(1-_c)*(p+1)/(t0**p)}} 187 | addUserKnob {7 _c R 0 10} 188 | _c {{pow(2,ex)}} 189 | } 190 | Expression { 191 | temp_name0 m 192 | temp_expr0 max(r,g,b) 193 | temp_name1 s 194 | temp_expr1 m>t0?1:pow(m,p)*(_a*m+_b)+_c 195 | expr0 r*s 196 | expr1 g*s 197 | expr2 b*s 198 | name exp_lower 199 | xpos -260 200 | ypos 62 201 | addUserKnob {20 Params} 202 | addUserKnob {7 ex l exposure R -4 4} 203 | ex {{le2}} 204 | addUserKnob {7 pv l pivot R -3 3} 205 | pv {{lp2}} 206 | addUserKnob {7 fa l falloff} 207 | fa {{lf2}} 208 | addUserKnob {7 f} 209 | f {{6-5*fa}} 210 | addUserKnob {7 p R 0 10} 211 | p {{min(f/2,f/2*pow(0.5,ex))}} 212 | addUserKnob {7 t0} 213 | t0 {{0.18*pow(2,pv)}} 214 | addUserKnob {7 _a R -10 10} 215 | _a {{p*(_c-1)/(t0**(p+1))}} 216 | addUserKnob {7 _b R -10 10} 217 | _b {{(1-_c)*(p+1)/(t0**p)}} 218 | addUserKnob {7 _c R 0 10} 219 | _c {{pow(2,ex)}} 220 | } 221 | push $Nd7e1600 222 | NodeWrapper { 223 | inputs 2+1 224 | channels rgb 225 | name NodeWrapper 226 | xpos -150 227 | ypos 62 228 | } 229 | Output { 230 | name Output 231 | xpos -260 232 | ypos 134 233 | } 234 | end_group -------------------------------------------------------------------------------- /look-transforms/tools/nuke/n6ChromaValue.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name n6ChromaValue 5 | tile_color 0x536177ff 6 | addUserKnob {20 n6ChromaValue_tab l n6ChromaValue} 7 | addUserKnob {26 about_label l " " T "\n\nNotorious Six Chroma Value created by Jed Smith\n
v0.1.0 | documentation
"} 8 | addUserKnob {41 my l yellow T MultiplyCMY.my} 9 | addUserKnob {41 mr l red T MultiplyRGB.mr} 10 | addUserKnob {41 mm l magenta T MultiplyCMY.mm} 11 | addUserKnob {41 mb l blue T MultiplyRGB.mb} 12 | addUserKnob {41 mc l cyan T MultiplyCMY.mc} 13 | addUserKnob {41 mg l green T MultiplyRGB.mg} 14 | addUserKnob {41 hs_rgb l "hue strength rgb" t "Adjust falloff from center of hue slice." T MultiplyRGB.hs_rgb} 15 | addUserKnob {41 hs_cmy l "hue strength cmy" t "Adjust falloff from center of hue slice." T MultiplyCMY.hs_cmy} 16 | addUserKnob {26 chroma_lbl l " " T chroma} 17 | addUserKnob {41 chs l "chroma strength" t "How much to affect mid-range purity" T ChromaFactor.chs} 18 | addUserKnob {41 chl l "chroma limit" t "Reduce effect at maximal purity" T ChromaFactor.chl} 19 | addUserKnob {6 ze l zoned t "enable zone limiting." +STARTLINE} 20 | addUserKnob {83 zr l "" -STARTLINE M {low high}} 21 | zr high 22 | addUserKnob {7 zp l "zone range" t "set range affected: higher values affect a larger range" R -4 4} 23 | addUserKnob {41 invert T MultiplyMix.invert} 24 | addUserKnob {26 ""} 25 | addUserKnob {41 maskChannelMask l mask -STARTLINE T NodeWrapper1.maskChannelMask} 26 | addUserKnob {41 invert_mask l invert -STARTLINE T NodeWrapper1.invert_mask} 27 | addUserKnob {41 mix T NodeWrapper1.mix} 28 | } 29 | Input { 30 | inputs 0 31 | name Inputmask 32 | xpos 70 33 | ypos 614 34 | number 1 35 | } 36 | Input { 37 | inputs 0 38 | name Input 39 | xpos -40 40 | ypos 278 41 | } 42 | Dot { 43 | name Dot1 44 | xpos -6 45 | ypos 330 46 | } 47 | set N22c03760 [stack 0] 48 | Dot { 49 | name Dot2 50 | xpos 104 51 | ypos 522 52 | } 53 | set N1758e800 [stack 0] 54 | Expression { 55 | temp_name0 n 56 | temp_expr0 max(1e-12,max(r,g,b)) 57 | temp_name1 to 58 | temp_expr1 (n*n/(n+fl)) 59 | temp_name2 flow 60 | temp_expr2 pow((to/(to+1))/n,p) 61 | temp_name3 fhi 62 | temp_expr3 1-pow((n/(n+1))/n,p) 63 | channel0 {rgba.red -rgba.green -rgba.blue none} 64 | expr0 r 65 | expr1 g 66 | expr2 b 67 | expr3 zr?fhi:flow 68 | name Extract 69 | xpos 70 70 | ypos 566 71 | addUserKnob {20 Params} 72 | addUserKnob {7 fl R 0 0.02} 73 | fl 0.01 74 | addUserKnob {7 p R 0 64} 75 | p {{pow(2,-zp+1)}} 76 | } 77 | push $N22c03760 78 | Dot { 79 | name Dot6 80 | xpos -226 81 | ypos 330 82 | } 83 | Expression { 84 | temp_name0 M 85 | temp_expr0 max(r,g,b) 86 | temp_name1 C 87 | temp_expr1 M-min(r,g,b) 88 | channel0 {rgba.red rgba.green rgba.blue none} 89 | expr0 (C==0?0:r==M?((g-b)/C+6)%6:g==M?(b-r)/C+2:b==M?(r-g)/C+4:0) 90 | expr3 M<=0?0:C/M 91 | name hue 92 | xpos -260 93 | ypos 350 94 | } 95 | set N17585100 [stack 0] 96 | Expression { 97 | temp_name0 h0 98 | temp_expr0 (r+o0)%6 99 | temp_name1 h1 100 | temp_expr1 (r+o1)%6 101 | temp_name2 h2 102 | temp_expr2 (r+o2)%6 103 | expr0 clamp(h0>c0?(h0-c0-f0)/(c0-(c0+f0)):(h0-(c0-f0))/(c0-(c0-f0))) 104 | expr1 clamp(h1>c1?(h1-c1-f1)/(c1-(c1+f1)):(h1-(c1-f1))/(c1-(c1-f1))) 105 | expr2 clamp(h2>c2?(h2-c2-f2)/(c2-(c2+f2)):(h2-(c2-f2))/(c2-(c2-f2))) 106 | channel3 none 107 | name LinearWindow1 108 | label CMY 109 | xpos -260 110 | ypos 392 111 | addUserKnob {20 Param} 112 | addUserKnob {7 o0 R 0 6} 113 | o0 5 114 | addUserKnob {7 o1 R 0 6} 115 | o1 3 116 | addUserKnob {7 o2 R 0 6} 117 | o2 1 118 | addUserKnob {26 ""} 119 | addUserKnob {7 c0 R 1 3} 120 | c0 2 121 | addUserKnob {7 f0 R 0.2 1.2} 122 | f0 1 123 | addUserKnob {7 c1 R 1 3} 124 | c1 2 125 | addUserKnob {7 f1 R 0.2 1.2} 126 | f1 1 127 | addUserKnob {7 c2 R 1 3} 128 | c2 2 129 | addUserKnob {7 f2 R 0.2 1.2} 130 | f2 1 131 | } 132 | Expression { 133 | temp_name0 pr 134 | temp_expr0 1-pow(1-r,p.r) 135 | temp_name1 pg 136 | temp_expr1 1-pow(1-g,p.g) 137 | temp_name2 pb 138 | temp_expr2 1-pow(1-b,p.b) 139 | channel0 {rgba.red rgba.green rgba.blue none} 140 | expr0 (1-pr+m.r*pr)*(1-pg+m.g*pg)*(1-pb+m.b*pb) 141 | name MultiplyCMY 142 | xpos -260 143 | ypos 446 144 | addUserKnob {20 Params} 145 | addUserKnob {7 mc R -4 4} 146 | addUserKnob {7 mm R -4 4} 147 | addUserKnob {7 my R -4 4} 148 | addUserKnob {18 hs_cmy R 1 4} 149 | hs_cmy 2 150 | addUserKnob {6 hs_cmy_panelDropped l "panel dropped state" -STARTLINE +HIDDEN} 151 | addUserKnob {18 m R 0 4} 152 | m {{2**mc} {2**mm} {2**my}} 153 | addUserKnob {6 m_panelDropped l "panel dropped state" -STARTLINE +HIDDEN} 154 | addUserKnob {18 p R 0 4} 155 | p {{min(hs_cmy,hs_cmy/m)} {min(hs_cmy,hs_cmy/m)} {min(hs_cmy,hs_cmy/m)}} 156 | addUserKnob {6 p_panelDropped l "panel dropped state" -STARTLINE +HIDDEN} 157 | } 158 | push $N17585100 159 | Expression { 160 | temp_name0 h0 161 | temp_expr0 (r+o0)%6 162 | temp_name1 h1 163 | temp_expr1 (r+o1)%6 164 | temp_name2 h2 165 | temp_expr2 (r+o2)%6 166 | expr0 clamp(h0>c0?(h0-c0-f0)/(c0-(c0+f0)):(h0-(c0-f0))/(c0-(c0-f0))) 167 | expr1 clamp(h1>c1?(h1-c1-f1)/(c1-(c1+f1)):(h1-(c1-f1))/(c1-(c1-f1))) 168 | expr2 clamp(h2>c2?(h2-c2-f2)/(c2-(c2+f2)):(h2-(c2-f2))/(c2-(c2-f2))) 169 | channel3 none 170 | name LinearWindow 171 | label RGB 172 | xpos -150 173 | ypos 392 174 | addUserKnob {20 Param} 175 | addUserKnob {7 o0 R 0 6} 176 | o0 2 177 | addUserKnob {7 o1 R 0 6} 178 | o1 6 179 | addUserKnob {7 o2 R 0 6} 180 | o2 4 181 | addUserKnob {26 ""} 182 | addUserKnob {7 c0 R 1 3} 183 | c0 2 184 | addUserKnob {7 f0 R 0.2 1.2} 185 | f0 1 186 | addUserKnob {7 c1 R 1 3} 187 | c1 2 188 | addUserKnob {7 f1 R 0.2 1.2} 189 | f1 1 190 | addUserKnob {7 c2 R 1 3} 191 | c2 2 192 | addUserKnob {7 f2 R 0.2 1.2} 193 | f2 1 194 | } 195 | Expression { 196 | temp_name0 pr 197 | temp_expr0 1-pow(1-r,p.r) 198 | temp_name1 pg 199 | temp_expr1 1-pow(1-g,p.g) 200 | temp_name2 pb 201 | temp_expr2 1-pow(1-b,p.b) 202 | channel0 {rgba.red rgba.green rgba.blue none} 203 | expr0 (1-pr+m.r*pr)*(1-pg+m.g*pg)*(1-pb+m.b*pb) 204 | name MultiplyRGB 205 | xpos -150 206 | ypos 446 207 | addUserKnob {20 Params} 208 | addUserKnob {7 mr R -4 4} 209 | addUserKnob {7 mg R -4 4} 210 | addUserKnob {7 mb R -4 4} 211 | addUserKnob {18 hs_rgb R 1 4} 212 | hs_rgb 2 213 | addUserKnob {6 hs_rgb_panelDropped l "panel dropped state" -STARTLINE +HIDDEN} 214 | addUserKnob {18 m R 0 4} 215 | m {{2**mr} {2**mg} {2**mb}} 216 | addUserKnob {6 m_panelDropped l "panel dropped state" -STARTLINE +HIDDEN} 217 | addUserKnob {18 p R 0 4} 218 | p {{min(hs_rgb,hs_rgb/m)} {min(hs_rgb,hs_rgb/m)} {min(hs_rgb,hs_rgb/m)}} 219 | addUserKnob {6 p_panelDropped l "panel dropped state" -STARTLINE +HIDDEN} 220 | } 221 | Merge2 { 222 | inputs 2 223 | operation multiply 224 | bbox B 225 | output rgb 226 | name Merge1 227 | xpos -150 228 | ypos 495 229 | } 230 | Expression { 231 | temp_name0 cs 232 | temp_expr0 min(1,a)**(1/chs) 233 | temp_name1 cl 234 | temp_expr1 cs*pow(1-cs,chl) 235 | temp_name2 m 236 | temp_expr2 max(1,r) 237 | expr3 cl/(cl*(1-m)+m) 238 | name ChromaFactor 239 | xpos -150 240 | ypos 518 241 | addUserKnob {20 User} 242 | addUserKnob {7 chs} 243 | chs 0.5 244 | addUserKnob {7 chl R 0 4} 245 | } 246 | push $N22c03760 247 | MergeExpression { 248 | inputs 2 249 | temp_name0 f 250 | temp_expr0 1-Aa 251 | expr0 invert?r/(Ar*(1-f)+f):Ar*r*(1-f)+r*f 252 | expr1 invert?g/(Ag*(1-f)+f):Ag*g*(1-f)+g*f 253 | expr2 invert?b/(Ab*(1-f)+f):Ab*b*(1-f)+b*f 254 | name MultiplyMix 255 | xpos -40 256 | ypos 518 257 | addUserKnob {20 User} 258 | addUserKnob {6 invert +STARTLINE} 259 | } 260 | MergeExpression { 261 | inputs 2 262 | temp_name0 f 263 | temp_expr0 ze?Aa:1 264 | expr0 Ar*(1-f)+Br*f 265 | expr1 Ag*(1-f)+Bg*f 266 | expr2 Ab*(1-f)+Bb*f 267 | name Mix 268 | xpos -40 269 | ypos 566 270 | } 271 | push $N1758e800 272 | NodeWrapper { 273 | inputs 2+1 274 | channels rgb 275 | name NodeWrapper1 276 | xpos -40 277 | ypos 614 278 | } 279 | Output { 280 | name Output 281 | xpos -40 282 | ypos 662 283 | } 284 | end_group -------------------------------------------------------------------------------- /look-transforms/tools/nuke/n6CrossTalk.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name n6CrossTalk 5 | addUserKnob {20 n6CrossTalk_tab l n6CrossTalk} 6 | addUserKnob {26 about_label l " " T "\n\nn6CrossTalk created by Jed Smith\n
v0.0.1 | documentation
"} 7 | addUserKnob {20 color_grp l "" +STARTLINE n -2} 8 | addUserKnob {20 rgb_tab l RGB} 9 | addUserKnob {7 rc l "R center" R -1 1} 10 | addUserKnob {7 gc l "G center" R -1 1} 11 | addUserKnob {7 bc l "B center" R -1 1} 12 | addUserKnob {26 ""} 13 | addUserKnob {7 rp l "red power"} 14 | rp 1 15 | addUserKnob {41 r0 l "red 0: Y->M" T ShiftRGB.r0} 16 | addUserKnob {41 r1 l "red 1: Y->M" T ShiftRGB.rb0} 17 | addUserKnob {41 rs l "red scale" T ShiftRGB.s0} 18 | addUserKnob {7 gp l "green power"} 19 | gp 1 20 | addUserKnob {41 g0 l "green 0: C->Y" T ShiftRGB.r1} 21 | addUserKnob {41 g1 l "green 1: C->Y" T ShiftRGB.rb1} 22 | addUserKnob {41 gs l "green scale" T ShiftRGB.s1} 23 | addUserKnob {7 bp l "blue power"} 24 | bp 1 25 | addUserKnob {41 b0 l "blue 0: M->C" T ShiftRGB.r2} 26 | addUserKnob {41 b1 l "blue 1: M->C" T ShiftRGB.rb2} 27 | addUserKnob {41 bs l "blue scale" T ShiftRGB.s2} 28 | addUserKnob {20 cmy_tab l CMY} 29 | addUserKnob {7 cc l "C center" R -1 1} 30 | cc 0.25 31 | addUserKnob {7 mc l "M center" R -1 1} 32 | addUserKnob {7 yc l "Y center" R -1 1} 33 | yc -0.25 34 | addUserKnob {26 ""} 35 | addUserKnob {7 cp l "cyan power"} 36 | cp 1 37 | addUserKnob {41 c0 l "cyan 0: G->B" T ShiftCMY.r0} 38 | addUserKnob {41 c1 l "cyan 1: G->B" T ShiftCMY.rb0} 39 | addUserKnob {41 cs l "cyan scale" T ShiftCMY.s0} 40 | addUserKnob {7 mp l "magenta power"} 41 | mp 1 42 | addUserKnob {41 m0 l "magenta 0: R->B" T ShiftCMY.r1} 43 | addUserKnob {41 m1 l "magenta 1: R->B" T ShiftCMY.rb1} 44 | addUserKnob {41 ms l "magenta scale" T ShiftCMY.s1} 45 | addUserKnob {7 yp l "yellow power"} 46 | yp 1 47 | addUserKnob {41 y0 l "yellow 0: G->R" T ShiftCMY.r2} 48 | addUserKnob {41 y1 l "yellow 1: G->R" T ShiftCMY.rb2} 49 | addUserKnob {41 ys l "yellow scale" T ShiftCMY.s2} 50 | addUserKnob {20 endGroup n -3} 51 | } 52 | Input { 53 | inputs 0 54 | name Input 55 | xpos 1060 56 | ypos 566 57 | } 58 | Dot { 59 | name Dot407 60 | xpos 1094 61 | ypos 618 62 | } 63 | set N7f8ced00 [stack 0] 64 | Expression { 65 | channel0 rgba 66 | expr0 min(r,g,b)*(1-f)+max(r,g,b)*f 67 | name HCH 68 | xpos 1170 69 | ypos 614 70 | addUserKnob {20 Params} 71 | addUserKnob {7 f} 72 | f 0.5 73 | } 74 | Dot { 75 | name Dot410 76 | xpos 1204 77 | ypos 642 78 | } 79 | set N5b75d910 [stack 0] 80 | Dot { 81 | name Dot409 82 | xpos 1204 83 | ypos 834 84 | } 85 | push $N7f8ced00 86 | Expression { 87 | temp_name0 M 88 | temp_expr0 max(r,g,b) 89 | temp_name1 C 90 | temp_expr1 M-min(r,g,b) 91 | channel0 {rgba.red rgba.green rgba.blue none} 92 | expr0 (C==0?0:r==M?((g-b)/C+6)%6:g==M?(b-r)/C+2:b==M?(r-g)/C+4:0) 93 | expr3 M==0?0:C/M 94 | name HueChroma 95 | xpos 950 96 | ypos 614 97 | } 98 | Clamp { 99 | channels alpha 100 | maximum 4 101 | name Clamp1 102 | xpos 950 103 | ypos 640 104 | } 105 | set N633c55e0 [stack 0] 106 | Expression { 107 | temp_name0 h0 108 | temp_expr0 (r+1)%6 109 | temp_name1 h1 110 | temp_expr1 (r+5)%6 111 | temp_name2 h2 112 | temp_expr2 (r+3)%6 113 | expr0 (h0>x1?0:h0>c.0?(1-((h0-c.0)/(x1-c.0))**p0)**p1:h0>x0?(1-((c.0-h0)/(c.0-x0))**p0)**p1:0)*a**(1/p.0) 114 | expr1 (h1>x1?0:h1>c.1?(1-((h1-c.1)/(x1-c.1))**p0)**p1:h1>x0?(1-((c.1-h1)/(c.1-x0))**p0)**p1:0)*a**(1/p.1) 115 | expr2 (h2>x1?0:h2>c.2?(1-((h2-c.2)/(x1-c.2))**p0)**p1:h2>x0?(1-((c.2-h2)/(c.2-x0))**p0)**p1:0)*a**(1/p.2) 116 | name PowerWindowRGB 117 | xpos 840 118 | ypos 686 119 | addUserKnob {20 Params} 120 | addUserKnob {78 c n 3} 121 | c {{1+rc} {1+gc} {1+bc}} 122 | addUserKnob {7 p0 R 1 2} 123 | p0 1.5 124 | addUserKnob {7 p1 R 1 2} 125 | p1 {{p0}} 126 | addUserKnob {7 x0 R 0 2} 127 | addUserKnob {7 x1 R 0 2} 128 | x1 2 129 | addUserKnob {26 ""} 130 | addUserKnob {78 p n 3} 131 | p {{rp} {gp} {bp}} 132 | } 133 | Dot { 134 | name Dot2 135 | xpos 874 136 | ypos 762 137 | } 138 | push $N633c55e0 139 | Expression { 140 | temp_name0 h0 141 | temp_expr0 (r+4)%6 142 | temp_name1 h1 143 | temp_expr1 (r+2)%6 144 | temp_name2 h2 145 | temp_expr2 (r)%6 146 | expr0 (h0>x1?0:h0>c.0?(1-((h0-c.0)/(x1-c.0))**p0)**p1:h0>x0?(1-((c.0-h0)/(c.0-x0))**p0)**p1:0)*a**(1/p.0) 147 | expr1 (h1>x1?0:h1>c.1?(1-((h1-c.1)/(x1-c.1))**p0)**p1:h1>x0?(1-((c.1-h1)/(c.1-x0))**p0)**p1:0)*a**(1/p.1) 148 | expr2 (h2>x1?0:h2>c.2?(1-((h2-c.2)/(x1-c.2))**p0)**p1:h2>x0?(1-((c.2-h2)/(c.2-x0))**p0)**p1:0)*a**(1/p.2) 149 | name PowerWindowCMY 150 | xpos 950 151 | ypos 686 152 | addUserKnob {20 Params} 153 | addUserKnob {78 c n 3} 154 | c {{1+cc} {1+mc} {1+yc}} 155 | addUserKnob {7 p0 R 1 2} 156 | p0 1.5 157 | addUserKnob {7 p1 R 1 2} 158 | p1 {{p0}} 159 | addUserKnob {7 x0 R 0 2} 160 | addUserKnob {7 x1 R 0 2} 161 | x1 2 162 | addUserKnob {26 ""} 163 | addUserKnob {78 p n 3} 164 | p {{cp} {mp} {yp}} 165 | } 166 | Dot { 167 | name Dot1 168 | xpos 984 169 | ypos 714 170 | } 171 | push $N5b75d910 172 | push $N7f8ced00 173 | MergeExpression { 174 | inputs 2 175 | expr0 Ar==0?0:max(-2,Br/Ar) 176 | expr1 Ag==0?0:max(-2,Bg/Ag) 177 | expr2 Ab==0?0:max(-2,Bb/Ab) 178 | name MergeDivideReverse 179 | xpos 1060 180 | ypos 638 181 | } 182 | MergeExpression { 183 | inputs 2 184 | expr0 (s1+1)*(r-max(0,r1)-min(0,rb1))*Ag+(s2+1)*(r+min(0,r2)+max(0,rb2))*Ab+r*(1-(Ag+Ab)) 185 | expr1 (s0+1)*(g-max(0,r0)-min(0,rb0))*Ar+(s2+1)*(g-max(0,r2)-min(0,rb2))*Ab+g*(1-(Ar+Ab)) 186 | expr2 (s0+1)*(b+min(0,r0)+max(0,rb0))*Ar+(s1+1)*(b+min(0,r1)+max(0,rb1))*Ag+b*(1-(Ar+Ag)) 187 | name ShiftCMY 188 | xpos 1060 189 | ypos 710 190 | addUserKnob {20 Params} 191 | addUserKnob {7 r0 R -1 1} 192 | addUserKnob {7 r1 R -1 1} 193 | addUserKnob {7 r2 R -1 1} 194 | addUserKnob {7 rb0 R -1 1} 195 | addUserKnob {7 rb1 R -1 1} 196 | addUserKnob {7 rb2 R -1 1} 197 | addUserKnob {26 ""} 198 | addUserKnob {7 s0 R -1 1} 199 | addUserKnob {7 s1 R -1 1} 200 | addUserKnob {7 s2 R -1 1} 201 | } 202 | MergeExpression { 203 | inputs 2 204 | expr0 (s0+1)*r*Ar+r*(1+min(0,r1))*(1+max(0,rb1))*Ag+r*(1-max(0,r2))*(1-min(0,rb2))*Ab+r*(1-(Ar+Ag+Ab)) 205 | expr1 (s1+1)*g*Ag+g*(1-max(0,r0))*(1-min(0,rb0))*Ar+g*(1+min(0,r2))*(1+max(0,rb2))*Ab+g*(1-(Ar+Ag+Ab)) 206 | expr2 (s2+1)*b*Ab+b*(1+min(0,r0))*(1+max(0,rb0))*Ar+b*(1-max(0,r1))*(1-min(0,rb1))*Ag+b*(1-(Ar+Ag+Ab)) 207 | name ShiftRGB 208 | xpos 1060 209 | ypos 758 210 | addUserKnob {20 Params} 211 | addUserKnob {7 r0 R -1 1} 212 | addUserKnob {7 r1 R -1 1} 213 | addUserKnob {7 r2 R -1 1} 214 | addUserKnob {7 rb0 R -1 1} 215 | addUserKnob {7 rb1 R -1 1} 216 | addUserKnob {7 rb2 R -1 1} 217 | addUserKnob {26 ""} 218 | addUserKnob {7 s0 R -1 1} 219 | addUserKnob {7 s1 R -1 1} 220 | addUserKnob {7 s2 R -1 1} 221 | } 222 | Merge2 { 223 | inputs 2 224 | operation multiply 225 | bbox B 226 | name MergeMultiply 227 | xpos 1060 228 | ypos 830 229 | } 230 | Output { 231 | name Output 232 | xpos 1060 233 | ypos 902 234 | } 235 | end_group 236 | -------------------------------------------------------------------------------- /look-transforms/tools/nuke/n6HueShift.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name N6HueShift 5 | tile_color 0x53617700 6 | addUserKnob {20 HueShift_tab l HueShift} 7 | addUserKnob {26 about_label l " " T "\n\nNotorious Six HueShift created by Jed Smith\n
v0.0.4 | documentation
"} 8 | addUserKnob {26 ""} 9 | addUserKnob {7 sy l yellow R -1 1} 10 | addUserKnob {7 sr l red R -1 1} 11 | addUserKnob {7 sm l magenta R -1 1} 12 | addUserKnob {7 sb l blue R -1 1} 13 | addUserKnob {7 sc l cyan R -1 1} 14 | addUserKnob {7 sg l green R -1 1} 15 | addUserKnob {7 scu l custom R -1 1} 16 | addUserKnob {7 cuh l "custom hue" t "hue angle center for custom hue extraction. 0 is green." R 0 360} 17 | cuh 100 18 | addUserKnob {7 cuw l "custom width" t "width for custom hue angle extraction"} 19 | cuw 0.3 20 | addUserKnob {26 ""} 21 | addUserKnob {7 str l strength R 0.1 1} 22 | str 0.33 23 | addUserKnob {7 chl l "chroma limit"} 24 | chl 0.33 25 | addUserKnob {6 ze l "zone extract" t "effect a limited range of luminance." +STARTLINE} 26 | addUserKnob {4 zr l "" -STARTLINE M {low high ""}} 27 | zr 1 28 | addUserKnob {7 zp l "zone range" t "set range affected: higher values affect a larger range" R -4 4} 29 | addUserKnob {26 ""} 30 | addUserKnob {41 maskChannelMask l mask -STARTLINE T NodeWrapper1.maskChannelMask} 31 | addUserKnob {41 invert_mask l invert -STARTLINE T NodeWrapper1.invert_mask} 32 | addUserKnob {41 mix T NodeWrapper1.mix} 33 | } 34 | Input { 35 | inputs 0 36 | name Inputmask 37 | xpos -150 38 | ypos 278 39 | number 1 40 | } 41 | Input { 42 | inputs 0 43 | name Input 44 | xpos -260 45 | ypos -442 46 | } 47 | Dot { 48 | name Dot104 49 | xpos -226 50 | ypos -366 51 | } 52 | set N6ff09600 [stack 0] 53 | Dot { 54 | name Dot1 55 | xpos -336 56 | ypos -366 57 | } 58 | set N6ff08f00 [stack 0] 59 | Dot { 60 | name Dot105 61 | xpos -446 62 | ypos -366 63 | } 64 | Expression { 65 | channel0 rgba 66 | expr0 max(r,g,b) 67 | channel3 none 68 | name Norm 69 | xpos -480 70 | ypos -346 71 | } 72 | Dot { 73 | name Dot2 74 | xpos -446 75 | ypos -318 76 | } 77 | set Nbcffb900 [stack 0] 78 | Dot { 79 | name Dot106 80 | xpos -446 81 | ypos 162 82 | } 83 | set Nbcffb200 [stack 0] 84 | push $N6ff08f00 85 | Dot { 86 | name Dot4 87 | xpos -336 88 | ypos 114 89 | } 90 | set Nbcffab00 [stack 0] 91 | MergeExpression { 92 | inputs 2 93 | temp_name0 n 94 | temp_expr0 max(1e-12,Ar) 95 | temp_name1 to 96 | temp_expr1 (n*n/(n+fl)) 97 | temp_name2 flow 98 | temp_expr2 pow((to/(to+1))/n,p) 99 | temp_name3 fhi 100 | temp_expr3 1-pow((n/(n+1))/n,p) 101 | channel0 {rgba.red -rgba.green -rgba.blue none} 102 | expr0 r 103 | expr1 g 104 | expr2 b 105 | expr3 zr?fhi:flow 106 | name Extract2 107 | xpos -370 108 | ypos 206 109 | addUserKnob {20 Params} 110 | addUserKnob {7 fl R 0 0.02} 111 | fl 0.004 112 | addUserKnob {7 p R 0 64} 113 | p {{pow(2,-zp)}} 114 | } 115 | push $Nbcffb200 116 | push $Nbcffb900 117 | push $N6ff09600 118 | MergeExpression { 119 | inputs 2 120 | temp_name0 n 121 | temp_expr0 Ar 122 | expr0 n==0?0:r/n 123 | expr1 n==0?0:g/n 124 | expr2 n==0?0:b/n 125 | name RGBRatios 126 | xpos -260 127 | ypos -322 128 | } 129 | Expression { 130 | temp_name0 th 131 | temp_expr0 -1 132 | expr0 max(th,r) 133 | expr1 max(th,g) 134 | expr2 max(th,b) 135 | name ClampMin 136 | xpos -260 137 | ypos -274 138 | } 139 | Dot { 140 | name Dot7 141 | xpos -226 142 | ypos -222 143 | } 144 | set Nbcff8f00 [stack 0] 145 | Dot { 146 | name Dot9 147 | xpos -116 148 | ypos -222 149 | } 150 | set Nbcff8800 [stack 0] 151 | Expression { 152 | temp_name0 ch 153 | temp_expr0 min(r,g,b)*(1-f)+f 154 | temp_name1 c 155 | temp_expr1 ch==0?0:min(1,1-min(r/ch,g/ch,b/ch)) 156 | temp_name2 cl 157 | temp_expr2 chl<0.5?c*f0+c*(1-c)*(1-f0):c*pow(1-c,f0) 158 | channel0 rgba 159 | expr0 cl 160 | name hch 161 | xpos -150 162 | ypos -178 163 | addUserKnob {20 Params} 164 | addUserKnob {7 f} 165 | f {{str}} 166 | addUserKnob {7 f0 R 0 10} 167 | f0 {{chl<0.5?max(0,0.5-chl)*2:1/max(1e-3,((1-chl)*2))}} 168 | } 169 | set Nbcff8100 [stack 0] 170 | push $Nbcff8800 171 | Dot { 172 | name Dot3 173 | xpos 214 174 | ypos -222 175 | } 176 | Expression { 177 | temp_name0 M 178 | temp_expr0 max(r,g,b) 179 | temp_name1 C 180 | temp_expr1 M-min(r,g,b) 181 | channel0 rgba 182 | expr0 (C==0?0:r==M?((g-b)/C+6)%6:g==M?(b-r)/C+2:b==M?(r-g)/C+4:0) 183 | name hue 184 | xpos 180 185 | ypos -178 186 | } 187 | Dot { 188 | name Dot8 189 | xpos 214 190 | ypos -102 191 | } 192 | set Nbc7deb00 [stack 0] 193 | Dot { 194 | name Dot5 195 | xpos 214 196 | ypos -30 197 | } 198 | set N7b7a8800 [stack 0] 199 | Dot { 200 | name Dot6 201 | xpos 214 202 | ypos 42 203 | } 204 | Expression { 205 | temp_name0 h 206 | temp_expr0 (r+o)%6 207 | channel0 rgba 208 | expr0 hc0?(h0-c0-f0)/(c0-(c0+f0)):(h0-(c0-f0))/(c0-(c0-f0))) 246 | expr1 clamp(h1>c1?(h1-c1-f1)/(c1-(c1+f1)):(h1-(c1-f1))/(c1-(c1-f1))) 247 | expr2 clamp(h2>c2?(h2-c2-f2)/(c2-(c2+f2)):(h2-(c2-f2))/(c2-(c2-f2))) 248 | channel3 none 249 | name LinearWindow1 250 | label CMY 251 | xpos 70 252 | ypos -40 253 | addUserKnob {20 Param} 254 | addUserKnob {7 o0 R 0 6} 255 | o0 5 256 | addUserKnob {7 o1 R 0 6} 257 | o1 3 258 | addUserKnob {7 o2 R 0 6} 259 | o2 1 260 | addUserKnob {26 ""} 261 | addUserKnob {7 c0 R 1 3} 262 | c0 2 263 | addUserKnob {7 f0 R 0.2 1.2} 264 | f0 1 265 | addUserKnob {7 c1 R 1 3} 266 | c1 2 267 | addUserKnob {7 f1 R 0.2 1.2} 268 | f1 1 269 | addUserKnob {7 c2 R 1 3} 270 | c2 2 271 | addUserKnob {7 f2 R 0.2 1.2} 272 | f2 1 273 | } 274 | MergeExpression { 275 | inputs 2 276 | temp_name0 f 277 | temp_expr0 Ar 278 | expr0 r*f 279 | expr1 g*f 280 | expr2 b*f 281 | name Multiply1 282 | xpos -150 283 | ypos -34 284 | } 285 | push $Nbcff8100 286 | push $Nbc7deb00 287 | Expression { 288 | temp_name0 h0 289 | temp_expr0 (r+o0)%6 290 | temp_name1 h1 291 | temp_expr1 (r+o1)%6 292 | temp_name2 h2 293 | temp_expr2 (r+o2)%6 294 | expr0 clamp(h0>c0?(h0-c0-f0)/(c0-(c0+f0)):(h0-(c0-f0))/(c0-(c0-f0))) 295 | expr1 clamp(h1>c1?(h1-c1-f1)/(c1-(c1+f1)):(h1-(c1-f1))/(c1-(c1-f1))) 296 | expr2 clamp(h2>c2?(h2-c2-f2)/(c2-(c2+f2)):(h2-(c2-f2))/(c2-(c2-f2))) 297 | channel3 none 298 | name LinearWindow 299 | label RGB 300 | xpos 70 301 | ypos -112 302 | addUserKnob {20 Param} 303 | addUserKnob {7 o0 R 0 6} 304 | o0 2 305 | addUserKnob {7 o1 R 0 6} 306 | o1 6 307 | addUserKnob {7 o2 R 0 6} 308 | o2 4 309 | addUserKnob {26 ""} 310 | addUserKnob {7 c0 R 1 3} 311 | c0 2 312 | addUserKnob {7 f0 R 0.2 1.2} 313 | f0 1 314 | addUserKnob {7 c1 R 1 3} 315 | c1 2 316 | addUserKnob {7 f1 R 0.2 1.2} 317 | f1 1 318 | addUserKnob {7 c2 R 1 3} 319 | c2 2 320 | addUserKnob {7 f2 R 0.2 1.2} 321 | f2 1 322 | } 323 | MergeExpression { 324 | inputs 2 325 | temp_name0 f 326 | temp_expr0 Ar 327 | expr0 r*f 328 | expr1 g*f 329 | expr2 b*f 330 | name Multiply 331 | xpos -150 332 | ypos -106 333 | } 334 | push $Nbcff8f00 335 | MergeExpression { 336 | inputs 2 337 | expr0 r+Ab*s2-Ag*s1 338 | expr1 g+Ar*s0-Ab*s2 339 | expr2 b+Ag*s1-Ar*s0 340 | name Shift_RGB 341 | xpos -260 342 | ypos -106 343 | addUserKnob {20 Params} 344 | addUserKnob {7 s0 R -1 1} 345 | s0 {{sr}} 346 | addUserKnob {7 s1 R -1 1} 347 | s1 {{sg}} 348 | addUserKnob {7 s2 R -1 1} 349 | s2 {{sb}} 350 | } 351 | MergeExpression { 352 | inputs 2 353 | expr0 r+Ab*s2-Ag*s1 354 | expr1 g+Ar*s0-Ab*s2 355 | expr2 b+Ag*s1-Ar*s0 356 | name Shift_CMY 357 | xpos -260 358 | ypos -34 359 | addUserKnob {20 Params} 360 | addUserKnob {7 s0 R -1 1} 361 | s0 {{sc}} 362 | addUserKnob {7 s1 R -1 1} 363 | s1 {{sm}} 364 | addUserKnob {7 s2 R -1 1} 365 | s2 {{sy}} 366 | } 367 | MergeExpression { 368 | inputs 2 369 | expr0 r+Ar*(sc2-sc1) 370 | expr1 g+Ar*(sc0-sc2) 371 | expr2 b+Ar*(sc1-sc0) 372 | name Shift_Custom 373 | xpos -260 374 | ypos 38 375 | addUserKnob {20 Params} 376 | addUserKnob {7 h R 0 6} 377 | h {{(cuh%360)/60}} 378 | addUserKnob {7 s R -1 1} 379 | s {{scu*cuw}} 380 | addUserKnob {7 sc0 R -1 1} 381 | sc0 {{h<3?s-s*min(1,fabs(h-2)):s*min(1,fabs(h-5))-s}} 382 | addUserKnob {7 sc1 R -1 1} 383 | sc1 {{h<1?s-s*min(1,fabs(h)):h<5?s*min(1,fabs(h-3))-s:s-s*min(1,fabs(h-6))}} 384 | addUserKnob {7 sc2 R -1 1} 385 | sc2 {{h<2?s*min(1,fabs(h-1))-s:s-s*min(1,fabs(h-4))}} 386 | } 387 | MergeExpression { 388 | inputs 2 389 | temp_name0 n 390 | temp_expr0 Ar 391 | expr0 n*r 392 | expr1 n*g 393 | expr2 n*b 394 | name Recombine 395 | xpos -260 396 | ypos 158 397 | } 398 | MergeExpression { 399 | inputs 2 400 | temp_name0 f 401 | temp_expr0 ze?Aa:1 402 | expr0 Ar*(1-f)+Br*f 403 | expr1 Ag*(1-f)+Bg*f 404 | expr2 Ab*(1-f)+Bb*f 405 | name Mix 406 | xpos -260 407 | ypos 206 408 | } 409 | push $Nbcffab00 410 | NodeWrapper { 411 | inputs 2+1 412 | channels rgb 413 | name NodeWrapper1 414 | xpos -260 415 | ypos 278 416 | } 417 | Output { 418 | name Output 419 | xpos -260 420 | ypos 350 421 | } 422 | end_group -------------------------------------------------------------------------------- /look-transforms/tools/nuke/n6Purity.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name n6Purity 5 | tile_color 0x536177ff 6 | addUserKnob {20 Params_tab l Params} 7 | addUserKnob {26 about_label l " " T "\n\nn6Purity created by Jed Smith\n
v0.0.2 | documentation
"} 8 | addUserKnob {20 color_grp l "" +STARTLINE n -2} 9 | addUserKnob {20 rgb_tab l RGB} 10 | addUserKnob {41 rp l "red purity" T CubicChromaCurveRGB.rp} 11 | addUserKnob {41 rs l "red strength" T CubicChromaCurveRGB.rs} 12 | addUserKnob {41 gp l "green purity" T CubicChromaCurveRGB.gp} 13 | addUserKnob {41 gs l "green strength" T CubicChromaCurveRGB.gs} 14 | addUserKnob {41 bp l "blue purity" T CubicChromaCurveRGB.bp} 15 | addUserKnob {41 bs l "blue strength" T CubicChromaCurveRGB.bs} 16 | addUserKnob {20 cmy_tab l CMY} 17 | addUserKnob {41 cp l "cyan purity" T CubicChromaCurveCMY.cp} 18 | addUserKnob {41 cs l "cyan strength" T CubicChromaCurveCMY.cs} 19 | addUserKnob {41 mp l "magenta purity" T CubicChromaCurveCMY.mp} 20 | addUserKnob {41 ms l "magenta strength" T CubicChromaCurveCMY.ms} 21 | addUserKnob {41 yp l "yellow purity" T CubicChromaCurveCMY.yp} 22 | addUserKnob {41 ys l "yellow strength" T CubicChromaCurveCMY.ys} 23 | addUserKnob {20 endGroup n -3} 24 | } 25 | Input { 26 | inputs 0 27 | name Input 28 | xpos 840 29 | ypos 566 30 | } 31 | Dot { 32 | name Dot425 33 | xpos 874 34 | ypos 642 35 | } 36 | set N63c749a0 [stack 0] 37 | Dot { 38 | name Dot421 39 | xpos 544 40 | ypos 642 41 | } 42 | Expression { 43 | temp_name0 M 44 | temp_expr0 max(r,g,b) 45 | temp_name1 C 46 | temp_expr1 M-min(r,g,b) 47 | channel0 {rgba.red rgba.green rgba.blue none} 48 | expr0 (C==0?0:r==M?((g-b)/C+6)%6:g==M?(b-r)/C+2:b==M?(r-g)/C+4:0) 49 | expr3 M==0?0:C/M 50 | name HueChroma 51 | xpos 510 52 | ypos 662 53 | } 54 | set N6afa7290 [stack 0] 55 | Expression { 56 | temp_name0 h0 57 | temp_expr0 (r+1)%6 58 | temp_name1 h1 59 | temp_expr1 (r+5)%6 60 | temp_name2 h2 61 | temp_expr2 (r+3)%6 62 | expr0 (h0>x1?0:h0>c.0?(1-((h0-c.0)/(x1-c.0))**p0)**p1:h0>x0?(1-((c.0-h0)/(c.0-x0))**p0)**p1:0) 63 | expr1 (h1>x1?0:h1>c.1?(1-((h1-c.1)/(x1-c.1))**p0)**p1:h1>x0?(1-((c.1-h1)/(c.1-x0))**p0)**p1:0) 64 | expr2 (h2>x1?0:h2>c.2?(1-((h2-c.2)/(x1-c.2))**p0)**p1:h2>x0?(1-((c.2-h2)/(c.2-x0))**p0)**p1:0) 65 | name PowerWindowRGB 66 | label https://www.desmos.com/calculator/8tqz4rs0wm 67 | xpos 510 68 | ypos 712 69 | addUserKnob {20 Params} 70 | addUserKnob {78 c n 3} 71 | c {1 1 1} 72 | addUserKnob {7 p0 R 1 2} 73 | p0 2 74 | addUserKnob {7 p1 R 1 2} 75 | p1 2 76 | addUserKnob {7 x0 R 0 2} 77 | addUserKnob {7 x1 R 0 2} 78 | x1 2 79 | } 80 | Expression { 81 | temp_name0 c 82 | temp_expr0 1-a 83 | temp_name1 cr 84 | temp_expr1 a==0?a:(rp<0?a>1?a:a<0?m.0*a:a*(a**p.0*(a0.0*a+b0.0)+m.0):a<0?a:a>1?m.0*(a-1)+1:(1-c*(c**p.0*(a0.0*c+b0.0)+m.0)))/a 85 | temp_name2 cg 86 | temp_expr2 a==0?a:(gp<0?a>1?a:a<0?m.1*a:a*(a**p.1*(a0.1*a+b0.1)+m.1):a<0?a:a>1?m.1*(a-1)+1:(1-c*(c**p.1*(a0.1*c+b0.1)+m.1)))/a 87 | temp_name3 cb 88 | temp_expr3 a==0?a:(bp<0?a>1?a:a<0?m.2*a:a*(a**p.2*(a0.2*a+b0.2)+m.2):a<0?a:a>1?m.2*(a-1)+1:(1-c*(c**p.2*(a0.2*c+b0.2)+m.2)))/a 89 | channel0 rgb 90 | expr0 r*cr+g*cg+b*cb+(1-(r+g+b)) 91 | name CubicChromaCurveRGB 92 | label https://www.desmos.com/calculator/bdbstdsvvv 93 | xpos 510 94 | ypos 762 95 | addUserKnob {20 Params} 96 | addUserKnob {7 rp l "red purity" t "adjust mid-range chrominance" R -1 1} 97 | addUserKnob {7 rs l "red strength" t "strength of the adjustment" R 0 4} 98 | rs 2 99 | addUserKnob {7 gp l "green purity" t "adjust mid-range chrominance" R -1 1} 100 | addUserKnob {7 gs l "green strength" t "strength of the adjustment" R 0 4} 101 | gs 2 102 | addUserKnob {7 bp l "blue purity" t "adjust mid-range chrominance" R -1 1} 103 | addUserKnob {7 bs l "blue strength" t "strength of the adjustment" R 0 4} 104 | bs 2 105 | addUserKnob {78 m R -1 1 n 3} 106 | m {{1-fabs(rp)} {1-fabs(gp)} {1-fabs(bp)}} 107 | addUserKnob {78 p R 0 10 n 3} 108 | p {{rs} {gs} {bs}} 109 | addUserKnob {78 a0 R -10 10 n 3} 110 | a0 {{p*(m-1)} {p*(m-1)} {p*(m-1)}} 111 | addUserKnob {78 b0 R -10 10 n 3} 112 | b0 {{(1-m)*(p+1)} {(1-m)*(p+1)} {(1-m)*(p+1)}} 113 | } 114 | push $N6afa7290 115 | Expression { 116 | temp_name0 h0 117 | temp_expr0 (r+4)%6 118 | temp_name1 h1 119 | temp_expr1 (r+2)%6 120 | temp_name2 h2 121 | temp_expr2 (r)%6 122 | expr0 (h0>x1?0:h0>c.0?(1-((h0-c.0)/(x1-c.0))**p0)**p1:h0>x0?(1-((c.0-h0)/(c.0-x0))**p0)**p1:0) 123 | expr1 (h1>x1?0:h1>c.1?(1-((h1-c.1)/(x1-c.1))**p0)**p1:h1>x0?(1-((c.1-h1)/(c.1-x0))**p0)**p1:0) 124 | expr2 (h2>x1?0:h2>c.2?(1-((h2-c.2)/(x1-c.2))**p0)**p1:h2>x0?(1-((c.2-h2)/(c.2-x0))**p0)**p1:0) 125 | name PowerWindowCMY 126 | xpos 620 127 | ypos 710 128 | addUserKnob {20 Params} 129 | addUserKnob {78 c n 3} 130 | c {1 1 1} 131 | addUserKnob {7 p0 R 1 2} 132 | p0 2 133 | addUserKnob {7 p1 R 1 2} 134 | p1 2 135 | addUserKnob {7 x0 R 0 2} 136 | addUserKnob {7 x1 R 0 2} 137 | x1 2 138 | } 139 | Expression { 140 | temp_name0 c 141 | temp_expr0 1-a 142 | temp_name1 cr 143 | temp_expr1 a==0?a:(cp<0?a>1?a:a<0?m.0*a:a*(a**p.0*(a0.0*a+b0.0)+m.0):a<0?a:a>1?m.0*(a-1)+1:(1-c*(c**p.0*(a0.0*c+b0.0)+m.0)))/a 144 | temp_name2 cg 145 | temp_expr2 a==0?a:(mp<0?a>1?a:a<0?m.1*a:a*(a**p.1*(a0.1*a+b0.1)+m.1):a<0?a:a>1?m.1*(a-1)+1:(1-c*(c**p.1*(a0.1*c+b0.1)+m.1)))/a 146 | temp_name3 cb 147 | temp_expr3 a==0?a:(yp<0?a>1?a:a<0?m.2*a:a*(a**p.2*(a0.2*a+b0.2)+m.2):a<0?a:a>1?m.2*(a-1)+1:(1-c*(c**p.2*(a0.2*c+b0.2)+m.2)))/a 148 | channel0 rgb 149 | expr0 r*cr+g*cg+b*cb+(1-(r+g+b)) 150 | name CubicChromaCurveCMY 151 | xpos 620 152 | ypos 748 153 | addUserKnob {20 Params} 154 | addUserKnob {7 cp l "cyan purity" t "adjust mid-range chrominance" R -1 1} 155 | addUserKnob {7 cs l "cyan strength" t "strength of the adjustment" R 0 4} 156 | cs 2 157 | addUserKnob {7 mp l "magenta purity" t "adjust mid-range chrominance" R -1 1} 158 | addUserKnob {7 ms l "magenta strength" t "strength of the adjustment" R 0 4} 159 | ms 2 160 | addUserKnob {7 yp l "yellow purity" t "adjust mid-range chrominance" R -1 1} 161 | addUserKnob {7 ys l "yellow strength" t "strength of the adjustment" R 0 4} 162 | ys 2 163 | addUserKnob {78 m R -1 1 n 3} 164 | m {{1-fabs(cp)} {1-fabs(mp)} {1-fabs(yp)}} 165 | addUserKnob {78 p R 0 10 n 3} 166 | p {{cs} {ms} {ys}} 167 | addUserKnob {78 a0 R -10 10 n 3} 168 | a0 {{p*(m-1)} {p*(m-1)} {p*(m-1)}} 169 | addUserKnob {78 b0 R -10 10 n 3} 170 | b0 {{(1-m)*(p+1)} {(1-m)*(p+1)} {(1-m)*(p+1)}} 171 | } 172 | Merge2 { 173 | inputs 2 174 | operation multiply 175 | bbox B 176 | name Merge162 177 | xpos 510 178 | ypos 806 179 | } 180 | push $N63c749a0 181 | Dot { 182 | name Dot299 183 | xpos 874 184 | ypos 738 185 | } 186 | set N67b039a0 [stack 0] 187 | Expression { 188 | channel0 rgba 189 | expr0 r*rw+g*gw+b*bw 190 | name Weights 191 | label "Weighted Sum" 192 | xpos 730 193 | ypos 728 194 | addUserKnob {20 User} 195 | addUserKnob {7 rw R 0.05 0.6} 196 | rw 0.3 197 | addUserKnob {7 gw} 198 | gw {{1-(rw+bw)}} 199 | addUserKnob {7 bw R 0.05 0.6} 200 | bw 0.1 201 | } 202 | Copy { 203 | inputs 2 204 | from0 rgba.red 205 | to0 rgba.alpha 206 | name Copy16 207 | xpos 730 208 | ypos 800 209 | } 210 | push $N67b039a0 211 | MergeExpression { 212 | inputs 2 213 | temp_name0 f 214 | temp_expr0 Aa 215 | temp_name1 L 216 | temp_expr1 Ar 217 | expr0 L*(1-f)+r*f 218 | expr1 L*(1-f)+g*f 219 | expr2 L*(1-f)+b*f 220 | name ChromaLerp 221 | xpos 840 222 | ypos 806 223 | } 224 | Output { 225 | name Output 226 | xpos 840 227 | ypos 878 228 | } 229 | end_group 230 | -------------------------------------------------------------------------------- /look-transforms/tools/nuke/n6Vibrance.nk: -------------------------------------------------------------------------------- 1 | set cut_paste_input [stack 0] 2 | push $cut_paste_input 3 | Group { 4 | name N6Vibrance 5 | tile_color 0x536177ff 6 | addUserKnob {20 Vibrance_tab l Vibrance} 7 | addUserKnob {26 about_label l " " T "\n\nNotorious Six Vibrance created by Jed Smith\n
v0.0.3 | documentation
"} 8 | addUserKnob {7 mgl l global R -1 1} 9 | addUserKnob {7 my l yellow R -1 1} 10 | addUserKnob {7 mr l red R -1 1} 11 | addUserKnob {7 mm l magenta R -1 1} 12 | addUserKnob {7 mb l blue R -1 1} 13 | addUserKnob {7 mc l cyan R -1 1} 14 | addUserKnob {7 mg l green R -1 1} 15 | addUserKnob {7 mcu l custom R -1 1} 16 | addUserKnob {7 cuh l "custom hue" t "hue angle center for custom hue extraction. 0 is green." R 0 360} 17 | cuh 100 18 | addUserKnob {7 cuw l "custom width" t "width for custom hue angle extraction"} 19 | cuw 0.3 20 | addUserKnob {26 ""} 21 | addUserKnob {7 hl l hue-linear} 22 | hl 0.5 23 | addUserKnob {6 ze l "zone extract" t "effect a limited range of luminance." +STARTLINE} 24 | ze true 25 | addUserKnob {4 zr l "" -STARTLINE M {low high ""}} 26 | addUserKnob {7 zp l "zone range" t "set range affected: higher values affect a larger range" R -4 4} 27 | addUserKnob {26 ""} 28 | addUserKnob {41 maskChannelMask l mask -STARTLINE T NodeWrapper1.maskChannelMask} 29 | addUserKnob {41 invert_mask l invert -STARTLINE T NodeWrapper1.invert_mask} 30 | addUserKnob {41 mix T NodeWrapper1.mix} 31 | } 32 | Input { 33 | inputs 0 34 | name Inputmask 35 | xpos 290 36 | ypos 230 37 | number 1 38 | } 39 | Input { 40 | inputs 0 41 | name Input 42 | xpos 180 43 | ypos -322 44 | } 45 | Dot { 46 | name Dot104 47 | xpos 214 48 | ypos -270 49 | } 50 | set Na64fcf00 [stack 0] 51 | Dot { 52 | name Dot24 53 | xpos 104 54 | ypos -270 55 | } 56 | set Na64fc800 [stack 0] 57 | Dot { 58 | name Dot105 59 | xpos -6 60 | ypos -270 61 | } 62 | Expression { 63 | channel0 rgba 64 | expr0 max(r,g,b) 65 | channel3 none 66 | name Norm 67 | xpos -40 68 | ypos -250 69 | } 70 | Dot { 71 | name Dot21 72 | xpos -6 73 | ypos -198 74 | } 75 | set Na2713200 [stack 0] 76 | Dot { 77 | name Dot106 78 | xpos -6 79 | ypos 114 80 | } 81 | set Na2712b00 [stack 0] 82 | push $Na64fc800 83 | Dot { 84 | name Dot27 85 | xpos 104 86 | ypos 66 87 | } 88 | set Na2712400 [stack 0] 89 | MergeExpression { 90 | inputs 2 91 | temp_name0 n 92 | temp_expr0 max(1e-12,Ar) 93 | temp_name1 to 94 | temp_expr1 (n*n/(n+fl)) 95 | temp_name2 flow 96 | temp_expr2 pow((to/(to+1))/n,p) 97 | temp_name3 fhi 98 | temp_expr3 1-pow((n/(n+1))/n,p) 99 | channel0 {rgba.red -rgba.green -rgba.blue none} 100 | expr0 r 101 | expr1 g 102 | expr2 b 103 | expr3 zr?fhi:flow 104 | name Extract 105 | xpos 70 106 | ypos 158 107 | addUserKnob {20 Params} 108 | addUserKnob {7 fl R 0 0.02} 109 | fl 0.004 110 | addUserKnob {7 p R 0 64} 111 | p {{pow(2,-zp)}} 112 | } 113 | push $Na2712b00 114 | push $Na2713200 115 | push $Na64fcf00 116 | MergeExpression { 117 | inputs 2 118 | temp_name0 n 119 | temp_expr0 Ar 120 | temp_name1 mn 121 | temp_expr1 -1 122 | expr0 n==0?0:max(mn,r/n) 123 | expr1 n==0?0:max(mn,g/n) 124 | expr2 n==0?0:max(mn,b/n) 125 | name RGBRatios 126 | xpos 180 127 | ypos -202 128 | } 129 | Dot { 130 | name Dot4 131 | xpos 214 132 | ypos -150 133 | } 134 | set Na2710f00 [stack 0] 135 | Expression { 136 | temp_name0 C 137 | temp_expr0 1-min(r,g,b) 138 | channel0 {rgba.red rgba.green rgba.blue none} 139 | expr0 (C==0?0:r==1?((g-b)/C+6)%6:g==1?(b-r)/C+2:b==1?(r-g)/C+4:0) 140 | expr3 C 141 | name hue 142 | xpos 510 143 | ypos -154 144 | } 145 | Dot { 146 | name Dot5 147 | xpos 544 148 | ypos -102 149 | } 150 | set Na2710100 [stack 0] 151 | Dot { 152 | name Dot6 153 | xpos 544 154 | ypos -54 155 | } 156 | set Na6f63900 [stack 0] 157 | Dot { 158 | name Dot7 159 | xpos 544 160 | ypos -6 161 | } 162 | Expression { 163 | temp_name0 h 164 | temp_expr0 (r+o)%6 165 | channel0 {rgba.red rgba.green rgba.blue none} 166 | expr0 (hc0?(h0-c0-f0)/(c0-(c0+f0)):(h0-(c0-f0))/(c0-(c0-f0)))*a 193 | expr1 clamp(h1>c1?(h1-c1-f1)/(c1-(c1+f1)):(h1-(c1-f1))/(c1-(c1-f1)))*a 194 | expr2 clamp(h2>c2?(h2-c2-f2)/(c2-(c2+f2)):(h2-(c2-f2))/(c2-(c2-f2)))*a 195 | channel3 none 196 | name LerpWindow4 197 | label CMY 198 | xpos 400 199 | ypos -64 200 | addUserKnob {20 Param} 201 | addUserKnob {7 o0 R 0 6} 202 | o0 5 203 | addUserKnob {7 o1 R 0 6} 204 | o1 3 205 | addUserKnob {7 o2 R 0 6} 206 | o2 1 207 | addUserKnob {26 ""} 208 | addUserKnob {7 c0 R 1 3} 209 | c0 2 210 | addUserKnob {7 f0 R 0.2 1.2} 211 | f0 1 212 | addUserKnob {7 c1 R 1 3} 213 | c1 2 214 | addUserKnob {7 f1 R 0.2 1.2} 215 | f1 1 216 | addUserKnob {7 c2 R 1 3} 217 | c2 2 218 | addUserKnob {7 f2 R 0.2 1.2} 219 | f2 1 220 | } 221 | set Na6f62400 [stack 0] 222 | push $Na2710100 223 | Expression { 224 | temp_name0 h0 225 | temp_expr0 (r+o0)%6 226 | temp_name1 h1 227 | temp_expr1 (r+o1)%6 228 | temp_name2 h2 229 | temp_expr2 (r+o2)%6 230 | expr0 clamp(h0>c0?(h0-c0-f0)/(c0-(c0+f0)):(h0-(c0-f0))/(c0-(c0-f0)))*a 231 | expr1 clamp(h1>c1?(h1-c1-f1)/(c1-(c1+f1)):(h1-(c1-f1))/(c1-(c1-f1)))*a 232 | expr2 clamp(h2>c2?(h2-c2-f2)/(c2-(c2+f2)):(h2-(c2-f2))/(c2-(c2-f2)))*a 233 | channel3 none 234 | name LerpWindow2 235 | label RGB 236 | xpos 400 237 | ypos -112 238 | addUserKnob {20 Param} 239 | addUserKnob {7 o0 R 0 6} 240 | o0 2 241 | addUserKnob {7 o1 R 0 6} 242 | o1 6 243 | addUserKnob {7 o2 R 0 6} 244 | o2 4 245 | addUserKnob {26 ""} 246 | addUserKnob {7 c0 R 1 3} 247 | c0 2 248 | addUserKnob {7 f0 R 0.2 1.2} 249 | f0 1 250 | addUserKnob {7 c1 R 1 3} 251 | c1 2 252 | addUserKnob {7 f1 R 0.2 1.2} 253 | f1 1 254 | addUserKnob {7 c2 R 1 3} 255 | c2 2 256 | addUserKnob {7 f2 R 0.2 1.2} 257 | f2 1 258 | } 259 | set Na6f61d00 [stack 0] 260 | push $Na2710f00 261 | MergeExpression { 262 | inputs 2 263 | temp_name0 m 264 | temp_expr0 1.1 265 | temp_name1 c 266 | temp_expr1 Aa 267 | temp_name3 f 268 | temp_expr3 c==0||c>1?1:((1-pow(1-c,p0))*Ar+(1-pow(1-c,p1))*Ag+(1-pow(1-c,p2))*Ab+c*(1-(Ar+Ag+Ab)))/c 269 | channel0 {rgba.red -rgba.green -rgba.blue none} 270 | expr0 m*(1-f)+r*f 271 | expr1 m*(1-f)+g*f 272 | expr2 m*(1-f)+b*f 273 | expr3 f 274 | name vihl_rgb 275 | xpos 180 276 | ypos -106 277 | addUserKnob {20 Params} 278 | addUserKnob {7 p0 R 0 4} 279 | p0 {{3**mr*3**mgl}} 280 | addUserKnob {7 p1 R 0 4} 281 | p1 {{3**mg*3**mgl}} 282 | addUserKnob {7 p2 R 0 4} 283 | p2 {{3**mb*3**mgl}} 284 | } 285 | MergeExpression { 286 | inputs 2 287 | temp_name0 m 288 | temp_expr0 1 289 | temp_name1 c 290 | temp_expr1 Aa 291 | temp_name3 f 292 | temp_expr3 c==0?1:((1-pow(1-c,p0))*Ar+(1-pow(1-c,p1))*Ag+(1-pow(1-c,p2))*Ab+c*(1-(Ar+Ag+Ab)))/c 293 | channel0 {rgba.red -rgba.green -rgba.blue none} 294 | expr0 m*(1-f)+r*f 295 | expr1 m*(1-f)+g*f 296 | expr2 m*(1-f)+b*f 297 | name vihl_cmy 298 | xpos 180 299 | ypos -58 300 | addUserKnob {20 Params} 301 | addUserKnob {7 p0 R 0 4} 302 | p0 {{3**mc*3**mgl}} 303 | addUserKnob {7 p1 R 0 4} 304 | p1 {{3**mm*3**mgl}} 305 | addUserKnob {7 p2 R 0 4} 306 | p2 {{3**my*2**mgl}} 307 | } 308 | MergeExpression { 309 | inputs 2 310 | temp_name0 m 311 | temp_expr0 1 312 | temp_name1 c 313 | temp_expr1 Aa 314 | temp_name3 f 315 | temp_expr3 c==0?1:((1-pow(1-c,p))*Ar+c*(1-Ar))/c 316 | channel0 {rgba.red -rgba.green -rgba.blue none} 317 | expr0 m*(1-f)+r*f 318 | expr1 m*(1-f)+g*f 319 | expr2 m*(1-f)+b*f 320 | name vihl_cu 321 | xpos 180 322 | ypos -10 323 | addUserKnob {20 Params} 324 | addUserKnob {7 p R 0 4} 325 | p {{3**mcu}} 326 | } 327 | push $Na6f62b00 328 | push $Na6f62400 329 | push $Na6f61d00 330 | push $Na2710f00 331 | MergeExpression { 332 | inputs 2 333 | channel0 {rgba.red -rgba.green -rgba.blue none} 334 | expr0 pow(r,p0)*Ar+pow(r,p1)*Ag+pow(r,p2)*Ab+r*(1-(Ar+Ag+Ab)) 335 | expr1 pow(g,p0)*Ar+pow(g,p1)*Ag+pow(g,p2)*Ab+g*(1-(Ar+Ag+Ab)) 336 | expr2 pow(b,p0)*Ar+pow(b,p1)*Ag+pow(b,p2)*Ab+b*(1-(Ar+Ag+Ab)) 337 | name vi_rgb 338 | xpos 290 339 | ypos -82 340 | addUserKnob {20 Params} 341 | addUserKnob {7 p0 R 0 4} 342 | p0 {{parent.vihl_rgb.p0}} 343 | addUserKnob {7 p1 R 0 4} 344 | p1 {{parent.vihl_rgb.p1}} 345 | addUserKnob {7 p2 R 0 4} 346 | p2 {{parent.vihl_rgb.p2}} 347 | } 348 | MergeExpression { 349 | inputs 2 350 | channel0 {rgba.red -rgba.green -rgba.blue none} 351 | expr0 pow(r,p0)*Ar+pow(r,p1)*Ag+pow(r,p2)*Ab+r*(1-(Ar+Ag+Ab)) 352 | expr1 pow(g,p0)*Ar+pow(g,p1)*Ag+pow(g,p2)*Ab+g*(1-(Ar+Ag+Ab)) 353 | expr2 pow(b,p0)*Ar+pow(b,p1)*Ag+pow(b,p2)*Ab+b*(1-(Ar+Ag+Ab)) 354 | name vi_cmy 355 | xpos 290 356 | ypos -34 357 | addUserKnob {20 Params} 358 | addUserKnob {7 p0 R 0 4} 359 | p0 {{parent.vihl_cmy.p0}} 360 | addUserKnob {7 p1 R 0 4} 361 | p1 {{parent.vihl_cmy.p1}} 362 | addUserKnob {7 p2 R 0 4} 363 | p2 {{parent.vihl_cmy.p2}} 364 | } 365 | MergeExpression { 366 | inputs 2 367 | channel0 {rgba.red -rgba.green -rgba.blue none} 368 | expr0 pow(r,p0)*Ar+r*(1-Ar) 369 | expr1 pow(g,p0)*Ar+g*(1-Ar) 370 | expr2 pow(b,p0)*Ar+b*(1-Ar) 371 | name vi_cu 372 | xpos 290 373 | ypos 17 374 | addUserKnob {20 Params} 375 | addUserKnob {7 p0 R 0 4} 376 | p0 {{parent.vihl_cu.p}} 377 | } 378 | Dissolve { 379 | inputs 2 380 | channels rgb 381 | which {{hl}} 382 | name Mix_hue_linear 383 | xpos 180 384 | ypos 63 385 | } 386 | MergeExpression { 387 | inputs 2 388 | temp_name0 n 389 | temp_expr0 Ar 390 | expr0 n*r 391 | expr1 n*g 392 | expr2 n*b 393 | name Recombine 394 | xpos 180 395 | ypos 110 396 | } 397 | MergeExpression { 398 | inputs 2 399 | temp_name0 f 400 | temp_expr0 ze?Aa:1 401 | expr0 Ar*(1-f)+Br*f 402 | expr1 Ag*(1-f)+Bg*f 403 | expr2 Ab*(1-f)+Bb*f 404 | name Mix 405 | xpos 180 406 | ypos 158 407 | } 408 | push $Na2712400 409 | NodeWrapper { 410 | inputs 2+1 411 | channels rgb 412 | name NodeWrapper1 413 | xpos 180 414 | ypos 230 415 | } 416 | Output { 417 | name Output 418 | xpos 180 419 | ypos 302 420 | } 421 | end_group 422 | -------------------------------------------------------------------------------- /look-transforms/tools/resolve/HighlightContrast.dctl: -------------------------------------------------------------------------------- 1 | #line 2 // Fix line numbers in resolve/logs/rollinglog.txt 2 | #include "libLMT.h" 3 | 4 | DEFINE_UI_PARAMS(ex, exposure, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 5 | DEFINE_UI_PARAMS(th, threshold, DCTLUI_SLIDER_FLOAT, -1, -4, 4, 0) 6 | DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0) 7 | DEFINE_UI_PARAMS(tf, Transfer Function, DCTLUI_COMBO_BOX, 1, {ioetf_linear, ioetf_davinci_intermediate, ioetf_acescct, ioetf_arri_logc3, ioetf_arri_logc4, ioetf_redlog3g10}, {Linear, Davinci Intermediate, ACEScct, Arri LogC3, Arri LogC4, RedLog3G10}) 8 | 9 | 10 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 11 | { 12 | float3 rgb = make_float3(p_R, p_G, p_B); 13 | rgb = linearize(rgb, tf, 0); 14 | rgb = hl_con(rgb, ex, th, invert); 15 | rgb = linearize(rgb, tf, 1); 16 | return rgb; 17 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/HueContrast.dctl: -------------------------------------------------------------------------------- 1 | #line 1 // Fix line numbers in resolve/logs/rollinglog.txt 2 | /* HueContrast ------------------------------------------------- 3 | v0.0.3 4 | A tool to compress hues towards the primary color vectors. Pretty similar to n6HueShift 5 | but parameterized to compress or expand on both sides of a primary hue vector instead. 6 | 7 | Written by Jed Smith 8 | https://github.com/jedypod/open-display-transform 9 | 10 | License: GPL v3 11 | -------------------------------------------------*/ 12 | 13 | 14 | DEFINE_UI_PARAMS(m0r, focus - R low, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 15 | DEFINE_UI_PARAMS(m1r, R high, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 16 | DEFINE_UI_PARAMS(m0g, G low, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 17 | DEFINE_UI_PARAMS(m1g, G high, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 18 | DEFINE_UI_PARAMS(m0b, B low, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 19 | DEFINE_UI_PARAMS(m1b, B high, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 20 | DEFINE_UI_PARAMS(p_sr, strength - R, DCTLUI_SLIDER_FLOAT, 0.5, 0, 1, 0) 21 | DEFINE_UI_PARAMS(p_sg, G, DCTLUI_SLIDER_FLOAT, 0.5, 0, 1, 0) 22 | DEFINE_UI_PARAMS(p_sb, B, DCTLUI_SLIDER_FLOAT, 0.5, 0, 1, 0) 23 | DEFINE_UI_PARAMS(p_wr, width - R, DCTLUI_SLIDER_FLOAT, 0.5, 0, 1, 0) 24 | DEFINE_UI_PARAMS(p_wg, G, DCTLUI_SLIDER_FLOAT, 0.5, 0, 1, 0) 25 | DEFINE_UI_PARAMS(p_wb, B, DCTLUI_SLIDER_FLOAT, 0.5, 0, 1, 0) 26 | DEFINE_UI_PARAMS(bias, bias, DCTLUI_SLIDER_FLOAT, 0.0, -3.0, 3.0, 0) 27 | 28 | 29 | 30 | 31 | //----------------------------------------------------------------------------// 32 | 33 | 34 | // Safe power function raising float a to power float b 35 | __DEVICE__ float spowf(float a, float b) { 36 | if (a <= 0.0f) return a; 37 | else return _powf(a, b); 38 | } 39 | 40 | // Safe division of float a by float b 41 | __DEVICE__ float sdivf(float a, float b) { 42 | if (b == 0.0f) return 0.0f; 43 | else return a/b; 44 | } 45 | 46 | // Safe division of float3 a by float b 47 | __DEVICE__ float3 sdivf3f(float3 a, float b) { 48 | return make_float3(sdivf(a.x, b), sdivf(a.y, b), sdivf(a.z, b)); 49 | } 50 | 51 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 52 | { 53 | // Parameter Setup 54 | float3 m0 = make_float3(1.0f - m0r, 1.0f - m0g, 1.0f - m0b); 55 | float3 m1 = make_float3(1.0f - m1r, 1.0f - m1g, 1.0f - m1b); 56 | 57 | float3 in = make_float3(p_R, p_G, p_B); 58 | 59 | // RGB Ratios 60 | float mx = _fmaxf(in.x, _fmaxf(in.y, in.z)); 61 | mx = _fabs(mx) < 1e-4f ? 0.0f : mx; 62 | float3 rgb = sdivf3f(in, mx); 63 | float mn = _fmaxf(0.0f, _fminf(rgb.x, _fminf(rgb.y, rgb.z))); 64 | 65 | // Remove achromatic from RGB Ratios 66 | rgb = rgb - mn; 67 | 68 | // Mix between wide and narrow hue angles 69 | rgb = make_float3( _fminf(1.0f, _fmaxf(0.0f, rgb.x - (rgb.y + rgb.z)*(1.0f - p_wr))), 70 | _fminf(1.0f, _fmaxf(0.0f, rgb.y - (rgb.x + rgb.z)*(1.0f - p_wg))), 71 | _fminf(1.0f, _fmaxf(0.0f, rgb.z - (rgb.x + rgb.y)*(1.0f - p_wb)))); 72 | 73 | // Apply power function to chroma to adjust strength 74 | rgb = make_float3(spowf(rgb.x, 1.0f/p_sr), spowf(rgb.y, 1.0f/p_sg), spowf(rgb.z, 1.0f/p_sb)); 75 | 76 | 77 | /* Hue Distortion 78 | We make the hue distortion bidirectional by using a lerp factor based on a generic hyperbolic 79 | "tonescale" curve, biased by a power function w/ lin extension. 80 | We use a Lift/Multiply linear function to remap the input 81 | to the 0-2 range expected by the lerp (1.0 is no distortion, 2.0 is distorted towards the primary, 82 | 0.0 is distorted towards the secondary). 83 | */ 84 | // Spliced contrast: https://www.desmos.com/calculator/61ezkjxsgb 85 | const float p = spowf(2.0f, bias); 86 | const float s0 = spowf(0.18, 1.0f - p); 87 | const float t0 = 0.18f; 88 | float zr_f = mx < t0 ? s0*spowf(mx, p) : p*(mx - t0) + t0; 89 | 90 | // Generic hyperbolic compression, roughly aligning middle grey to typical display output value 91 | zr_f = sdivf(zr_f, zr_f + 0.66f); 92 | 93 | // Remap with a lift/multiply function: https://www.desmos.com/calculator/eaxwxrhrev 94 | float3 f = make_float3(zr_f*(m1.x-m0.x)+m0.x, zr_f*(m1.y-m0.y)+m0.y, zr_f*(m1.z-m0.z)+m0.z); 95 | 96 | // Do the hue distortion / compression / "focus", basically a 3-way lerp 97 | rgb = make_float3( 98 | in.x*f.y*rgb.y + in.x*f.z*rgb.z + in.x*(1.0f - (rgb.y + rgb.z)), 99 | in.y*f.x*rgb.x + in.y*f.z*rgb.z + in.y*(1.0f - (rgb.x + rgb.z)), 100 | in.z*f.x*rgb.x + in.z*f.y*rgb.y + in.z*(1.0f - (rgb.x + rgb.y))); 101 | 102 | return rgb; 103 | } 104 | -------------------------------------------------------------------------------- /look-transforms/tools/resolve/LinearGrade.dctl: -------------------------------------------------------------------------------- 1 | /* Linear Grade 2 | Super simple chromaticity preserving scene-linear grading operator. 3 | offset -> pivoted contrast -> exposure 4 | */ 5 | 6 | DEFINE_UI_PARAMS(e, exposure, DCTLUI_SLIDER_FLOAT, 0.0, -6.0, 6.0, 0.0) 7 | DEFINE_UI_PARAMS(c, contrast, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 8 | DEFINE_UI_PARAMS(pv, pivot, DCTLUI_SLIDER_FLOAT, 0.0, -4.0, 4.0, 0.0) 9 | DEFINE_UI_PARAMS(off, offset, DCTLUI_SLIDER_FLOAT, 0.0, -0.02, 0.02, 0.0) 10 | 11 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 12 | { 13 | float3 rgb = make_float3(p_R, p_G, p_B); 14 | const float ex = _powf(2.0f, e); 15 | rgb += off; 16 | float m = _fmaxf(rgb.x, _fmaxf(rgb.y, rgb.z)) / _powf(2.0f, pv); 17 | float s = c == 1.0f || c <= 0.0f ? ex : m > 0.0f ? _powf(m, c - 1.0f) * ex : 1.0f; 18 | rgb *= s; 19 | return rgb; 20 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/MidtoneContrast.dctl: -------------------------------------------------------------------------------- 1 | /* Midtone Contrast 2 | v0.0.1 3 | A more sophisticated contrast operator with linear toe and shoulder sections. 4 | https://www.desmos.com/calculator/mqvhho1mf9 5 | 6 | Written by Jed Smith 7 | https://github.com/jedypod/open-display-transform 8 | 9 | License: GPL v3 10 | */ 11 | 12 | DEFINE_UI_PARAMS(con, contrast, DCTLUI_SLIDER_FLOAT, 0.0, -3.0, 2.0, 0.0) 13 | DEFINE_UI_PARAMS(pv, pivot, DCTLUI_SLIDER_FLOAT, 0.0, -4.0, 4.0, 0.0) 14 | DEFINE_UI_PARAMS(sh, shoulder, DCTLUI_SLIDER_FLOAT, 0.0, 0.0, 4.0, 0.0) 15 | DEFINE_UI_PARAMS(toe, toe, DCTLUI_SLIDER_FLOAT, 0.2, 0.0, 1.0, 0.0) 16 | DEFINE_UI_PARAMS(rp, preserve ratios, DCTLUI_SLIDER_FLOAT, 0.0, 0.0, 1.0, 0.0) 17 | DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0) 18 | 19 | 20 | __DEVICE__ float spowf(float x, float p) { return x <= 0.0f ? x : _powf(x, p); } 21 | __DEVICE__ float sdivf(float a, float b) { return _fabs(b) < 1e-6f ? 0.0f : a/b; } 22 | 23 | __DEVICE__ float contrast(float x, float s0, float s1, float p, float o, float m0, float m1, float tlx, float tly, float tux, float tuy, int inv) { 24 | if (inv == 0) { 25 | return s1*(x3.0.CO;2-R 7 | 8 | Clarification of differences between variable achromatic color and variable chromatic color methods in the Helmholtz–Kohlrausch effect 9 | Yoshinobu Nayatani, Hideki Sakai 10 | https://doi.org/10.1002/col.20194 11 | 12 | Prediction of the Helmholtz-Kohlrausch effect using the CIELUV formula 13 | Yoshinobu Nayatani, Motohiro Nakajima 14 | https://doi.org/10.1002/(SICI)1520-6378(199608)21:4<252::AID-COL1>3.0.CO;2-P 15 | */ 16 | 17 | DEFINE_UI_PARAMS(in_gamut, input gamut, DCTLUI_COMBO_BOX, 1, {ap0, ap1, p3d65, rec2020, rec709, awg, rwg, sgamut3, blackmagicwg, egamut, davinciwg}, {ACES, ACEScg, P3D65, Rec.2020, Rec.709, Alexa Wide Gamut, Red Wide Gamut RGB, Sony SGamut3, Blackmagic Wide Gamut, Filmlight E - Gamut, DaVinci Wide Gamut}) 18 | DEFINE_UI_PARAMS(wp, whitepoint, DCTLUI_COMBO_BOX, 3, {D50, D55, D60, D65}, {D50, D55, D60, D65}) 19 | DEFINE_UI_PARAMS(La, L adapt, DCTLUI_SLIDER_FLOAT, 63.61, 0, 200, 1) 20 | DEFINE_UI_PARAMS(meth, method, DCTLUI_COMBO_BOX, 1, {VAC, VCC}, {VAC, VCC}) 21 | DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0) 22 | 23 | __CONSTANT__ float pi = 3.14159265358979323846f; 24 | 25 | // Custom 3x3 matrix struct float3x3 26 | typedef struct { 27 | float3 x, y, z; 28 | } float3x3; 29 | 30 | // Helper function to create a float3x3 31 | __DEVICE__ float3x3 make_float3x3(float3 a, float3 b, float3 c) { 32 | float3x3 d; 33 | d.x = a, d.y = b, d.z = c; 34 | return d; 35 | } 36 | 37 | // Multiply float3 vector a and 3x3 matrix m 38 | __DEVICE__ float3 mult_f3_f33(float3 a, float3x3 m) { 39 | return make_float3( 40 | m.x.x * a.x + m.x.y * a.y + m.x.z * a.z, 41 | m.y.x * a.x + m.y.y * a.y + m.y.z * a.z, 42 | m.z.x * a.x + m.z.y * a.y + m.z.z * a.z); 43 | } 44 | 45 | #define identity_mtx make_float3x3(make_float3(1.0f, 0.0f, 0.0f), make_float3(0.0f, 1.0f, 0.0f), make_float3(0.0f, 0.0f, 1.0f)) 46 | #define matrix_ap0_to_xyz make_float3x3(make_float3(0.950362384319f, 0.000000000000f, 0.000093463248f), make_float3(0.343966454268f, 0.728166162968f, -0.072132542729f), make_float3(0.000000000000f, 0.000000000000, 1.089057803154f)) 47 | #define matrix_ap1_to_xyz make_float3x3(make_float3(0.660931229591f, 0.133696138859f, 0.155828580260f), make_float3(0.272228747606f, 0.674081742764f, 0.053689509630f), make_float3(-0.006018006243f, 0.004383686464, 1.090692043304f)) 48 | #define matrix_p3d65_to_xyz make_float3x3(make_float3(0.486571133137f, 0.265667706728f, 0.198217317462f), make_float3(0.228974640369f, 0.691738605499f, 0.079286918044f), make_float3(-0.000000000000f, 0.045113388449, 1.043944478035f)) 49 | #define matrix_p3d60_to_xyz make_float3x3(make_float3(0.504949748516f, 0.264681518078f, 0.183015048504f), make_float3(0.237623393536f, 0.689170777798f, 0.073206014931f), make_float3(-0.000000000000f, 0.044945921749f, 0.963879227638f)) 50 | #define matrix_p3dci_to_xyz make_float3x3(make_float3(0.445170015097f, 0.277134418488f, 0.172282665968f), make_float3(0.209491759539f, 0.721595287323f, 0.068913064897f), make_float3(-0.000000000000f, 0.047060567886f, 0.907355427742f)) 51 | #define matrix_rec2020_to_xyz make_float3x3(make_float3(0.636958122253f, 0.144616916776f, 0.168880969286f), make_float3(0.262700229883f, 0.677998125553f, 0.059301715344f), make_float3(0.000000000000f, 0.028072696179, 1.060985088348f)) 52 | #define matrix_rec709_to_xyz make_float3x3(make_float3(0.412390917540f, 0.357584357262f, 0.180480793118f), make_float3(0.212639078498f, 0.715168714523f, 0.072192311287f), make_float3(0.019330825657f, 0.119194783270f, 0.950532138348f)) 53 | #define matrix_arriwg_to_xyz make_float3x3(make_float3(0.638007640839f, 0.214703813195f, 0.097744457424f), make_float3(0.291953772306f, 0.823840856552f, -0.115794822574f), make_float3(0.002798279049f, -0.067034222186, 1.153293848038f)) 54 | #define matrix_redwg_to_xyz make_float3x3(make_float3(0.735275208950f, 0.068609409034f, 0.146571278572f), make_float3(0.286694079638f, 0.842979073524f, -0.129673242569f), make_float3(-0.079680845141f, -0.347343206406, 1.516081929207f)) 55 | #define matrix_sonysgamut3 make_float3x3(make_float3(0.599083900452f, 0.248925492167f, 0.102446496487f), make_float3(0.215075820684f, 0.885068416595f, -0.100144319236f), make_float3(-0.032065849751f, -0.027658388019, 1.148782014847f)) 56 | #define matrix_blackmagicwg_to_xyz make_float3x3(make_float3(0.606538414955f, 0.220412746072f, 0.123504832387f), make_float3(0.267992943525f, 0.832748472691f, -0.100741356611f), make_float3(-0.029442556202f, -0.086612440646, 1.205112814903f)) 57 | #define matrix_egamut_to_xyz make_float3x3(make_float3(0.705396831036f, 0.164041340351f, 0.081017754972f), make_float3(0.280130714178f, 0.820206701756f, -0.100337378681f), make_float3(-0.103781513870f, -0.072907261550, 1.265746593475f)) 58 | #define matrix_davinciwg_to_xyz make_float3x3(make_float3(0.700622320175f, 0.148774802685f, 0.101058728993f), make_float3(0.274118483067f, 0.873631775379f, -0.147750422359f), make_float3(-0.098962903023f, -0.137895315886, 1.325916051865f)) 59 | 60 | __DEVICE__ float _radians(float d) {return d * (pi / 180.0f);} 61 | __DEVICE__ float _degrees(float r) {return r * (180.0f / pi);} 62 | __DEVICE__ float3 maxf3(float3 a, float b) { return make_float3(_fmaxf(a.x, b), _fmaxf(a.y, b), _fmaxf(a.z, b)); } 63 | 64 | 65 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 66 | { 67 | 68 | float3 rgb = make_float3(p_R, p_G, p_B); 69 | 70 | // Input gamut conversion to D65 aligned XYZ (CAT: xyz scaling) 71 | float3x3 in_to_xyz; 72 | if (in_gamut == ap0) in_to_xyz = matrix_ap0_to_xyz; 73 | else if (in_gamut == ap1) in_to_xyz = matrix_ap1_to_xyz; 74 | else if (in_gamut == p3d65) in_to_xyz = matrix_p3d65_to_xyz; 75 | else if (in_gamut == rec2020) in_to_xyz = matrix_rec2020_to_xyz; 76 | else if (in_gamut == rec709) in_to_xyz = matrix_rec709_to_xyz; 77 | else if (in_gamut == awg) in_to_xyz = matrix_arriwg_to_xyz; 78 | else if (in_gamut == rwg) in_to_xyz = matrix_redwg_to_xyz; 79 | else if (in_gamut == sgamut3) in_to_xyz = matrix_sonysgamut3; 80 | else if (in_gamut == blackmagicwg) in_to_xyz = matrix_blackmagicwg_to_xyz; 81 | else if (in_gamut == egamut) in_to_xyz = matrix_egamut_to_xyz; 82 | else if (in_gamut == davinciwg) in_to_xyz = matrix_davinciwg_to_xyz; 83 | 84 | // Reference white illuminant 85 | float2 w_xy; 86 | if (wp == D50) w_xy = make_float2(0.3457f, 0.3585f); 87 | else if (wp == D55) w_xy = make_float2(0.33243f, 0.34744f); 88 | else if (wp == D60) w_xy = make_float2(0.321626f, 0.337737f); 89 | else if (wp == D65) w_xy = make_float2(0.3127f, 0.329f); 90 | 91 | const float w_uv_d = (-2.0f * w_xy.x + 12.0f * w_xy.y + 3.0f); 92 | const float2 w_uv = make_float2(4.0f * w_xy.x / w_uv_d, 9.0f * w_xy.y / w_uv_d); 93 | 94 | // Convert RGB to XYZ 95 | float3 xyz = mult_f3_f33(rgb, in_to_xyz); 96 | 97 | xyz = maxf3(xyz, 0.0f); 98 | 99 | // Convert XYZ to L*u'v' 100 | float d = xyz.x + 15.0f * xyz.y + 3.0f * xyz.z; 101 | const float _e = 216.0f / 24389.0f; 102 | const float _k = 24389.0f / 27.0f; 103 | float3 Luv = make_float3((xyz.y > _e ? 116.0f * _powf(xyz.y, 1.0f / 3.0f) - 16.0f : xyz.y * _k) / 100.0f, 104 | d == 0.0f ? 0.0f : 4.0f * xyz.x / d, 105 | d == 0.0f ? 0.0f : 9.0f * xyz.y / d); 106 | 107 | // Calculate Nayatani 1997 Helmholtz-Kohlrausch compensation factor 108 | float m = meth == VAC ? -0.866f : -0.134f; 109 | const float K_Br = 0.2717f * (6.469f + 6.362f * _powf(La, 0.4495f)) / (6.469f + _powf(La, 0.4495f)); 110 | 111 | // Hue angle in radians 112 | float h = _atan2f(Luv.z - w_uv.y, Luv.y - w_uv.x); 113 | h = h < 0.0f ? h + _radians(360.0f) : h; 114 | 115 | float q = -0.01585f - 0.03017f * _cosf(h) - 0.04556f * _cosf(2.0f * h) - 0.02667f * _cosf(3.0f * h) - 0.00295f * _cosf(4.0f * h) + 0.14592f * _sinf(h) + 0.05084f * _sinf(2.0f * h) - 0.01900f * _sinf(3.0f * h) - 0.00764f * _sinf(4.0f * h); 116 | float S_uv = 13.0f * _hypotf(Luv.y - w_uv.x, Luv.z - w_uv.y); 117 | 118 | float s = (1.0f + (m * q + 0.0872f * K_Br) * S_uv); 119 | s = s == 0.0f ? 1.0f : 1.0f / s; 120 | 121 | if (invert == 1) 122 | rgb /= s; 123 | else 124 | rgb *= s; 125 | 126 | return rgb; 127 | 128 | }; -------------------------------------------------------------------------------- /look-transforms/tools/resolve/Purity.dctl: -------------------------------------------------------------------------------- 1 | /* Purity - v0.0.1 2 | ------------------------- 3 | Simpler weighted-sum based version of n6Purity. Probably more robust through variations in hue. 4 | 5 | --- 6 | Written by Jed Smith 7 | github.com/jedypod/open-display-transform 8 | */ 9 | 10 | DEFINE_UI_PARAMS(purity, purity, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 11 | DEFINE_UI_PARAMS(strength, strength, DCTLUI_SLIDER_FLOAT, 2, 0, 4, 0) 12 | DEFINE_UI_PARAMS(rw, red weight, DCTLUI_SLIDER_FLOAT, 0.25, 0.05, 1, 0) 13 | DEFINE_UI_PARAMS(bw, blue weight, DCTLUI_SLIDER_FLOAT, 0.1, 0.05, 1, 0) 14 | 15 | 16 | // Safe division of float a by float b 17 | __DEVICE__ float sdivf(float a, float b) { return _fabs(b) < 1e-3f ? 0.0f : a/b; } 18 | 19 | // Safe division of float3 a by float b 20 | __DEVICE__ float3 sdivf3f(float3 a, float b) { return make_float3(sdivf(a.x, b), sdivf(a.y, b), sdivf(a.z, b)); } 21 | 22 | // Safe power function raising float a to power float b 23 | __DEVICE__ float spowf(float a, float b) { return a <= 0.0f ? a : _powf(a, b); } 24 | 25 | // https://www.desmos.com/calculator/bdbstdsvvv 26 | __DEVICE__ float pivoted_power_cubic(float x, float m, float p) { 27 | m = 1.0f - _fabs(m); 28 | float a0 = p*(m - 1.0f); 29 | float b0 = (1.0f - m)*(p + 1.0f); 30 | return x <= 0.0f ? m*x : x > 1.0f ? x : x*(_powf(x, p)*(a0*x + b0) + m); 31 | } 32 | 33 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) { 34 | float3 rgb = make_float3(p_R, p_G, p_B); 35 | 36 | float mx = _fmaxf(rgb.x, _fmaxf(rgb.y, rgb.z)); 37 | float3 rats = sdivf3f(rgb, mx); // rgb ratios 38 | float3 rats_c = 1.0f - rats; // complement of rgb ratios 39 | 40 | float gw = 1.0f - (rw + bw); // green weight sums weights to 1 41 | 42 | float w = rats_c.x*rw + rats_c.y*gw + rats_c.z*bw; // "luminance" weights complement 43 | float c = _fmaxf(rats_c.x, _fmaxf(rats_c.y, rats_c.z)); // chroma 44 | 45 | float L = 1.0f - w; // "luminance" weights inside normalized rgb ratios 46 | w = sdivf(w, c); // chroma-normalized weights 47 | 48 | float f0 = sdivf(pivoted_power_cubic(c, purity, strength), c); 49 | float f1 = sdivf(1.0f - pivoted_power_cubic(1.0f - c, purity, strength), c); 50 | 51 | // Lerp factor for nonlinear "purity"/saturation adjustment. 52 | // decrease uses luminance weights (yellow highest, blue lowest) 53 | // increase uses chrominance weights (complement of luminance: yellow lowest, blue highest) 54 | float f = purity > 0.0f ? (w*f1 + (1.0f - w)) : ((1.0f - w)*f0 + w); 55 | 56 | // negatives could cause nan/inf in shadow grain. 57 | f = _fmaxf(0.0f, f); 58 | 59 | rats = L*(1.0f - f) + rats*f; 60 | 61 | rgb = rats * mx; 62 | 63 | return rgb; 64 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/Saturation.dctl: -------------------------------------------------------------------------------- 1 | DEFINE_UI_PARAMS(sag, global sat, DCTLUI_SLIDER_FLOAT, 1, 0, 2, 0) 2 | DEFINE_UI_PARAMS(sah, hue sat, DCTLUI_SLIDER_FLOAT, 1, 0, 2, 0) 3 | DEFINE_UI_PARAMS(ho, hue angle, DCTLUI_SLIDER_FLOAT, 1, 0, 6, 0) 4 | DEFINE_UI_PARAMS(hw, hue width, DCTLUI_SLIDER_FLOAT, 1, 0.1, 1.5, 0) 5 | DEFINE_UI_PARAMS(wr, weight red, DCTLUI_SLIDER_FLOAT, 0.23, 0, 1, 0) 6 | DEFINE_UI_PARAMS(wb, weight blue, DCTLUI_SLIDER_FLOAT, 0.08, 0, 1, 0) 7 | DEFINE_UI_PARAMS(lg, in log, DCTLUI_CHECK_BOX, 1) 8 | DEFINE_UI_PARAMS(ze, zone extract, DCTLUI_CHECK_BOX, 0) 9 | DEFINE_UI_PARAMS(zp, zone range, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 10 | DEFINE_UI_PARAMS(zone, zone, DCTLUI_COMBO_BOX, 1, {low, high}, {low, high}) 11 | DEFINE_UI_PARAMS(tf, Transfer Function, DCTLUI_COMBO_BOX, 1, {ioetf_linear, ioetf_davinci_intermediate, ioetf_acescct, ioetf_arri_logc3, ioetf_arri_logc4, ioetf_redlog3g10}, {Linear, Davinci Intermediate, ACEScct, Arri LogC3, Arri LogC4, RedLog3G10}) 12 | #include "libLMT.h" 13 | 14 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 15 | { 16 | float3 rgb = make_float3(p_R, p_G, p_B); 17 | rgb = linearize(rgb, tf, 0); 18 | 19 | int zr = zone == high ? 0 : 1; 20 | 21 | rgb = saturation(rgb, sag, sah, ho, hw, wr, wb, lg, ze, zp, zr); 22 | rgb = linearize(rgb, tf, 1); 23 | return rgb; 24 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/ShadowContrast.dctl: -------------------------------------------------------------------------------- 1 | #line 2 // Fix line numbers in resolve/logs/rollinglog.txt 2 | #include "libLMT.h" 3 | 4 | DEFINE_UI_PARAMS(ex, exposure, DCTLUI_SLIDER_FLOAT, 0.0, -6.0, 0.0, 0.0) 5 | DEFINE_UI_PARAMS(str, strength, DCTLUI_SLIDER_FLOAT, 0.5, 0.0, 1.0, 0.0) 6 | DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0) 7 | DEFINE_UI_PARAMS(tf, Transfer Function, DCTLUI_COMBO_BOX, 1, {ioetf_linear, ioetf_davinci_intermediate, ioetf_acescct, ioetf_arri_logc3, ioetf_arri_logc4, ioetf_redlog3g10}, {Linear, Davinci Intermediate, ACEScct, Arri LogC3, Arri LogC4, RedLog3G10}) 8 | 9 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 10 | { 11 | float3 rgb = make_float3(p_R, p_G, p_B); 12 | rgb = linearize(rgb, tf, 0); 13 | rgb = shd_con(rgb, ex, str, invert); 14 | rgb = linearize(rgb, tf, 1); 15 | return rgb; 16 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/XLog.dctl: -------------------------------------------------------------------------------- 1 | #line 2 // Fix line numbers in resolve/logs/rollinglog.txt 2 | /* XLog 3 | v0.0.1 4 | A flexible parameterized log function. This one has been floating around in my various tools for a while, 5 | but I figured it would be useful to have as a standalone. This is the variation that includes 6 | a linear extension at the specified slope value, instead of at a specific x coordinate. 7 | 8 | A couple of preset parameter values to start you off: 9 | XLog: Classic Cineon style log space for grading, similar to Filmlight's T-Log. 10 | w0 128 w1 1 o 7.5 k 0.06 x0 0 y0 0.075 11 | 12 | XLogHalf: Cineon style log space with less dynamic range up to 16. suitable for log grading in half float maybe? 13 | w0 16 w1 1 o 6.7 k 0.05 x0 0 y0 0.092 14 | 15 | XLogC: Camera encoding style log curve with an extended linear section in in the shadows, similar to Arri LogC3. 16 | w0 64 w1 1 o 7 k 0.18 x0 0.01 y0 0.15 17 | 18 | 19 | https://www.desmos.com/calculator/9pgjgo1gq4 20 | 21 | Google Colab Notebook with mathematical derivation and extra variations: 22 | https://colab.research.google.com/drive/1NwjaD0NzNMzQeNQqZECj33PdcYGkeBM4 23 | 24 | 25 | Written by Jed Smith 26 | https://github.com/jedypod/open-display-transform 27 | 28 | License: GPL v3 29 | */ 30 | 31 | DEFINE_UI_PARAMS(w0, high x intersect, DCTLUI_SLIDER_FLOAT, 16, 10, 256, 0.0) 32 | DEFINE_UI_PARAMS(o, slope, DCTLUI_SLIDER_FLOAT, 6.7, 0, 12, 0.0) 33 | DEFINE_UI_PARAMS(x0, low x intersect, DCTLUI_SLIDER_FLOAT, 0, 0, 0.5, 0.0) 34 | DEFINE_UI_PARAMS(y0, low y intersect, DCTLUI_SLIDER_FLOAT, 0.092, 0, 0.5, 0.0) 35 | DEFINE_UI_PARAMS(k, lin ext slope, DCTLUI_SLIDER_FLOAT, 0.05, 0, 0.2, 0.0) 36 | DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0) 37 | 38 | 39 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 40 | { 41 | 42 | /* Pre-Calculations */ 43 | // high y intersect is always 1.0 44 | const float w1 = 1.0f; 45 | // x offset: the y asymptote of the log curve 46 | const float o0 = -_powf(2.0f,-o); 47 | // s0: scale factor to satisfy intersection constraint at (x0, y0) 48 | const float s0 = (w1-y0)/_logf((w0-o0)/(x0-o0)); 49 | // o1: y offset to satisfy intersection constraint at (w0, w1) 50 | const float o1 = w1-s0*_logf(w0-o0); 51 | // x1: x coordinate of linear extension intercept (controlled by user-specified slope k) 52 | const float x1 = s0*log(k*s0*_expf(o1/s0)); 53 | // y1: is y coordinate of linear extension intercept 54 | const float y1 = _expf((x1-o1)/s0)+o0; 55 | // y (x=0) intercept of linear equation 56 | const float y2 = y1-k*x1; 57 | 58 | /* Shader Code */ 59 | float3 rgb = make_float3(p_R, p_G, p_B); 60 | 61 | if (invert) { 62 | rgb.x = rgb.x < x1 ? k*rgb.x+y2 : _expf((rgb.x - o1)/s0) + o0; 63 | rgb.y = rgb.y < x1 ? k*rgb.y+y2 : _expf((rgb.y - o1)/s0) + o0; 64 | rgb.z = rgb.z < x1 ? k*rgb.z+y2 : _expf((rgb.z - o1)/s0) + o0; 65 | } else { 66 | rgb.x = rgb.x < y1 ? (rgb.x - y2)/k : s0*_logf(rgb.x - o0) + o1; 67 | rgb.y = rgb.y < y1 ? (rgb.y - y2)/k : s0*_logf(rgb.y - o0) + o1; 68 | rgb.z = rgb.z < y1 ? (rgb.z - y2)/k : s0*_logf(rgb.z - o0) + o1; 69 | } 70 | 71 | return rgb; 72 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/ZoneExposureHigh.dctl: -------------------------------------------------------------------------------- 1 | #line 2 // Fix line numbers in resolve/logs/rollinglog.txt 2 | #include "libLMT.h" 3 | 4 | DEFINE_UI_PARAMS(ex, exposure, DCTLUI_SLIDER_FLOAT, 0.0, -5.0, 5.0, 0.0) 5 | DEFINE_UI_PARAMS(pv, pivot, DCTLUI_SLIDER_FLOAT, -1.0, -5.0, 5.0, 0.0) 6 | DEFINE_UI_PARAMS(fa, falloff, DCTLUI_SLIDER_FLOAT, 0.6, 0.0, 1.0, 0.0) 7 | DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0) 8 | DEFINE_UI_PARAMS(tf, Transfer Function, DCTLUI_COMBO_BOX, 1, {ioetf_linear, ioetf_davinci_intermediate, ioetf_acescct, ioetf_arri_logc3, ioetf_arri_logc4, ioetf_redlog3g10}, {Linear, Davinci Intermediate, ACEScct, Arri LogC3, Arri LogC4, RedLog3G10}) 9 | 10 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 11 | { 12 | float3 rgb = make_float3(p_R, p_G, p_B); 13 | rgb = linearize(rgb, tf, 0); 14 | rgb = ex_high(rgb, ex, pv, fa, invert); 15 | rgb = linearize(rgb, tf, 1); 16 | return rgb; 17 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/ZoneExposureLow.dctl: -------------------------------------------------------------------------------- 1 | #line 2 // Fix line numbers in resolve/logs/rollinglog.txt 2 | #include "libLMT.h" 3 | 4 | DEFINE_UI_PARAMS(ex, exposure, DCTLUI_SLIDER_FLOAT, 0.0, -5.0, 5.0, 0.0) 5 | DEFINE_UI_PARAMS(pv, pivot, DCTLUI_SLIDER_FLOAT, -1.0, -5.0, 5.0, 0.0) 6 | DEFINE_UI_PARAMS(fa, falloff, DCTLUI_SLIDER_FLOAT, 0.6, 0.0, 1.0, 0.0) 7 | DEFINE_UI_PARAMS(tf, Transfer Function, DCTLUI_COMBO_BOX, 1, {ioetf_linear, ioetf_davinci_intermediate, ioetf_acescct, ioetf_arri_logc3, ioetf_arri_logc4, ioetf_redlog3g10}, {Linear, Davinci Intermediate, ACEScct, Arri LogC3, Arri LogC4, RedLog3G10}) 8 | 9 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 10 | { 11 | float3 rgb = make_float3(p_R, p_G, p_B); 12 | rgb = linearize(rgb, tf, 0); 13 | rgb = ex_low(rgb, ex, pv, fa); 14 | rgb = linearize(rgb, tf, 1); 15 | return rgb; 16 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/ZoneGrade.dctl: -------------------------------------------------------------------------------- 1 | #line 2 // Fix line numbers in resolve/logs/rollinglog.txt 2 | #include "libLMT.h" 3 | 4 | DEFINE_UI_PARAMS(ex, exposure, DCTLUI_SLIDER_FLOAT, 0.0, -4.0, 4.0, 0.0) 5 | DEFINE_UI_PARAMS(c, contrast, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 6 | DEFINE_UI_PARAMS(pv, pivot, DCTLUI_SLIDER_FLOAT, 0.0, -4.0, 4.0, 0.0) 7 | DEFINE_UI_PARAMS(off, offset, DCTLUI_SLIDER_FLOAT, 0.0, -0.02, 0.02, 0.0) 8 | DEFINE_UI_PARAMS(he, exposure - H, DCTLUI_SLIDER_FLOAT, 0.0, -4.0, 4.0, 0.0) 9 | DEFINE_UI_PARAMS(hp, pivot - H, DCTLUI_SLIDER_FLOAT, -1.0, -4.0, 4.0, 0.0) 10 | DEFINE_UI_PARAMS(hf, falloff - H, DCTLUI_SLIDER_FLOAT, 0.6, 0.0, 1.0, 0.0) 11 | DEFINE_UI_PARAMS(le, exposure - L, DCTLUI_SLIDER_FLOAT, 0.0, -4.0, 4.0, 0.0) 12 | DEFINE_UI_PARAMS(lp, pivot - L, DCTLUI_SLIDER_FLOAT, 1.0, -4.0, 4.0, 0.0) 13 | DEFINE_UI_PARAMS(lf, falloff - L, DCTLUI_SLIDER_FLOAT, 0.6, 0.0, 1.0, 0.0) 14 | DEFINE_UI_PARAMS(he2, exposure - H2, DCTLUI_SLIDER_FLOAT, 0.0, -4.0, 4.0, 0.0) 15 | DEFINE_UI_PARAMS(hp2, pivot - H2, DCTLUI_SLIDER_FLOAT, 1.0, -4.0, 4.0, 0.0) 16 | DEFINE_UI_PARAMS(hf2, falloff - H2, DCTLUI_SLIDER_FLOAT, 0.6, 0.0, 1.0, 0.0) 17 | DEFINE_UI_PARAMS(le2, exposure - L2, DCTLUI_SLIDER_FLOAT, 0.0, -4.0, 4.0, 0.0) 18 | DEFINE_UI_PARAMS(lp2, pivot - L2, DCTLUI_SLIDER_FLOAT, -1.0, -4.0, 4.0, 0.0) 19 | DEFINE_UI_PARAMS(lf2, falloff - L2, DCTLUI_SLIDER_FLOAT, 0.6, 0.0, 1.0, 0.0) 20 | DEFINE_UI_PARAMS(tf, Transfer Function, DCTLUI_COMBO_BOX, 1, {ioetf_linear, ioetf_davinci_intermediate, ioetf_acescct, ioetf_arri_logc3, ioetf_arri_logc4, ioetf_redlog3g10}, {Linear, Davinci Intermediate, ACEScct, Arri LogC3, Arri LogC4, RedLog3G10}) 21 | 22 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 23 | { 24 | float3 rgb = make_float3(p_R, p_G, p_B); 25 | rgb = linearize(rgb, tf, 0); 26 | rgb = zone_grade(rgb, ex, c, pv, off, he, hp, hf, le, lp, lf, he2, hp2, hf2, le2, lp2, lf2); 27 | rgb = linearize(rgb, tf, 1); 28 | return rgb; 29 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/ZoneSaturation.dctl: -------------------------------------------------------------------------------- 1 | /* ZoneSaturation 2 | A zoned saturation control with per-hue angle controls. 3 | The zones are defined by a hyperbolic extraction of input 4 | 5 | Input should be scene-linear. 6 | 7 | --------------------------------------------------- 8 | v0.0.2 9 | Written by Jed Smith 10 | github.com/jedypod/open-display-transform 11 | */ 12 | 13 | DEFINE_UI_PARAMS(in_gamut, input gamut, DCTLUI_COMBO_BOX, 1, {ap0, ap1, p3d65, rec2020, rec709, awg, rwg, sgamut3, blackmagicwg, egamut, davinciwg}, {ACES, ACEScg, P3D65, Rec.2020, Rec.709, Alexa Wide Gamut, Red Wide Gamut RGB, Sony SGamut3, Blackmagic Wide Gamut, Filmlight E - Gamut, DaVinci Wide Gamut}) 14 | DEFINE_UI_PARAMS(sat, sat, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 15 | DEFINE_UI_PARAMS(sal, sat low, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 16 | DEFINE_UI_PARAMS(zrl, range low, DCTLUI_SLIDER_FLOAT, 0.0, -4.0, 4.0, 0.0) 17 | DEFINE_UI_PARAMS(sah, sat high, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 18 | DEFINE_UI_PARAMS(zrh, range high, DCTLUI_SLIDER_FLOAT, 0.0, -4.0, 4.0, 0.0) 19 | DEFINE_UI_PARAMS(sy, sat yellow, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 20 | DEFINE_UI_PARAMS(sr, sat red, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 21 | DEFINE_UI_PARAMS(sm, sat magenta, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 22 | DEFINE_UI_PARAMS(sb, sat blue, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 23 | DEFINE_UI_PARAMS(sc, sat cyan, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 24 | DEFINE_UI_PARAMS(sg, sat green, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.0) 25 | DEFINE_UI_PARAMS(pch, perceptual, DCTLUI_CHECK_BOX, 0) 26 | DEFINE_UI_PARAMS(zha, zone hue angle, DCTLUI_COMBO_BOX, 1, {none, low, high}, {none, low, high}) 27 | 28 | 29 | #define catd65 make_float3(1.07046f, 0.916817f, 0.594251f) 30 | // Gamut conversion Matrices 31 | #define identity_mtx make_float3x3(make_float3(1.0f, 0.0f, 0.0f), make_float3(0.0f, 1.0f, 0.0f), make_float3(0.0f, 0.0f, 1.0f)) 32 | #define matrix_ap0_to_xyz make_float3x3(make_float3(0.950362384319f, 0.000000000000f, 0.000093463248f), make_float3(0.343966454268f, 0.728166162968f, -0.072132542729f), make_float3(0.000000000000f, 0.000000000000, 1.089057803154f)) 33 | #define matrix_ap1_to_xyz make_float3x3(make_float3(0.660931229591f, 0.133696138859f, 0.155828580260f), make_float3(0.272228747606f, 0.674081742764f, 0.053689509630f), make_float3(-0.006018006243f, 0.004383686464, 1.090692043304f)) 34 | #define matrix_p3d65_to_xyz make_float3x3(make_float3(0.486571133137f, 0.265667706728f, 0.198217317462f), make_float3(0.228974640369f, 0.691738605499f, 0.079286918044f), make_float3(-0.000000000000f, 0.045113388449, 1.043944478035f)) 35 | #define matrix_p3d60_to_xyz make_float3x3(make_float3(0.504949748516f, 0.264681518078f, 0.183015048504f), make_float3(0.237623393536f, 0.689170777798f, 0.073206014931f), make_float3(-0.000000000000f, 0.044945921749f, 0.963879227638f)) 36 | #define matrix_p3dci_to_xyz make_float3x3(make_float3(0.445170015097f, 0.277134418488f, 0.172282665968f), make_float3(0.209491759539f, 0.721595287323f, 0.068913064897f), make_float3(-0.000000000000f, 0.047060567886f, 0.907355427742f)) 37 | #define matrix_rec2020_to_xyz make_float3x3(make_float3(0.636958122253f, 0.144616916776f, 0.168880969286f), make_float3(0.262700229883f, 0.677998125553f, 0.059301715344f), make_float3(0.000000000000f, 0.028072696179, 1.060985088348f)) 38 | #define matrix_rec709_to_xyz make_float3x3(make_float3(0.412390917540f, 0.357584357262f, 0.180480793118f), make_float3(0.212639078498f, 0.715168714523f, 0.072192311287f), make_float3(0.019330825657f, 0.119194783270f, 0.950532138348f)) 39 | #define matrix_arriwg_to_xyz make_float3x3(make_float3(0.638007640839f, 0.214703813195f, 0.097744457424f), make_float3(0.291953772306f, 0.823840856552f, -0.115794822574f), make_float3(0.002798279049f, -0.067034222186, 1.153293848038f)) 40 | #define matrix_redwg_to_xyz make_float3x3(make_float3(0.735275208950f, 0.068609409034f, 0.146571278572f), make_float3(0.286694079638f, 0.842979073524f, -0.129673242569f), make_float3(-0.079680845141f, -0.347343206406, 1.516081929207f)) 41 | #define matrix_sonysgamut3 make_float3x3(make_float3(0.599083900452f, 0.248925492167f, 0.102446496487f), make_float3(0.215075820684f, 0.885068416595f, -0.100144319236f), make_float3(-0.032065849751f, -0.027658388019, 1.148782014847f)) 42 | #define matrix_egamut_to_xyz make_float3x3(make_float3(0.705396831036f, 0.164041340351f, 0.081017754972f), make_float3(0.280130714178f, 0.820206701756f, -0.100337378681f), make_float3(-0.103781513870f, -0.072907261550, 1.265746593475f)) 43 | #define matrix_davinciwg_to_xyz make_float3x3(make_float3(0.700622320175f, 0.148774802685f, 0.101058728993f), make_float3(0.274118483067f, 0.873631775379f, -0.147750422359f), make_float3(-0.098962903023f, -0.137895315886, 1.325916051865f)) 44 | #define matrix_blackmagicwg_to_xyz make_float3x3(make_float3(0.606538414955f, 0.220412746072f, 0.123504832387f), make_float3(0.267992943525f, 0.832748472691f, -0.100741356611f), make_float3(-0.029442556202f, -0.086612440646, 1.205112814903f)) 45 | 46 | /* Matrix for conversion from CIE 1931 XYZ tristumulus to CIE 2006 LMS or "Truelight LMS", described in: 47 | "Chromaticity Coordinates for Graphic Arts Based on CIE 2006 LMS with Even Spacing of Munsell Colours" by Richard Kirk 48 | https://doi.org/10.2352/issn.2169-2629.2019.27.38 49 | */ 50 | #define matrix_xyz_to_truelightlms make_float3x3(make_float3(0.257085f, 0.859943f, -0.031061f), make_float3(-0.394427, 1.175800f, 0.106423f), make_float3(0.064856f, -0.07625f, 0.559067f)) 51 | 52 | #define matrix_jzazbz_xyz_to_lms make_float3x3(make_float3(0.41479f, 0.579999f, 0.014648f), make_float3(-0.20151f, 1.12065f, 0.0531008f), make_float3(-0.0166008f, 0.2648f, 0.66848f)) 53 | #define matrix_jzazbz_lms_p_to_izazbz make_float3x3(make_float3(0.5f, 0.5f, 0.0f), make_float3(3.524f, -4.06671f, 0.542708f), make_float3(0.199076f, 1.0968f, -1.29588f)) 54 | 55 | 56 | 57 | 58 | // Custom 3x3 matrix struct float3x3 59 | typedef struct { 60 | float3 x, y, z; 61 | } float3x3; 62 | 63 | __DEVICE__ float extract(float e0, float e1, float x) { 64 | // Extract a range from e0 to e1 from f, clamping values above or below. 65 | return _clampf((x - e0) / (e1 - e0), 0.0f, 1.0f); 66 | } 67 | 68 | __DEVICE__ float extract_window(float e0, float e1, float e2, float e3, float x) { 69 | // Linear window function to extract a range from float x 70 | // https://www.desmos.com/calculator/uzsk5ta5v7 71 | return x < e1 ? extract(e0, e1, x) : extract(e3, e2, x); 72 | } 73 | 74 | __DEVICE__ float extract_hue_angle(float h, float o, float w) { 75 | // Given hue, offset, width, and chroma, extract hue angle 76 | float hc = extract_window(2.0f - w, 2.0f, 2.0f, 2.0f + w, _fmod(h + o, 6.0f)); 77 | hc = hc * hc * (3.0f - 2.0f * hc); // smoothstep 78 | return hc; 79 | } 80 | 81 | 82 | __DEVICE__ float _sign(float x) { 83 | // Return the sign of float x 84 | if (x > 0.0f) return 1.0f; 85 | if (x < 0.0f) return -1.0f; 86 | return 0.0f; 87 | } 88 | __DEVICE__ float3 powf3(float3 a, float b) { 89 | // Raise each component of float3 a to power b 90 | return make_float3(_powf(a.x, b), _powf(a.y, b), _powf(a.z, b)); 91 | } 92 | 93 | __DEVICE__ float3 spowf3(float3 a, float b) { 94 | // Compute "safe" power of float3 a, reflected over the origin 95 | return make_float3( 96 | _sign(a.x)*_powf(_fabs(a.x), b), 97 | _sign(a.y)*_powf(_fabs(a.y), b), 98 | _sign(a.z)*_powf(_fabs(a.z), b)); 99 | } 100 | 101 | __DEVICE__ float3 cartesian_to_polar(float3 a) { 102 | return make_float3(a.x, _hypotf(a.y, a.z), _atan2f(a.z, a.y)); 103 | } 104 | 105 | __DEVICE__ float3 polar_to_cartesian(float3 a) { 106 | return make_float3(a.x, a.y * _cosf(a.z), a.y * _sinf(a.z)); 107 | } 108 | 109 | 110 | // Helper function to create a float3x3 111 | __DEVICE__ float3x3 make_float3x3(float3 a, float3 b, float3 c) { 112 | float3x3 d; 113 | d.x = a, d.y = b, d.z = c; 114 | return d; 115 | } 116 | // Multiply float3 vector a and 3x3 matrix m 117 | __DEVICE__ float3 mult_f3_f33(float3 a, float3x3 m) { 118 | return make_float3( 119 | m.x.x * a.x + m.x.y * a.y + m.x.z * a.z, 120 | m.y.x * a.x + m.y.y * a.y + m.y.z * a.z, 121 | m.z.x * a.x + m.z.y * a.y + m.z.z * a.z); 122 | } 123 | // Calculate inverse of 3x3 matrix: https://stackoverflow.com/questions/983999/simple-3x3-matrix-inverse-code-c 124 | __DEVICE__ float3x3 inv_f33(float3x3 m) { 125 | float d = m.x.x * (m.y.y * m.z.z - m.z.y * m.y.z) - 126 | m.x.y * (m.y.x * m.z.z - m.y.z * m.z.x) + 127 | m.x.z * (m.y.x * m.z.y - m.y.y * m.z.x); 128 | float id = 1.0f / d; 129 | float3x3 c = identity_mtx; 130 | c.x.x = id * (m.y.y * m.z.z - m.z.y * m.y.z); 131 | c.x.y = id * (m.x.z * m.z.y - m.x.y * m.z.z); 132 | c.x.z = id * (m.x.y * m.y.z - m.x.z * m.y.y); 133 | c.y.x = id * (m.y.z * m.z.x - m.y.x * m.z.z); 134 | c.y.y = id * (m.x.x * m.z.z - m.x.z * m.z.x); 135 | c.y.z = id * (m.y.x * m.x.z - m.x.x * m.y.z); 136 | c.z.x = id * (m.y.x * m.z.y - m.z.x * m.y.y); 137 | c.z.y = id * (m.z.x * m.x.y - m.x.x * m.z.y); 138 | c.z.z = id * (m.x.x * m.y.y - m.y.x * m.x.y); 139 | return c; 140 | } 141 | 142 | __DEVICE__ float hue(float3 rgb) { 143 | // Calculate and return hue in degrees between 0 and 6 144 | float mx = _fmaxf(rgb.x, _fmaxf(rgb.y, rgb.z)); 145 | float mn = _fminf(rgb.x, _fminf(rgb.y, rgb.z)); 146 | float ch = mx - mn; 147 | float h; 148 | if (ch == 0.0f) h = 0.0f; 149 | else if (mx == rgb.x) h = _fmod((rgb.y - rgb.z) / ch + 6.0f, 6.0f); 150 | else if (mx == rgb.y) h = (rgb.z - rgb.x) / ch + 2.0f; 151 | else if (mx == rgb.z) h = (rgb.x - rgb.y) / ch + 4.0f; 152 | return h; 153 | } 154 | 155 | 156 | __DEVICE__ float3 eotf_pq(float3 rgb, int inverse, int jz) { 157 | // Apply the ST-2084 PQ Forward or Inverse EOTF 158 | // Normalized such that input display linear light code value 1.0 equals 10,000 nits 159 | // ITU-R Rec BT.2100-2 https://www.itu.int/rec/R-REC-BT.2100 160 | // ITU-R Rep BT.2390-9 https://www.itu.int/pub/R-REP-BT.2390 161 | 162 | float Lp = 1.0f; // We normalize for hdr peak display luminance elsewhere. 163 | const float m1 = 2610.0f / 16384.0f; 164 | float m2 = 2523.0f / 32.0f; 165 | const float c1 = 107.0f / 128.0f; 166 | const float c2 = 2413.0f / 128.0f; 167 | const float c3 = 2392.0f / 128.0f; 168 | 169 | // Custom values for JzAzBz colorspace 170 | if (jz == 1) { 171 | m2 *= 1.7f; 172 | Lp = 10000.0f; 173 | } 174 | 175 | if (inverse == 1) { 176 | rgb /= Lp; 177 | rgb = spowf3(rgb, m1); 178 | // Prevent shitting of the bed when there are negatives, for JzAzBz conversion 179 | rgb.x = _sign(rgb.x) * _powf((c1 + c2 * _fabs(rgb.x)) / (1.0f + c3 * _fabs(rgb.x)), m2); 180 | rgb.y = _sign(rgb.y) * _powf((c1 + c2 * _fabs(rgb.y)) / (1.0f + c3 * _fabs(rgb.y)), m2); 181 | rgb.z = _sign(rgb.z) * _powf((c1 + c2 * _fabs(rgb.z)) / (1.0f + c3 * _fabs(rgb.z)), m2); 182 | } else { 183 | rgb = spowf3(rgb, 1.0f / m2); 184 | rgb.x = _sign(rgb.x) * _powf((_fabs(rgb.x) - c1) / (c2 - c3 * _fabs(rgb.x)), 1.0f / m1) * Lp; 185 | rgb.y = _sign(rgb.y) * _powf((_fabs(rgb.y) - c1) / (c2 - c3 * _fabs(rgb.y)), 1.0f / m1) * Lp; 186 | rgb.z = _sign(rgb.z) * _powf((_fabs(rgb.z) - c1) / (c2 - c3 * _fabs(rgb.z)), 1.0f / m1) * Lp; 187 | } 188 | return rgb; 189 | } 190 | __DEVICE__ float3 xyz_to_jzlms(float3 xyz) { 191 | float3 lms; 192 | lms = make_float3(1.15f * xyz.x - (1.15f - 1.0f) * xyz.z, 193 | 0.66f * xyz.y - (0.66f - 1.0f) * xyz.x, 194 | xyz.z); 195 | lms = mult_f3_f33(lms, matrix_jzazbz_xyz_to_lms); 196 | return lms; 197 | } 198 | 199 | __DEVICE__ float3 jzlms_to_xyz(float3 lms) { 200 | float3 xyz; 201 | xyz = mult_f3_f33(lms, inv_f33(matrix_jzazbz_xyz_to_lms)); 202 | xyz = make_float3( 203 | (xyz.x + (1.15f - 1.0f) * xyz.z) / 1.15f, 204 | (xyz.y + (0.66f - 1.0f) * ((xyz.x + (1.15f - 1.0f) * xyz.z) / 1.15f)) / 0.66f, 205 | xyz.z); 206 | return xyz; 207 | } 208 | 209 | __DEVICE__ float3 xyz_to_jzazbz(float3 xyz, int cyl) { 210 | // Convert input XYZ D65 aligned tristimulus values into JzAzBz perceptual colorspace, 211 | // if cyl==1: output cylindrical JCh : J = luma, C = chroma, h = hue in radians 212 | const float d = -0.56f; 213 | const float d_0 = 1.6295499532821565e-11f; 214 | float3 lms; 215 | lms = xyz_to_jzlms(xyz); 216 | lms = eotf_pq(lms, 1, 1); 217 | lms = mult_f3_f33(lms, matrix_jzazbz_lms_p_to_izazbz); 218 | lms.x = lms.x * (1.0f + d) / (1.0f + d * lms.x) - d_0; 219 | 220 | // Convert to cylindrical 221 | if (cyl == 1) lms = cartesian_to_polar(lms); 222 | 223 | return lms; 224 | } 225 | 226 | 227 | __DEVICE__ float3 jzazbz_to_xyz(float3 jz, int cyl) { 228 | const float d = -0.56f; 229 | const float d_0 = 1.6295499532821565e-11f; 230 | // Convert to cartesian 231 | if (cyl == 1) jz = polar_to_cartesian(jz); 232 | 233 | jz.x = (jz.x + d_0) / (1.0f + d - d * (jz.x + d_0)); 234 | jz = mult_f3_f33(jz, inv_f33(matrix_jzazbz_lms_p_to_izazbz)); 235 | jz = eotf_pq(jz, 0, 1); 236 | jz = jzlms_to_xyz(jz); 237 | return jz; 238 | } 239 | 240 | 241 | 242 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 243 | { 244 | float3 rgb, lms, xyz; 245 | const float3x3 xyz_to_lms = matrix_xyz_to_truelightlms; 246 | const float3x3 lms_to_xyz = inv_f33(matrix_xyz_to_truelightlms); 247 | 248 | // Input gamut conversion to D65 aligned XYZ (CAT: xyz scaling) 249 | float3x3 in_to_xyz; 250 | if (in_gamut == ap0) in_to_xyz = matrix_ap0_to_xyz; 251 | else if (in_gamut == ap1) in_to_xyz = matrix_ap1_to_xyz; 252 | else if (in_gamut == p3d65) in_to_xyz = matrix_p3d65_to_xyz; 253 | else if (in_gamut == rec2020) in_to_xyz = matrix_rec2020_to_xyz; 254 | else if (in_gamut == rec709) in_to_xyz = matrix_rec709_to_xyz; 255 | else if (in_gamut == awg) in_to_xyz = matrix_arriwg_to_xyz; 256 | else if (in_gamut == rwg) in_to_xyz = matrix_redwg_to_xyz; 257 | else if (in_gamut == sgamut3) in_to_xyz = matrix_sonysgamut3; 258 | else if (in_gamut == blackmagicwg) in_to_xyz = matrix_blackmagicwg_to_xyz; 259 | else if (in_gamut == egamut) in_to_xyz = matrix_egamut_to_xyz; 260 | else if (in_gamut == davinciwg) in_to_xyz = matrix_davinciwg_to_xyz; 261 | const float3x3 xyz_to_in = inv_f33(in_to_xyz); 262 | 263 | 264 | rgb = make_float3(p_R, p_G, p_B); 265 | 266 | xyz = mult_f3_f33(rgb, in_to_xyz); 267 | lms = mult_f3_f33(xyz, xyz_to_lms); 268 | lms /= catd65; 269 | 270 | float n = (lms.x + lms.y + lms.z) / 3.0f; 271 | float fh = _powf(n / (n + 1.0f), 1.0f / _powf(2.0f, zrh)); 272 | float fl = _powf(1.0f / (n + 1.0f), 1.0f / _powf(2.0f, zrl)); 273 | 274 | float fha; // factor for hue angle 275 | if (zha == none) fha = 1.0f; 276 | else if (zha == low) fha = fl; 277 | else if (zha == high) fha = fh; 278 | 279 | // Global saturation 280 | lms = n * (1.0f - sat) + lms * sat; 281 | 282 | // Zoned saturation low 283 | lms = lms * (1.0f - fh) + (n * (1.0f - sah) + lms * sah) * fh; 284 | 285 | // Zoned saturation high 286 | lms = lms * (1.0f - fl) + (n * (1.0f - sal) + lms * sal) * fl; 287 | 288 | // Hue Angle Controls 289 | float h = hue(rgb); 290 | // hue extraction for primaries (RGB) 291 | float3 hep = make_float3( 292 | extract_hue_angle(h, 2.0f, 1.0f), 293 | extract_hue_angle(h, 6.0f, 1.0f), 294 | extract_hue_angle(h, 4.0f, 1.0f)); 295 | // hue extraction for secondaries (CMY) 296 | float3 hes = make_float3( 297 | extract_hue_angle(h, 5.0f, 1.0f), 298 | extract_hue_angle(h, 3.0f, 1.0f), 299 | extract_hue_angle(h, 1.0f, 1.0f)); 300 | // Per hue angle saturation, mixed by factor hue angle fha 301 | lms.x = lms.x*(1.0f-fha)+((n*(1.0f-sr)+lms.x*sr)*hep.x+(n*(1.0f-sg)+lms.x*sg)*hep.y+(n*(1.0f-sb)+lms.x*sb)*hep.z+lms.x*(1.0f-(hep.x+hep.y+hep.z)))*fha; 302 | lms.y = lms.y*(1.0f-fha)+((n*(1.0f-sr)+lms.y*sr)*hep.x+(n*(1.0f-sg)+lms.y*sg)*hep.y+(n*(1.0f-sb)+lms.y*sb)*hep.z+lms.y*(1.0f-(hep.x+hep.y+hep.z)))*fha; 303 | lms.z = lms.z*(1.0f-fha)+((n*(1.0f-sr)+lms.z*sr)*hep.x+(n*(1.0f-sg)+lms.z*sg)*hep.y+(n*(1.0f-sb)+lms.z*sb)*hep.z+lms.z*(1.0f-(hep.x+hep.y+hep.z)))*fha; 304 | 305 | lms.x = lms.x*(1.0f-fha)+((n*(1.0f-sc)+lms.x*sc)*hes.x+(n*(1.0f-sm)+lms.x*sm)*hes.y+(n*(1.0f-sy)+lms.x*sy)*hes.z+lms.x*(1.0f-(hes.x+hes.y+hes.z)))*fha; 306 | lms.y = lms.y*(1.0f-fha)+((n*(1.0f-sc)+lms.y*sc)*hes.x+(n*(1.0f-sm)+lms.y*sm)*hes.y+(n*(1.0f-sy)+lms.y*sy)*hes.z+lms.y*(1.0f-(hes.x+hes.y+hes.z)))*fha; 307 | lms.z = lms.z*(1.0f-fha)+((n*(1.0f-sc)+lms.z*sc)*hes.x+(n*(1.0f-sm)+lms.z*sm)*hes.y+(n*(1.0f-sy)+lms.z*sy)*hes.z+lms.z*(1.0f-(hes.x+hes.y+hes.z)))*fha; 308 | 309 | lms *= catd65; 310 | float3 out_xyz = mult_f3_f33(lms, lms_to_xyz); 311 | 312 | if (pch == 1) { 313 | float3 jz = xyz_to_jzazbz(out_xyz, 1); 314 | float3 jz_nch = xyz_to_jzazbz(xyz, 1); 315 | jz.z = jz_nch.z; 316 | out_xyz = jzazbz_to_xyz(jz, 1); 317 | } 318 | 319 | rgb = mult_f3_f33(out_xyz, xyz_to_in); 320 | 321 | return rgb; 322 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/n6ChromaValue.dctl: -------------------------------------------------------------------------------- 1 | #line 2 // Fix line numbers in resolve/logs/rollinglog.txt 2 | #include "libLMT.h" 3 | 4 | DEFINE_UI_PARAMS(my, yellow, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 5 | DEFINE_UI_PARAMS(mr, red, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 6 | DEFINE_UI_PARAMS(mm, magenta, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 7 | DEFINE_UI_PARAMS(mb, blue, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 8 | DEFINE_UI_PARAMS(mc, cyan, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 9 | DEFINE_UI_PARAMS(mg, green, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 10 | DEFINE_UI_PARAMS(hs_rgb, hue strength rgb, DCTLUI_SLIDER_FLOAT, 2, 1, 4, 0) 11 | DEFINE_UI_PARAMS(hs_cmy, hue strength cmy, DCTLUI_SLIDER_FLOAT, 2, 1, 4, 0) 12 | DEFINE_UI_PARAMS(chs, chroma strength, DCTLUI_SLIDER_FLOAT, 0.5, 0, 1, 0) 13 | DEFINE_UI_PARAMS(chl, chroma limit, DCTLUI_SLIDER_FLOAT, 0.0, 0, 1, 0) 14 | DEFINE_UI_PARAMS(ze, zone extract, DCTLUI_CHECK_BOX, 0) 15 | DEFINE_UI_PARAMS(zp, zone range, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 16 | DEFINE_UI_PARAMS(zone, zone, DCTLUI_COMBO_BOX, 1, {low, high}, {low, high}) 17 | DEFINE_UI_PARAMS(tf, Transfer Function, DCTLUI_COMBO_BOX, 1, {ioetf_linear, ioetf_davinci_intermediate, ioetf_acescct, ioetf_arri_logc3, ioetf_arri_logc4, ioetf_redlog3g10}, {Linear, Davinci Intermediate, ACEScct, Arri LogC3, Arri LogC4, RedLog3G10}) 18 | 19 | 20 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 21 | { 22 | float3 rgb = make_float3(p_R, p_G, p_B); 23 | rgb = linearize(rgb, tf, 0); 24 | 25 | int zr = 0; 26 | if (zone == high) zr = 1; 27 | 28 | rgb = n6_chroma_value(rgb, my, mr, mm, mb, mc, mg, hs_rgb, hs_cmy, chs, chl, ze, zp, zr); 29 | rgb = linearize(rgb, tf, 1); 30 | return rgb; 31 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/n6CrossTalk.dctl: -------------------------------------------------------------------------------- 1 | /* n6CrossTalk - v0.0.1 2 | ------------------------- 3 | Another tool for distorting hues in an intentional way. 4 | Similar to n6HueShift, but with more flexibility and control. 5 | Uses different methods for distorting hue for primaries and secondaries. 6 | Includes power adjustment for each hue angle to adjust the strength: How much 7 | to distort chrominance near achromatic. 8 | 9 | Also includes a scale for each hue angle. This control scales the vector 10 | up and distorts towards the hue angle a bit. Effectively brightening or 11 | darkening the color while introducing small hue shifts towards or away 12 | from the hue angle in question. 13 | 14 | CMY hue angles also include control for offsetting the "center" of the hue angle. 15 | This can be useful for yellows for example, where you might want to place the 16 | center point slightly more towards orange-red than purely on the yellow secondary. 17 | 18 | The same control is not included for RGB because in my testing it was not needed. 19 | 20 | --- 21 | Written by Jed Smith 22 | github.com/jedypod/open-display-transform 23 | */ 24 | 25 | DEFINE_UI_PARAMS(yp, yellow power, DCTLUI_SLIDER_FLOAT, 1, 0, 1, 0) 26 | DEFINE_UI_PARAMS(y0, yellow shift 0: G->R, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 27 | DEFINE_UI_PARAMS(y1, yellow shift 1: G->R, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 28 | DEFINE_UI_PARAMS(ys, yellow scale, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 29 | DEFINE_UI_PARAMS(rp, red power, DCTLUI_SLIDER_FLOAT, 1, 0, 1, 0) 30 | DEFINE_UI_PARAMS(r0, red shift 0: Y->M, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 31 | DEFINE_UI_PARAMS(r1, red shift 1: Y->M, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 32 | DEFINE_UI_PARAMS(rs, red scale, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 33 | DEFINE_UI_PARAMS(mp, magenta power, DCTLUI_SLIDER_FLOAT, 1, 0, 1, 0) 34 | DEFINE_UI_PARAMS(m0, magenta shift 0: R->B, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 35 | DEFINE_UI_PARAMS(m1, magenta shift 1: R->B, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 36 | DEFINE_UI_PARAMS(ms, magenta scale, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 37 | DEFINE_UI_PARAMS(bp, blue power, DCTLUI_SLIDER_FLOAT, 1, 0, 1, 0) 38 | DEFINE_UI_PARAMS(b0, blue shift 0: M->C, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 39 | DEFINE_UI_PARAMS(b1, blue shift 1: M->C, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 40 | DEFINE_UI_PARAMS(bs, blue scale, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 41 | DEFINE_UI_PARAMS(cp, cyan power, DCTLUI_SLIDER_FLOAT, 1, 0, 1, 0) 42 | DEFINE_UI_PARAMS(c0, cyan shift 0: G->B, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 43 | DEFINE_UI_PARAMS(c1, cyan shift 1: G->B, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 44 | DEFINE_UI_PARAMS(cs, cyan scale, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 45 | DEFINE_UI_PARAMS(gp, green power, DCTLUI_SLIDER_FLOAT, 1, 0, 1, 0) 46 | DEFINE_UI_PARAMS(g0, green shift 0: C->Y, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 47 | DEFINE_UI_PARAMS(g1, green shift 1: C->Y, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 48 | DEFINE_UI_PARAMS(gs, green scale, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 49 | DEFINE_UI_PARAMS(cc, cyan center, DCTLUI_SLIDER_FLOAT, 0.25, -0.8, 0.8, 0) 50 | DEFINE_UI_PARAMS(mc, magenta center, DCTLUI_SLIDER_FLOAT, 0, -0.8, 0.8, 0) 51 | DEFINE_UI_PARAMS(yc, yellow center, DCTLUI_SLIDER_FLOAT, -0.25, -0.8, 0.8, 0) 52 | 53 | 54 | // Safe division of float a by float b 55 | __DEVICE__ float sdivf(float a, float b) { 56 | if (_fabs(b) < 0.0001f) return 0.0f; 57 | else return a / b; 58 | } 59 | // Safe division of float3 a by float b 60 | __DEVICE__ float3 sdivf3f(float3 a, float b) { 61 | return make_float3(sdivf(a.x, b), sdivf(a.y, b), sdivf(a.z, b)); 62 | } 63 | // Safe power function raising float a to power float b 64 | __DEVICE__ float spowf(float a, float b) { 65 | if (a <= 0.0f) return a; 66 | else return _powf(a, b); 67 | } 68 | // Take the max of each component of float3 a and float b 69 | __DEVICE__ float3 maxf3(float3 a, float b) { 70 | return make_float3(_fmaxf(a.x, b), _fmaxf(a.y, b), _fmaxf(a.z, b)); 71 | } 72 | 73 | // https://www.desmos.com/calculator/8tqz4rs0wm 74 | __DEVICE__ float power_window(float x, float c, float p0, float p1, float x0, float x1) { 75 | return x > x1 ? 0.0f : x > c ? _powf(1.0f - _powf((x - c)/(x1 - c), p0), p1) : x > x0 ? _powf(1.0f - _powf((c - x)/(c - x0), p0), p1) : 0.0f; 76 | } 77 | 78 | 79 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 80 | { 81 | float3 rgb = make_float3(p_R, p_G, p_B); 82 | 83 | // Calculate hue and "chroma" 84 | float mx = _fmaxf(rgb.x, _fmaxf(rgb.y, rgb.z)); 85 | float mn = _fminf(rgb.x, _fminf(rgb.y, rgb.z)); 86 | float ch = mx - mn; 87 | float h; 88 | if (ch == 0.0f) h = 0.0f; 89 | else if (mx == rgb.x) h = _fmod((rgb.y - rgb.z) / ch + 6.0f, 6.0f); 90 | else if (mx == rgb.y) h = (rgb.z - rgb.x) / ch + 2.0f; 91 | else if (mx == rgb.z) h = (rgb.x - rgb.y) / ch + 4.0f; 92 | ch = sdivf(ch, mx); 93 | // Clamp 0-4 94 | ch = _fmaxf(0.0f, _fminf(4.0f, ch)); 95 | 96 | // "Half-Chroma" Norm: halfway between min and max of rgb 97 | float hch = mn*0.5f + mx*0.5f; 98 | 99 | // RGB Ratios 100 | rgb = sdivf3f(rgb, hch); 101 | rgb = maxf3(rgb, -2.0f); 102 | 103 | // Extract hue angles 104 | float hr = power_window(_fmod(h + 1.0f, 6.0f), 1.0f, 1.5f, 1.5f, 0.0f, 2.0f)*spowf(ch, 1.0f/_fmaxf(1e-5, rp)); 105 | float hg = power_window(_fmod(h + 5.0f, 6.0f), 1.0f, 1.5f, 1.5f, 0.0f, 2.0f)*spowf(ch, 1.0f/_fmaxf(1e-5, gp)); 106 | float hb = power_window(_fmod(h + 3.0f, 6.0f), 1.0f, 1.5f, 1.5f, 0.0f, 2.0f)*spowf(ch, 1.0f/_fmaxf(1e-5, bp)); 107 | float hc = power_window(_fmod(h + 4.0f, 6.0f), 1.0f+cc, 1.5f, 1.5f, 0.0f, 2.0f)*spowf(ch, 1.0f/_fmaxf(1e-5, cp)); 108 | float hm = power_window(_fmod(h + 2.0f, 6.0f), 1.0f+mc, 1.5f, 1.5f, 0.0f, 2.0f)*spowf(ch, 1.0f/_fmaxf(1e-5, mp)); 109 | float hy = power_window(_fmod(h + 0.0f, 6.0f), 1.0f+yc, 1.5f, 1.5f, 0.0f, 2.0f)*spowf(ch, 1.0f/_fmaxf(1e-5, yp)); 110 | 111 | // Distort CMY hue angles 112 | rgb.x = (ms+1.0f)*(rgb.x-_fmaxf(0.0f,m0)-_fminf(0.0f,m1))*hm+(ys+1.0f)*(rgb.x+_fminf(0.0f,y0)+_fmaxf(0.0f,y1))*hy+rgb.x*(1.0f-(hm+hy)); 113 | rgb.y = (cs+1.0f)*(rgb.y-_fmaxf(0.0f,c0)-_fminf(0.0f,c1))*hc+(ys+1.0f)*(rgb.y-_fmaxf(0.0f,y0)-_fminf(0.0f,y1))*hy+rgb.y*(1.0f-(hc+hy)); 114 | rgb.z = (cs+1.0f)*(rgb.z+_fminf(0.0f,c0)+_fmaxf(0.0f,c1))*hc+(ms+1.0f)*(rgb.z+_fminf(0.0f,m0)+_fmaxf(0.0f,m1))*hm+rgb.z*(1.0f-(hc+hm)); 115 | 116 | // Distort RGB hue angles 117 | rgb.x = (rs+1.0f)*rgb.x*hr+rgb.x*(1.0f+_fminf(0.0f,g0))*(1.0f+_fmaxf(0.0f,g1))*hg+rgb.x*(1.0f-_fmaxf(0.0f,b0))*(1.0f-_fminf(0.0f,b1))*hb+rgb.x*(1.0f-(hr+hg+hb)); 118 | rgb.y = (gs+1.0f)*rgb.y*hg+rgb.y*(1.0f-_fmaxf(0.0f,r0))*(1.0f-_fminf(0.0f,r1))*hr+rgb.y*(1.0f+_fminf(0.0f,b0))*(1.0f+_fmaxf(0.0f,b1))*hb+rgb.y*(1.0f-(hr+hg+hb)); 119 | rgb.z = (bs+1.0f)*rgb.z*hb+rgb.z*(1.0f+_fminf(0.0f,r0))*(1.0f+_fmaxf(0.0f,r1))*hr+rgb.z*(1.0f-_fmaxf(0.0f,g0))*(1.0f-_fminf(0.0f,g1))*hg+rgb.z*(1.0f-(hr+hg+hb)); 120 | 121 | rgb *= hch; 122 | return rgb; 123 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/n6HueShift.dctl: -------------------------------------------------------------------------------- 1 | #line 2 // Fix line numbers in resolve/logs/rollinglog.txt 2 | #include "libLMT.h" 3 | 4 | DEFINE_UI_PARAMS(sy, yellow, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 5 | DEFINE_UI_PARAMS(sr, red, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 6 | DEFINE_UI_PARAMS(sm, magenta, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 7 | DEFINE_UI_PARAMS(sb, blue, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 8 | DEFINE_UI_PARAMS(sc, cyan, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 9 | DEFINE_UI_PARAMS(sg, green, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 10 | DEFINE_UI_PARAMS(scu, custom, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 11 | DEFINE_UI_PARAMS(cuh, custom hue, DCTLUI_SLIDER_FLOAT, 100, 0, 360, 0) 12 | DEFINE_UI_PARAMS(cuw, custom width, DCTLUI_SLIDER_FLOAT, 0.3, 0, 2, 0) 13 | DEFINE_UI_PARAMS(str, strength, DCTLUI_SLIDER_FLOAT, 0.33, 0.1, 1, 0) 14 | DEFINE_UI_PARAMS(chl, chroma limit, DCTLUI_SLIDER_FLOAT, 0.33, 0, 1, 0) 15 | DEFINE_UI_PARAMS(ze, zone extract, DCTLUI_CHECK_BOX, 0) 16 | DEFINE_UI_PARAMS(zp, zone range, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 17 | DEFINE_UI_PARAMS(zone, zone, DCTLUI_COMBO_BOX, 1, {low, high}, {low, high}) 18 | DEFINE_UI_PARAMS(tf, Transfer Function, DCTLUI_COMBO_BOX, 1, {ioetf_linear, ioetf_davinci_intermediate, ioetf_acescct, ioetf_arri_logc3, ioetf_arri_logc4, ioetf_redlog3g10}, {Linear, Davinci Intermediate, ACEScct, Arri LogC3, Arri LogC4, RedLog3G10}) 19 | 20 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 21 | { 22 | float3 rgb = make_float3(p_R, p_G, p_B); 23 | rgb = linearize(rgb, tf, 0); 24 | int zr = 0; 25 | if (zone == high) zr = 1; 26 | 27 | rgb = n6_hueshift(rgb, sy, sr, sm, sb, sc, sg, scu, cuh, cuw, str, chl, ze, zp, zr); 28 | rgb = linearize(rgb, tf, 1); 29 | return rgb; 30 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/n6Purity.dctl: -------------------------------------------------------------------------------- 1 | /* n6Purity - v0.0.2 2 | ------------------------- 3 | Another tool on the theme of "Vibrance". 4 | n6Purity adjusts the saturation of "mid-range" chroma values. 5 | The purity sliders adjust the saturation, and the strength sliders 6 | control how much of the chroma range to affect. 7 | 8 | --- 9 | Written by Jed Smith 10 | github.com/jedypod/open-display-transform 11 | */ 12 | 13 | DEFINE_UI_PARAMS(rp, red purity, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 14 | DEFINE_UI_PARAMS(rs, red strength, DCTLUI_SLIDER_FLOAT, 2, 0, 4, 0) 15 | DEFINE_UI_PARAMS(gp, green purity, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 16 | DEFINE_UI_PARAMS(gs, green strength, DCTLUI_SLIDER_FLOAT, 2, 0, 4, 0) 17 | DEFINE_UI_PARAMS(bp, blue purity, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 18 | DEFINE_UI_PARAMS(bs, blue strength, DCTLUI_SLIDER_FLOAT, 2, 0, 4, 0) 19 | DEFINE_UI_PARAMS(cp, cyan purity, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 20 | DEFINE_UI_PARAMS(cs, cyan strength, DCTLUI_SLIDER_FLOAT, 2, 0, 4, 0) 21 | DEFINE_UI_PARAMS(mp, magenta purity, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 22 | DEFINE_UI_PARAMS(ms, magenta strength, DCTLUI_SLIDER_FLOAT, 2, 0, 4, 0) 23 | DEFINE_UI_PARAMS(yp, yellow purity, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 24 | DEFINE_UI_PARAMS(ys, yellow strength, DCTLUI_SLIDER_FLOAT, 2, 0, 4, 0) 25 | 26 | // Safe division of float a by float b 27 | __DEVICE__ float sdivf(float a, float b) { 28 | if (_fabs(b) < 0.0001f) return 0.0f; 29 | else return a / b; 30 | } 31 | 32 | // https://www.desmos.com/calculator/8tqz4rs0wm 33 | __DEVICE__ float power_window(float x, float c, float p0, float p1, float x0, float x1) { 34 | return x > x1 ? 0.0f : x > c ? _powf(1.0f - _powf((x - c)/(x1 - c), p0), p1) : x > x0 ? _powf(1.0f - _powf((c - x)/(c - x0), p0), p1) : 0.0f; 35 | } 36 | 37 | // https://www.desmos.com/calculator/bdbstdsvvv 38 | __DEVICE__ float pivoted_power_cubic(float x, float m, float p) { 39 | m = 1.0f - _fabs(m); 40 | float a0 = p*(m - 1.0f); 41 | float b0 = (1.0f - m)*(p + 1.0f); 42 | return x <= 0.0f ? m*x : x > 1.0f ? x : x*(_powf(x, p)*(a0*x + b0) + m); 43 | } 44 | 45 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 46 | { 47 | float3 rgb = make_float3(p_R, p_G, p_B); 48 | 49 | // Calculate hue and "chroma" 50 | float mx = _fmaxf(rgb.x, _fmaxf(rgb.y, rgb.z)); 51 | float mn = _fminf(rgb.x, _fminf(rgb.y, rgb.z)); 52 | float ch = mx - mn; 53 | float h; 54 | if (ch == 0.0f) h = 0.0f; 55 | else if (mx == rgb.x) h = _fmod((rgb.y - rgb.z) / ch + 6.0f, 6.0f); 56 | else if (mx == rgb.y) h = (rgb.z - rgb.x) / ch + 2.0f; 57 | else if (mx == rgb.z) h = (rgb.x - rgb.y) / ch + 4.0f; 58 | ch = sdivf(ch, mx); 59 | 60 | // Extract hue angles 61 | float hr = power_window(_fmod(h + 1.0f, 6.0f), 1.0f, 1.5f, 1.5f, 0.0f, 2.0f); 62 | float hg = power_window(_fmod(h + 5.0f, 6.0f), 1.0f, 1.5f, 1.5f, 0.0f, 2.0f); 63 | float hb = power_window(_fmod(h + 3.0f, 6.0f), 1.0f, 1.5f, 1.5f, 0.0f, 2.0f); 64 | float hc = power_window(_fmod(h + 4.0f, 6.0f), 1.0f, 1.5f, 1.5f, 0.0f, 2.0f); 65 | float hm = power_window(_fmod(h + 2.0f, 6.0f), 1.0f, 1.5f, 1.5f, 0.0f, 2.0f); 66 | float hy = power_window(_fmod(h + 0.0f, 6.0f), 1.0f, 1.5f, 1.5f, 0.0f, 2.0f); 67 | 68 | // Cubic chroma compression curve 69 | float cr = sdivf(rp < 0.0f ? pivoted_power_cubic(ch, rp, rs) : 1.0f - pivoted_power_cubic(1.0f - ch, rp, rs), ch); 70 | float cg = sdivf(gp < 0.0f ? pivoted_power_cubic(ch, gp, gs) : 1.0f - pivoted_power_cubic(1.0f - ch, gp, gs), ch); 71 | float cb = sdivf(bp < 0.0f ? pivoted_power_cubic(ch, bp, bs) : 1.0f - pivoted_power_cubic(1.0f - ch, bp, bs), ch); 72 | float cc = sdivf(cp < 0.0f ? pivoted_power_cubic(ch, cp, cs) : 1.0f - pivoted_power_cubic(1.0f - ch, cp, cs), ch); 73 | float cm = sdivf(mp < 0.0f ? pivoted_power_cubic(ch, mp, ms) : 1.0f - pivoted_power_cubic(1.0f - ch, mp, ms), ch); 74 | float cy = sdivf(yp < 0.0f ? pivoted_power_cubic(ch, yp, ys) : 1.0f - pivoted_power_cubic(1.0f - ch, yp, ys), ch); 75 | 76 | 77 | // Combine all hue angles to single chroma compression factor 78 | float chf = (hr*cr + hg*cg + hb*cb + (1.0f - (hr + hg + hb)))*(hc*cc + hm*cm + hy*cy + (1.0f - (hc + hm + hy))); 79 | 80 | // Weighted sum of RGB 81 | float wsum = rgb.x*0.3f + rgb.y*0.6f + rgb.z*0.1f; 82 | 83 | // Lerp towards wsum by chf 84 | float3 result = wsum*(1.0f - chf) + rgb*chf; 85 | return result; 86 | } -------------------------------------------------------------------------------- /look-transforms/tools/resolve/n6Vibrance.dctl: -------------------------------------------------------------------------------- 1 | #line 2 // Fix line numbers in resolve/logs/rollinglog.txt 2 | #include "libLMT.h" 3 | 4 | DEFINE_UI_PARAMS(mgl, global, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 5 | DEFINE_UI_PARAMS(my, yellow, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 6 | DEFINE_UI_PARAMS(mr, red, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 7 | DEFINE_UI_PARAMS(mm, magenta, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 8 | DEFINE_UI_PARAMS(mb, blue, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 9 | DEFINE_UI_PARAMS(mc, cyan, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 10 | DEFINE_UI_PARAMS(mg, green, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 11 | DEFINE_UI_PARAMS(mcu, custom, DCTLUI_SLIDER_FLOAT, 0, -1, 1, 0) 12 | DEFINE_UI_PARAMS(cuh, hue, DCTLUI_SLIDER_FLOAT, 100, 0, 360, 0) 13 | DEFINE_UI_PARAMS(cuw, width, DCTLUI_SLIDER_FLOAT, 0.3, 0, 2, 0) 14 | DEFINE_UI_PARAMS(hl, hue-linear, DCTLUI_SLIDER_FLOAT, 0.5, 0, 1, 0) 15 | DEFINE_UI_PARAMS(ze, zone extract, DCTLUI_CHECK_BOX, 1) 16 | DEFINE_UI_PARAMS(zp, zone range, DCTLUI_SLIDER_FLOAT, 0, -4, 4, 0) 17 | DEFINE_UI_PARAMS(zone, zone, DCTLUI_COMBO_BOX, 0, {low, high}, {low, high}) 18 | DEFINE_UI_PARAMS(tf, Transfer Function, DCTLUI_COMBO_BOX, 1, {ioetf_linear, ioetf_davinci_intermediate, ioetf_acescct, ioetf_arri_logc3, ioetf_arri_logc4, ioetf_redlog3g10}, {Linear, Davinci Intermediate, ACEScct, Arri LogC3, Arri LogC4, RedLog3G10}) 19 | 20 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 21 | { 22 | float3 rgb = make_float3(p_R, p_G, p_B); 23 | rgb = linearize(rgb, tf, 0); 24 | int zr = 0; 25 | if (zone == high) zr = 1; 26 | 27 | rgb = n6_vibrance(rgb, mgl, my, mr, mm, mb, mc, mg, mcu, cuh, cuw, hl, ze, zp, zr); 28 | rgb = linearize(rgb, tf, 1); 29 | return rgb; 30 | } -------------------------------------------------------------------------------- /utilities/GamutConvert.dctl: -------------------------------------------------------------------------------- 1 | #line 2 2 | /* GamutConvert 3 | Applies a pre-calculated 3x3 matrix to convert from in gamut to out gamut. 4 | */ 5 | 6 | DEFINE_UI_PARAMS(ig, in gamut, DCTLUI_COMBO_BOX, 0, {i_xyz, i_ap0, i_ap1, i_p3d65, i_rec2020, i_rec709, i_awg3, i_awg4, i_rwg, i_sgamut3, i_sgamut3cine, i_vgamut, i_fgamutc, i_bmdwg, i_egamut, i_egamut2, i_davinciwg}, {XYZ, ACES 2065-1, ACEScg, P3D65, Rec.2020, Rec.709, Arri Wide Gamut 3, Arri Wide Gamut 4, Red Wide Gamut RGB, Sony SGamut3, Sony SGamut3Cine, Panasonic V-Gamut, Fujifilm F-GamutC, Blackmagic Wide Gamut, Filmlight E-Gamut, Filmlight E-Gamut2, DaVinci Wide Gamut}) 7 | DEFINE_UI_PARAMS(og, out gamut, DCTLUI_COMBO_BOX, 0, {o_xyz, o_ap0, o_ap1, o_p3d65, o_rec2020, o_rec709, o_awg3, o_awg4, o_rwg, o_sgamut3, o_sgamut3cine, o_vgamut, o_fgamutc, o_bmdwg, o_egamut, o_egamut2, o_davinciwg}, {XYZ, ACES 2065-1, ACEScg, P3D65, Rec.2020, Rec.709, Arri Wide Gamut 3, Arri Wide Gamut 4, Red Wide Gamut RGB, Sony SGamut3, SGamut3Cine, Panasonic V-Gamut, Fujifilm F-GamutC, Blackmagic Wide Gamut, Filmlight E-Gamut, Filmlight E-Gamut2, DaVinci Wide Gamut}) 8 | // DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0) 9 | 10 | 11 | // Struct for a 3x3 matrix 12 | typedef struct { 13 | float3 x, y, z; 14 | } float3x3; 15 | 16 | // Helper function to create a float3x3 17 | __DEVICE__ float3x3 make_float3x3(float3 a, float3 b, float3 c) { 18 | float3x3 d; 19 | d.x = a, d.y = b, d.z = c; 20 | return d; 21 | } 22 | 23 | // Multiply 3x3 matrix m and float3 vector v 24 | __DEVICE__ float3 vdot(float3x3 m, float3 v) { 25 | return make_float3(m.x.x*v.x + m.x.y*v.y + m.x.z*v.z, m.y.x*v.x + m.y.y*v.y + m.y.z*v.z, m.z.x*v.x + m.z.y*v.y + m.z.z*v.z); 26 | } 27 | 28 | 29 | 30 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 31 | { 32 | // Get the input RGB 33 | float3 rgb = make_float3(p_R, p_G, p_B); 34 | 35 | // If in gamut equals out gamut, do nothing 36 | if (ig == og) return rgb; 37 | 38 | 39 | float3x3 imtx; 40 | // Match in-gamut to the right matrix 41 | if (ig == i_ap0) imtx = make_float3x3(make_float3(0.93863094875f, -0.00574192055f, 0.017566898852f), make_float3(0.338093594922f, 0.727213902811f, -0.065307497733f), make_float3(0.000723121511f, 0.000818441849f, 1.0875161874f)); 42 | else if (ig == i_ap1) imtx = make_float3x3(make_float3(0.652418717672f, 0.127179925538f, 0.170857283842f), make_float3(0.268064059194f, 0.672464478993f, 0.059471461813f), make_float3(-0.00546992851f, 0.005182799977f, 1.08934487929f)); 43 | else if (ig == i_p3d65) imtx = make_float3x3(make_float3(0.486570948648f, 0.265667693169f, 0.198217285234f), make_float3(0.22897456407f, 0.691738521837f, 0.079286914094f), make_float3(-0.0f, 0.045113381859f, 1.0439443689f)); 44 | else if (ig == i_rec2020) imtx = make_float3x3(make_float3(0.636958048301f, 0.144616903586f, 0.168880975164f), make_float3(0.262700212011f, 0.677998071519f, 0.05930171647f), make_float3(0.0f, 0.028072693049f, 1.06098505771f)); 45 | else if (ig == i_rec709) imtx = make_float3x3(make_float3(0.412390799266f, 0.357584339384f, 0.180480788402f), make_float3(0.212639005872f, 0.715168678768f, 0.072192315361f), make_float3(0.019330818716f, 0.119194779795f, 0.95053215225f)); 46 | else if (ig == i_awg3) imtx = make_float3x3(make_float3(0.638007619284f, 0.214703856337f, 0.097744451431f), make_float3(0.291953779f, 0.823841041511f, -0.11579482051f), make_float3(0.002798279032f, -0.067034235689f, 1.15329370742f)); 47 | else if (ig == i_awg4) imtx = make_float3x3(make_float3(0.704858320407f, 0.12976029517f, 0.115837311474f), make_float3(0.254524176404f, 0.781477732712f, -0.036001909116f), make_float3(0.0f, 0.0f, 1.08905775076f)); 48 | else if (ig == i_rwg) imtx = make_float3x3(make_float3(0.735275245906f, 0.068609410614f, 0.146571270532f), make_float3(0.2866940995f, 0.842979134017f, -0.129673233517f), make_float3(-0.079680856878f, -0.347343216994f, 1.51608182463f)); 49 | else if (ig == i_sgamut3) imtx = make_float3x3(make_float3(0.706482713192f, 0.128801049791f, 0.115172164069f), make_float3(0.270979670813f, 0.786606411221f, -0.057586082034f), make_float3(-0.009677845386f, 0.004600037493f, 1.09413555865f)); 50 | else if (ig == i_sgamut3cine) imtx = make_float3x3(make_float3(0.599083920758f, 0.248925516115f, 0.102446490178f), make_float3(0.215075820116f, 0.885068501744f, -0.100144321859f), make_float3(-0.032065849545f, -0.027658390679f, 1.14878199098f)); 51 | else if (ig == i_vgamut) imtx = make_float3x3(make_float3(0.679644469878f, 0.15221141244f, 0.118600044733f), make_float3(0.26068555009f, 0.77489446333f, -0.03558001342f), make_float3(-0.009310198218f, -0.004612467044f, 1.10298041602f)); 52 | else if (ig == i_fgamutc) imtx = make_float3x3(make_float3(0.789274967789f, 0.02004022988f, 0.141140729383f), make_float3(0.285007008241f, 0.741945697114f, -0.026952705355f), make_float3(0.0f, 0.0f, 1.08905775076f)); 53 | else if (ig == i_bmdwg) imtx = make_float3x3(make_float3(0.606538368283f, 0.220412735329f, 0.12350482344f), make_float3(0.267992940057f, 0.832748409123f, -0.10074134918f), make_float3(-0.02944255416f, -0.086612430277f, 1.2051127352f)); 54 | else if (ig == i_egamut) imtx = make_float3x3(make_float3(0.705396850088f, 0.16404132831f, 0.081017748654f), make_float3(0.280130724091f, 0.82020664155f, -0.100337365641f), make_float3(-0.103781511569f, -0.072907257027f, 1.26574651936f)); 55 | else if (ig == i_egamut2) imtx = make_float3x3(make_float3(0.736477700184f, 0.130739651087f, 0.083238575781f), make_float3(0.275069984406f, 0.828017790216f, -0.103087774621f), make_float3(-0.124225154248f, -0.087159767391f, 1.3004426724f)); 56 | else if (ig == i_davinciwg) imtx = make_float3x3(make_float3(0.700622392094f, 0.148774815123f, 0.101058719835f), make_float3(0.274118510907f, 0.87363189594f, -0.147750406847f), make_float3(-0.098962912883f, -0.137895325076f, 1.32591598872f)); 57 | 58 | float3x3 omtx; 59 | // Match out-gamut to the right matrix 60 | if (og == o_ap0) omtx = make_float3x3(make_float3(1.06236610705f, 0.008406953654f, -0.016655789633f), make_float3(-0.493941371628f, 1.37110952521f, 0.090316586974f), make_float3(-0.000334668577f, -0.001037458272f, 0.919469647322f)); 61 | else if (og == o_ap1) omtx = make_float3x3(make_float3(1.65885430847f, -0.311856975397f, -0.243156007126f), make_float3(-0.662283287108f, 1.61219957087f, 0.015859126603f), make_float3(0.011480566457f, -0.009236324924f, 0.916686513449f)); 62 | else if (og == o_p3d65) omtx = make_float3x3(make_float3(2.49349691194f, -0.931383617919f, -0.402710784451f), make_float3(-0.829488969562f, 1.76266406032f, 0.023624685842f), make_float3(0.035845830244f, -0.076172389268f, 0.956884524008f)); 63 | else if (og == o_rec2020) omtx = make_float3x3(make_float3(1.71665118797f, -0.355670783776f, -0.253366281374f), make_float3(-0.666684351832f, 1.61648123664f, 0.015768545814f), make_float3(0.017639857445f, -0.042770613258f, 0.942103121235f)); 64 | else if (og == o_rec709) omtx = make_float3x3(make_float3(3.2409699419f, -1.53738317757f, -0.498610760293f), make_float3(-0.969243636281f, 1.87596750151f, 0.041555057407f), make_float3(0.055630079697f, -0.203976958889f, 1.05697151424f)); 65 | else if (og == o_awg3) omtx = make_float3x3(make_float3(1.78906555097f, -0.482533863771f, -0.200075792936f), make_float3(-0.639848659902f, 1.39639995686f, 0.194432291778f), make_float3(-0.041531545853f, 0.082335373554f, 0.878868480293f)); 66 | else if (og == o_awg4) omtx = make_float3x3(make_float3(1.50921547224f, -0.250597345204f, -0.168811475294f), make_float3(-0.491545451661f, 1.36124554593f, 0.097282942014f), make_float3(0.0f, 0.0f, 0.918224951158f)); 67 | else if (og == o_rwg) omtx = make_float3x3(make_float3(1.41280648037f, -0.17752320099f, -0.151770732029f), make_float3(-0.48620327686f, 1.2906964268f, 0.15740061473f), make_float3(-0.037139010853f, 0.286375999779f, 0.687679778862f)); 68 | else if (og == o_sgamut3) omtx = make_float3x3(make_float3(1.50739989906f, -0.245822137385f, -0.171611680816f), make_float3(-0.518151727083f, 1.3553912409f, 0.125878668162f), make_float3(0.015511698158f, -0.007872771427f, 0.911916365575f)); 69 | else if (og == o_sgamut3cine) omtx = make_float3x3(make_float3(1.84677896929f, -0.525986122969f, -0.210545211388f), make_float3(-0.444153262903f, 1.25944290281f, 0.149399972888f), make_float3(0.040855421196f, 0.01564088931f, 0.868207248699f)); 70 | else if (og == o_vgamut) omtx = make_float3x3(make_float3(1.58901177387f, -0.31320448446f, -0.180964851528f), make_float3(-0.534052910449f, 1.39601143335f, 0.102457671017f), make_float3(0.011179448843f, 0.003194128241f, 0.905535356281f)); 71 | else if (og == o_fgamutc) omtx = make_float3x3(make_float3(1.27946475834f, -0.034558820113f, -0.166672559633f), make_float3(-0.491486673948f, 1.36108277177f, 0.0973811081f), make_float3(0.0f, 0.0f, 0.918224951158f)); 72 | else if (og == o_bmdwg) omtx = make_float3x3(make_float3(1.86635773561f, -0.518390508775f, -0.234606716542f), make_float3(-0.600329854462f, 1.37811995056f, 0.176728109838f), make_float3(0.002451481064f, 0.086381609339f, 0.836767715319f)); 73 | else if (og == o_egamut) omtx = make_float3x3(make_float3(1.52505277041f, -0.315913510935f, -0.122658264605f), make_float3(-0.509152559971f, 1.33332740873f, 0.138284365141f), make_float3(0.095715345314f, 0.050897443852f, 0.787955770285f)); 74 | else if (og == o_egamut2) omtx = make_float3x3(make_float3(1.42776075557f, -0.237033581941f, -0.110177895085f), make_float3(-0.461174449232f, 1.2944289444f, 0.13212985645f), make_float3(0.105477884785f, 0.064114008399f, 0.767299906963f)); 75 | else if (og == o_davinciwg) omtx = make_float3x3(make_float3(1.51667204202f, -0.281478047879f, -0.146963633237f), make_float3(-0.464917101233f, 1.25142377568f, 0.174884608865f), make_float3(0.064849047067f, 0.109139343711f, 0.76141462155f)); 76 | 77 | 78 | 79 | if (ig != i_xyz) { 80 | // Apply in gamut to XYZ conversion 81 | rgb = vdot(imtx, rgb); 82 | } 83 | if (og != o_xyz) { 84 | // Apply XYZ to out gamut conversion 85 | rgb = vdot(omtx, rgb); 86 | } 87 | 88 | return rgb; 89 | } 90 | -------------------------------------------------------------------------------- /utilities/GamutConvertFull.dctl: -------------------------------------------------------------------------------- 1 | #line 2 2 | /* GamutConvert 3 | Calculate a 3x3 matrix to convert between two gamuts. 4 | 5 | Includes a Chromatic Adaptation Transform (CAT) if the whitepoint of gamut A does not match gamut B. 6 | Does not rely on predefined matrices. Calculates the gamut conversion matrix at machine precision, 7 | using the RGBW chromaticity coordinates of the gamut. 8 | 9 | */ 10 | 11 | DEFINE_UI_PARAMS(ig, in gamut, DCTLUI_COMBO_BOX, 0, {i_xyz, i_xyz_d65, i_ap0, i_ap1, i_p3d65, i_rec2020, i_rec709, i_awg3, i_awg4, i_rwg, i_sgamut3, i_sgamut3cine, i_vgamut, i_bmdwg, i_egamut, i_egamut2, i_davinciwg}, {XYZ, XYZ D65, ACES 2065-1, ACEScg, P3D65, Rec.2020, Rec.709, Arri Wide Gamut 3, Arri Wide Gamut 4, Red Wide Gamut RGB, Sony SGamut3, Sony SGamut3Cine, Panasonic V-Gamut, Blackmagic Wide Gamut, Filmlight E-Gamut, Filmlight E-Gamut2, DaVinci Wide Gamut}) 12 | DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0); 13 | DEFINE_UI_PARAMS(og, out gamut, DCTLUI_COMBO_BOX, 0, {o_xyz, o_xyz_d65, o_ap0, o_ap1, o_p3d65, o_rec2020, o_rec709, o_awg3, o_awg4, o_rwg, o_sgamut3, o_sgamut3cine, o_vgamut, o_bmdwg, o_egamut, o_egamut2, o_davinciwg}, {XYZ, XYZ D65, ACES 2065-1, ACEScg, P3D65, Rec.2020, Rec.709, Arri Wide Gamut 3, Arri Wide Gamut 4, Red Wide Gamut RGB, Sony SGamut3, SGamut3Cine, Panasonic V-Gamut, Blackmagic Wide Gamut, Filmlight E-Gamut, Filmlight E-Gamut2, DaVinci Wide Gamut}) 14 | 15 | // Struct for a 3x3 matrix 16 | typedef struct { 17 | float3 x, y, z; 18 | } float3x3; 19 | 20 | // chromaticity coordinates for primaries and whitepoint of an rgb gamut 21 | typedef struct { 22 | float2 r, g, b, w; 23 | } chr; 24 | 25 | // Helper function to create a float3x3 26 | __DEVICE__ float3x3 make_float3x3(float3 a, float3 b, float3 c) { 27 | float3x3 d; 28 | d.x = a, d.y = b, d.z = c; 29 | return d; 30 | } 31 | 32 | // Helper function to create a chr chromaticities object 33 | __DEVICE__ chr make_chr(float2 r, float2 g, float2 b, float2 w) { 34 | chr c; 35 | c.r = r, c.g = g, c.b = b, c.w = w; 36 | return c; 37 | } 38 | 39 | // Return 3x3 matrix filled with zeros 40 | __DEVICE__ float3x3 zeros() { 41 | return make_float3x3(make_float3(0.0f, 0.0f, 0.0f), make_float3(0.0f, 0.0f, 0.0f), make_float3(0.0f, 0.0f, 0.0f)); 42 | } 43 | 44 | // set diagonal row of 3x3 matrix m to float3 v 45 | __DEVICE__ float3x3 diag(float3x3 m, float3 v) { 46 | m.x.x = v.x; 47 | m.y.y = v.y; 48 | m.z.z = v.z; 49 | return m; 50 | } 51 | 52 | // Return identity 3x3 matrix 53 | __DEVICE__ float3x3 identity() { 54 | return diag(zeros(), make_float3(1.0f, 1.0f, 1.0f)); 55 | } 56 | 57 | // Multiply 3x3 matrix m and float3 vector v 58 | __DEVICE__ float3 vdot(float3x3 m, float3 v) { 59 | return make_float3(m.x.x*v.x + m.x.y*v.y + m.x.z*v.z, m.y.x*v.x + m.y.y*v.y + m.y.z*v.z, m.z.x*v.x + m.z.y*v.y + m.z.z*v.z); 60 | } 61 | 62 | // transpose 3x3 matrix m by swapping rows and columns 63 | __DEVICE__ float3x3 transpose(float3x3 a) { 64 | float3x3 m = zeros(); 65 | m.x = make_float3(a.x.x, a.y.x, a.z.x); 66 | m.y = make_float3(a.x.y, a.y.y, a.z.y); 67 | m.z = make_float3(a.x.z, a.y.z, a.z.z); 68 | return m; 69 | } 70 | 71 | // Multiply 3x3 matrix a with 3x3 matrix b 72 | __DEVICE__ float3x3 matmul(float3x3 a, float3x3 b) { 73 | float3x3 c = zeros(); 74 | c.x.x = a.x.x*b.x.x + a.x.y*b.y.x + a.x.z*b.z.x; 75 | c.x.y = a.x.x*b.x.y + a.x.y*b.y.y + a.x.z*b.z.y; 76 | c.x.z = a.x.x*b.x.z + a.x.y*b.y.z + a.x.z*b.z.z; 77 | c.y.x = a.y.x*b.x.x + a.y.y*b.y.x + a.y.z*b.z.x; 78 | c.y.y = a.y.x*b.x.y + a.y.y*b.y.y + a.y.z*b.z.y; 79 | c.y.z = a.y.x*b.x.z + a.y.y*b.y.z + a.y.z*b.z.z; 80 | c.z.x = a.z.x*b.x.x + a.z.y*b.y.x + a.z.z*b.z.x; 81 | c.z.y = a.z.x*b.x.y + a.z.y*b.y.y + a.z.z*b.z.y; 82 | c.z.z = a.z.x*b.x.z + a.z.y*b.y.z + a.z.z*b.z.z; 83 | return c; 84 | } 85 | 86 | // Calculate inverse of 3x3 matrix: https://stackoverflow.com/questions/983999/simple-3x3-matrix-inverse-code-c 87 | __DEVICE__ float3x3 inv(float3x3 m) { 88 | float3x3 c = identity(); 89 | float d = m.x.x*(m.y.y*m.z.z - m.z.y*m.y.z) - 90 | m.x.y*(m.y.x*m.z.z - m.y.z*m.z.x) + 91 | m.x.z*(m.y.x*m.z.y - m.y.y*m.z.x); 92 | if (d == 0.0f) return c; // No Inverse 93 | float id = 1.0f/d; 94 | c.x.x = id*(m.y.y*m.z.z - m.z.y*m.y.z); 95 | c.x.y = id*(m.x.z*m.z.y - m.x.y*m.z.z); 96 | c.x.z = id*(m.x.y*m.y.z - m.x.z*m.y.y); 97 | c.y.x = id*(m.y.z*m.z.x - m.y.x*m.z.z); 98 | c.y.y = id*(m.x.x*m.z.z - m.x.z*m.z.x); 99 | c.y.z = id*(m.y.x*m.x.z - m.x.x*m.y.z); 100 | c.z.x = id*(m.y.x*m.z.y - m.z.x*m.y.y); 101 | c.z.y = id*(m.z.x*m.x.y - m.x.x*m.z.y); 102 | c.z.z = id*(m.x.x*m.y.y - m.y.x*m.x.y); 103 | return c; 104 | } 105 | 106 | /* Calculate the Normalized Primaries Matrix for the specified chromaticities 107 | Adapted from RP 177:1993 108 | SMPTE Recommended Practice - Derivation of Basic Television Color Equations 109 | http://doi.org/10.5594/S9781614821915 110 | https://mega.nz/file/frAnCIYK#CNRW5Q99G-w_QZtv5ey_0AkRWNrQVh7bM70kVwv42NQ 111 | */ 112 | __DEVICE__ float3x3 npm(chr p) { 113 | float3x3 P = zeros(); 114 | P.x = make_float3(p.r.x, p.r.y, 1.0f - p.r.x - p.r.y); 115 | P.y = make_float3(p.g.x, p.g.y, 1.0f - p.g.x - p.g.y); 116 | P.z = make_float3(p.b.x, p.b.y, 1.0f - p.b.x - p.b.y); 117 | P = transpose(P); 118 | float3 W = make_float3(p.w.x, p.w.y, 1.0f - p.w.x - p.w.y); 119 | W = make_float3(W.x / W.y, 1.0f, W.z / W.y); 120 | float3 C = vdot(inv(P), W); 121 | float3x3 M = diag(zeros(), C); 122 | return matmul(P, M); 123 | } 124 | 125 | // Convert xy chromaticity coordinate to XYZ tristimulus with Y=1.0 126 | __DEVICE__ float3 xy_to_XYZ(float2 xy) { 127 | return make_float3(xy.x/xy.y, 1.0f, (1.0f - xy.x - xy.y)/xy.y); 128 | } 129 | 130 | /* Calculate a von Kries style chromatic adaptation matrix 131 | given xy chromaticities for source white (ws) and destination white (wd) 132 | Source: Mark D. Fairchild - 2013 - Color Appearance Models Third Edition p. 181-186 133 | Source: Bruce Lindbloom - Chromatic Adaptation - http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html 134 | */ 135 | __DEVICE__ float3x3 cat(float2 ws, float2 wd, int method) { 136 | if (ws.x == wd.x && ws.y == wd.y) return identity(); // Whitepoints are equal, nothing to do 137 | float3x3 mcat = identity(); 138 | if (method == 0) { // CAT02 139 | mcat = make_float3x3(make_float3(0.7328f, 0.4296f, -0.1624f), make_float3(-0.7036f, 1.6975f, 0.0061f), make_float3(0.003f, 0.0136f, 0.9834f)); 140 | } else if (method == 1) { // Bradford 141 | mcat = make_float3x3(make_float3(0.8951f, 0.2664f, -0.1614f), make_float3(-0.7502f, 1.7135f, 0.0367f), make_float3(0.0389f, -0.0685f, 1.0296f)); 142 | } 143 | 144 | float3 sXYZ = xy_to_XYZ(ws); // source normalized XYZ 145 | float3 dXYZ = xy_to_XYZ(wd); // destination normalized XYZ 146 | 147 | float3 sm = vdot(mcat, sXYZ); // source mult 148 | float3 dm = vdot(mcat, dXYZ); // destination mult 149 | 150 | float3x3 smat = diag(zeros(), make_float3(dm.x/sm.x, dm.y/sm.y, dm.z/sm.z)); 151 | float3x3 nmat = matmul(inv(mcat), smat); 152 | return matmul(nmat, mcat); 153 | } 154 | 155 | // Calculate 3x3 matrix to convert from source rgb gamut to destination rgb gamut 156 | // Include CAT if whitepoints are different. 157 | __DEVICE__ float3x3 rgb_to_rgb(chr ch0, chr ch1) { 158 | float3x3 rgb0_to_xyz = npm(ch0); 159 | float3x3 rgb1_to_xyz = npm(ch1); 160 | float3x3 xyz_to_cat = cat(ch0.w, ch1.w, 0); 161 | float3x3 rgb0_to_cat = matmul(xyz_to_cat, rgb0_to_xyz); 162 | float3x3 rgb0_to_rgb1 = matmul(inv(rgb1_to_xyz), rgb0_to_cat); 163 | return rgb0_to_rgb1; 164 | } 165 | 166 | // Calculate 3x3 matrix to convert from source rgb gamut ch to XYZ with CAT 167 | __DEVICE__ float3x3 rgb_to_XYZ_cat(chr ch, float2 wd) { 168 | float3x3 rgb_to_xyz = npm(ch); 169 | if (ch.w.x == wd.x && ch.w.y == wd.y) return rgb_to_xyz; // No CAT needed. 170 | float3x3 cat_mtx = cat(ch.w, wd, 0); 171 | return matmul(cat_mtx, rgb_to_xyz); 172 | } 173 | 174 | 175 | 176 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 177 | { 178 | // Chromaticity coordinates for various whitepoints 179 | float2 wp_ACES = make_float2(0.32168f, 0.33767f); 180 | float2 wp_D60 = make_float2(0.321626f, 0.337737f); 181 | float2 wp_D65 = make_float2(0.3127f, 0.329f); 182 | float2 wp_DCI = make_float2(0.314f, 0.351f); 183 | float2 wp_E = make_float2(0.333333f, 0.333333f); 184 | 185 | // Chromaticity coordinates for various gamuts 186 | chr ap0 = make_chr(make_float2(0.7347f, 0.2653f), make_float2(0.0f, 1.0f), make_float2(0.0001f, -0.077f), wp_ACES); 187 | chr ap1 = make_chr(make_float2(0.713f, 0.293f), make_float2(0.165f, 0.83f), make_float2(0.128f, 0.044f), wp_ACES); 188 | chr bdgamut = make_chr(make_float2(0.8150f, 0.3167f), make_float2(0.2036f, 0.8500f), make_float2(0.0517f, -0.1026f), wp_D65); 189 | chr egamut = make_chr(make_float2(0.8f, 0.3177f), make_float2(0.18f, 0.9f), make_float2(0.065f, -0.0805f), wp_D65); 190 | chr egamut2 = make_chr(make_float2(0.83f, 0.31f), make_float2(0.15f, 0.95f), make_float2(0.065f, -0.0805f), wp_D65); 191 | chr davinciwg = make_chr(make_float2(0.8f, 0.313f), make_float2(0.1682f, 0.9877f), make_float2(0.079f, -0.1155f), wp_D65); 192 | chr rec709 = make_chr(make_float2(0.64f, 0.33f), make_float2(0.3f, 0.6f), make_float2(0.15f, 0.06f), wp_D65); 193 | chr rec2020 = make_chr(make_float2(0.708f, 0.292f), make_float2(0.17f, 0.797f), make_float2(0.131f, 0.046f), wp_D65); 194 | chr p3d60 = make_chr(make_float2(0.68f, 0.32f), make_float2(0.265f, 0.69f), make_float2(0.15f, 0.06f), wp_D60); 195 | chr p3d65 = make_chr(make_float2(0.68f, 0.32f), make_float2(0.265f, 0.69f), make_float2(0.15f, 0.06f), wp_D65); 196 | chr p3dci = make_chr(make_float2(0.68f, 0.32f), make_float2(0.265f, 0.69f), make_float2(0.15f, 0.06f), wp_DCI); 197 | chr awg3 = make_chr(make_float2(0.684f, 0.313f), make_float2(0.221f, 0.848f), make_float2(0.0861f, -0.102f), wp_D65); 198 | chr awg4 = make_chr(make_float2(0.7347f, 0.2653f), make_float2(0.1424f, 0.8576f), make_float2(0.0991f, -0.0308f), wp_D65); 199 | chr rwg = make_chr(make_float2(0.780308f, 0.304253f), make_float2(0.121595f, 1.493994f), make_float2(0.095612f, -0.084589f), wp_D65); 200 | chr protune = make_chr(make_float2(0.69848046f, 0.19302645f), make_float2(0.32955538f, 1.02459662f), make_float2(0.10844263f, -0.03467857f), wp_D65); 201 | chr cgamut = make_chr(make_float2(0.74f, 0.27f), make_float2(0.17f, 1.14f), make_float2(0.08f, -0.1f), wp_D65); 202 | chr sgamut3 = make_chr(make_float2(0.73f, 0.28f), make_float2(0.14f, 0.855f), make_float2(0.1f, -0.05f), wp_D65); 203 | chr sgamut3cine = make_chr(make_float2(0.766f, 0.275f), make_float2(0.225f, 0.8f), make_float2(0.089f, -0.087f), wp_D65); 204 | chr vgamut = make_chr(make_float2(0.73f, 0.28f), make_float2(0.165f, 0.84f), make_float2(0.1f, -0.03f), wp_D65); 205 | chr dgamut = make_chr(make_float2(0.71f, 0.31f), make_float2(0.21f, 0.88f), make_float2(0.09f, -0.08f), wp_D65); 206 | chr bmdwg = make_chr(make_float2(0.7177215f, 0.3171181f), make_float2(0.228041f, 0.861569f), make_float2(0.1005841f, -0.0820452f), wp_D65); 207 | chr adobergb = make_chr(make_float2(0.64f, 0.33f), make_float2(0.21f, 0.71f), make_float2(0.15f, 0.06f), wp_D65); 208 | 209 | 210 | chr ichr; // input chromaticities 211 | // Match in-gamut to the right chromaticities 212 | if (ig == i_ap0) ichr = ap0; 213 | else if (ig == i_ap1) ichr = ap1; 214 | else if (ig == i_p3d65) ichr = p3d65; 215 | else if (ig == i_rec2020) ichr = rec2020; 216 | else if (ig == i_rec709) ichr = rec709; 217 | else if (ig == i_awg3) ichr = awg3; 218 | else if (ig == i_awg4) ichr = awg4; 219 | else if (ig == i_rwg) ichr = rwg; 220 | else if (ig == i_sgamut3) ichr = sgamut3; 221 | else if (ig == i_sgamut3cine) ichr = sgamut3cine; 222 | else if (ig == i_vgamut) ichr = vgamut; 223 | else if (ig == i_bmdwg) ichr = bmdwg; 224 | else if (ig == i_egamut) ichr = egamut; 225 | else if (ig == i_egamut2) ichr = egamut2; 226 | else if (ig == i_davinciwg) ichr = davinciwg; 227 | 228 | chr ochr; // output chromaticities 229 | // Match out-gamut to the right chromaticities 230 | if (og == o_ap0) ochr = ap0; 231 | else if (og == o_ap1) ochr = ap1; 232 | else if (og == o_p3d65) ochr = p3d65; 233 | else if (og == o_rec2020) ochr = rec2020; 234 | else if (og == o_rec709) ochr = rec709; 235 | else if (og == o_awg3) ochr = awg3; 236 | else if (og == o_awg4) ochr = awg4; 237 | else if (og == o_rwg) ochr = rwg; 238 | else if (og == o_sgamut3) ochr = sgamut3; 239 | else if (og == o_sgamut3cine) ochr = sgamut3cine; 240 | else if (og == o_vgamut) ochr = vgamut; 241 | else if (og == o_bmdwg) ochr = bmdwg; 242 | else if (og == o_egamut) ochr = egamut; 243 | else if (og == o_egamut2) ochr = egamut2; 244 | else if (og == o_davinciwg) ochr = davinciwg; 245 | 246 | 247 | // Get the input RGB and calculate the matrix. 248 | float3 rgb = make_float3(p_R, p_G, p_B); 249 | 250 | float3x3 mtx = identity(); 251 | 252 | mtx = npm(ichr); 253 | 254 | // If in gamut equals out gamut, do nothing 255 | if (ig == og) return rgb; 256 | 257 | // If in-gamut is XYZ: mtx is inverse of out-gamut to XYZ. (No chromatic adaptation transform!) 258 | // If out-gamut is XYZ: mtx is in-gamut to XYZ. 259 | // Otherwise, calculate a full rgb to rgb conversion matrix. 260 | if (ig == i_xyz) mtx = inv(npm(ochr)); 261 | else if (ig == i_xyz_d65) mtx = inv(rgb_to_XYZ_cat(ochr, wp_D65)); 262 | else if (og == o_xyz) mtx = npm(ichr); 263 | else if (og == o_xyz_d65) mtx = rgb_to_XYZ_cat(ichr, wp_D65); 264 | else mtx = rgb_to_rgb(ichr, ochr); 265 | 266 | if (invert == 1) mtx = inv(mtx); 267 | 268 | // Apply the matrix to RGB with a vector dot-product. 269 | rgb = vdot(mtx, rgb); 270 | 271 | return rgb; 272 | } 273 | -------------------------------------------------------------------------------- /utilities/LogConvert.dctl: -------------------------------------------------------------------------------- 1 | /* LogConvert 2 | ------------------ 3 | Converts from linear to log and back. 4 | 5 | */ 6 | 7 | DEFINE_UI_PARAMS(curve, curve, DCTLUI_COMBO_BOX, 0, {acescc, acescct, arri_logc3, arri_logc4, blackmagic_filmgen5, canon_clog2, canon_clog3, dji_dlog, fujifilm_flog, fujifilm_flog2, gopro_protune, leica_llog, nikon_nlog, panasonic_vlog, red_log3g10, sony_slog2, sony_slog3, davinci_intermediate, filmlight_tlog, kodak_cineon}, {ACEScc, ACEScct, Arri LogC3, Arri LogC4, Blackmagic Film Gen5, Canon CLog2, Canon CLog3, DJI DLog, Fujifilm FLog, Fujifilm FLog2, GoPro ProTune, Leica LLog, Nikon NLog, Panasonic VLog, Red Log3G10, Sony SLog2, Sony SLog3, DaVinci Intermediate, Filmlight TLog, Kodak Cineon}) 8 | DEFINE_UI_PARAMS(invert, invert, DCTLUI_CHECK_BOX, 0); 9 | 10 | 11 | __DEVICE__ float oetf_acescc(float x, int inv) { 12 | /* ACEScc Log 13 | S-2014-003 : ACEScc - A Quasi-Logarithmic Encoding of ACES Data for use within Color Grading Systems 14 | http://j.mp/S-2014-003 15 | */ 16 | const float A = 9.72f; 17 | const float B = 17.52f; 18 | 19 | if (inv == 1) { 20 | return x <= (A - 15.0f)/B ? (_powf(2.0f, x*B - A) - _powf(2.0f, -16.0f))*2.0f : x < (_log2f(65504.0f) + A)/B ? _powf(2.0f, x*B - A) : x; 21 | } else { 22 | return x <= 0.0f ? (_log2f(-16.0f) + A)/B : x < _powf(2.0f, -15.0f) ? (_log2f(_powf(2.0f, -16.0f) + x/2.0f) + A)/B : (_log2f(x) + A)/B; 23 | } 24 | } 25 | 26 | 27 | __DEVICE__ float oetf_acescct(float x, int inv) { 28 | /* ACEScct Log 29 | S-2016-001 : ACEScct - A Quasi-Logarithmic Encoding of ACES Data for use within Color Grading Systems 30 | http://j.mp/S-2016-001_ 31 | */ 32 | const float cut1 = 0.0078125f; 33 | const float cut2 = 0.155251141552511f; 34 | const float A = 10.5402377416545f; 35 | const float B = 0.0729055341958355f; 36 | const float C = 9.72f; 37 | const float D = 17.52f; 38 | 39 | if (inv == 1) { 40 | return x <= cut2 ? (x - B)/A : _exp2f(x*D - C); 41 | } else { 42 | return x <= cut1 ? A*x + B : (_log2f(x) + C)/D; 43 | } 44 | } 45 | 46 | __DEVICE__ float oetf_arri_logc3(float x, int inv) { 47 | /* Arri Alexa LogC3 48 | Formerly known as Alexa V3LogC EI800 49 | https://www.arri.com/resource/blob/31918/66f56e6abb6e5b6553929edf9aa7483e/2017-03-alexa-logc-curve-in-vfx-data.pdf 50 | */ 51 | 52 | const float cut = 0.010591f; 53 | const float a = 5.555556f; 54 | const float b = 0.052272f; 55 | const float c = 0.247190f; 56 | const float d = 0.385537f; 57 | const float e = 5.367655f; 58 | const float f = 0.092809f; 59 | 60 | if (inv == 1) { 61 | return x < e*cut + f ? (x - f)/e : (_exp10f((x - d)/c) - b)/a; 62 | } else { 63 | return x < cut ? e*x + f : c*_log10f(a*x + b) + d; 64 | } 65 | } 66 | 67 | __DEVICE__ float oetf_arri_logc4(float x, int inv) { 68 | /* Arri Alexa LogC4 69 | https://www.arri.com/resource/blob/278790/bea879ac0d041a925bed27a096ab3ec2/2022-05-arri-logc4-specification-data.pdf 70 | */ 71 | 72 | const float a = (_exp2f(18.0f) - 16.0f)/117.45f; 73 | const float b = (1023.0f - 95.0f)/1023.0f; 74 | const float c = 95.0f/1023.0f; 75 | const float s = (7.0f*_logf(2.0f)*_exp2f(7.0f - 14.0f*c/b))/(a*b); 76 | const float t = (_exp2f(14.0f*(-c/b) + 6.0f) - 64.0f)/a; 77 | 78 | if (inv == 1) { 79 | return x < t ? x*s + t : (_exp2f(14.0f*(x - c)/b + 6.0f) - 64.0f)/a; 80 | } else { 81 | return x < t ? (x - t)/s : (_log2f(a*x + 64.0f) - 6.0f)/14.0f*b + c; 82 | } 83 | } 84 | 85 | __DEVICE__ float oetf_blackmagic_filmgen5(float x, int inv) { 86 | /* Blackmagic Film Generation 5 87 | Specified in the Blackmagic Generation 5 Color Science whitepaper included in the Blackmagic Raw SDK available here 88 | https://www.blackmagicdesign.com/support/download/1bad3dc74c2c4a908ce5c9ce8b9f74f8/Linux 89 | At this path in the installer: 90 | /usr/lib64/blackmagic/BlackmagicRAWSDK/Documents/Blackmagic Generation 5 Color Science Technical Reference.pdf 91 | */ 92 | 93 | const float A = 0.08692876065491224f; 94 | const float B = 0.005494072432257808f; 95 | const float C = 0.5300133392291939f; 96 | const float D = 8.283605932402494f; 97 | const float E = 0.09246575342465753f; 98 | const float LIN_CUT = 0.005f; 99 | const float LOG_CUT = D * LIN_CUT + E; 100 | 101 | if (inv == 1) { 102 | return x < LOG_CUT ? (x - E)/D : _expf((x - C)/A) - B; 103 | } else { 104 | return x < LIN_CUT ? D*x + E : A*_logf(x + B) + C; 105 | } 106 | } 107 | 108 | __DEVICE__ float oetf_canon_clog2(float x, int inv) { 109 | /* Canon CLog2 110 | CLog2 is intended for grading workflows, whereas CLog3 is intended for a more "direct to display" workflow. 111 | 112 | Canon log transfer functions are all described in this whitepaper: 113 | https://downloads.canon.com/nw/learn/white-papers/cinema-eos/white-paper-canon-log-gamma-curves.pdf 114 | 115 | The log transfer functions described above match the 1D LUTs available in the "Canon lookup table Version 201911" 116 | download available here 117 | https://www.usa.canon.com/internet/portal/us/home/support/details/cameras/cinema-eos/cinema-eos-c500-mark-ii?tab=drivers_downloads 118 | 119 | However in the CTL ACES IDT provided in the "Input Transform Version 202007 for EOS C500 Mark II" file 120 | at the above url, they add the /=0.9 on the scene-linear values. This function matches the IDT. 121 | */ 122 | const float c0 = 0.092864125f; 123 | const float c1 = 0.24136077f; 124 | const float c2 = 87.099375f; 125 | 126 | if (inv == 1) { 127 | x = x < c0 ? -(_exp10f((c0 - x)/c1) - 1.0f)/c2 : (_exp10f((x - c0)/c1) - 1.0f)/c2; 128 | return x*0.9f; 129 | } else { 130 | x /= 0.9f; 131 | return x < 0.0f ? -c1*_log10f(1.0f - c2*x) + c0 : c1*_log10f(c2*x + 1.0f) + c0; 132 | } 133 | } 134 | 135 | __DEVICE__ float oetf_canon_clog3(float x, int inv) { 136 | /* Canon CLog3 137 | Warning: CLog3 is intended for a more "direct to display" workflow 138 | */ 139 | const float sp0 = 0.014f; 140 | const float sp1 = 0.09746547f; 141 | const float sp2 = 0.15277891f; 142 | const float c0 = 0.36726845f; 143 | const float c1 = 14.98325f; 144 | const float c2 = 0.12783901f; 145 | const float c3 = 1.9754798f; 146 | const float c4 = 0.12512219f; 147 | const float c5 = 0.12240537f; 148 | 149 | if (inv == 1) { 150 | x = x < sp1 ? -(_exp10f((c2 - x)/c0) - 1.0f)/c1 : x <= sp2 ? (x - c4)/c3 : (_exp10f((x - c5)/c0) - 1.0f)/c1; 151 | return x*0.9f; 152 | } else { 153 | x /= 0.9f; 154 | return x < -sp0 ? -c0*_log10f(1.0f - c1*x) + c2 : x <= sp0 ? c3*x + c4 : c0*_log10f(c1*x + 1.0f) + c5; 155 | } 156 | } 157 | 158 | __DEVICE__ float oetf_dji_dlog(float x, int inv) { 159 | /* DJI D-Log 160 | https://dl.djicdn.com/downloads/zenmuse+x7/20171010/D-Log_D-Gamut_Whitepaper.pdf 161 | */ 162 | 163 | if (inv == 1) { 164 | return x <= 0.14f ? (x - 0.0929f)/6.025f : (_exp10f((3.89616f*x - 2.27752f)) - 0.0108f)/0.9892f; 165 | } else { 166 | return x <= 0.0078f ? 6.025f*x + 0.0929f : (_log10f(x*0.9892f + 0.0108f))*0.256663f + 0.584555f; 167 | } 168 | } 169 | 170 | __DEVICE__ float oetf_fujifilm_flog(float x, int inv) { 171 | /* Fujifilm F-Log 172 | https://dl.fujifilm-x.com/support/lut/F-Log_DataSheet_E_Ver.1.0.pdf 173 | */ 174 | const float a = 0.555556f; 175 | const float b = 0.009468f; 176 | const float c = 0.344676f; 177 | const float d = 0.790453f; 178 | const float e = 8.735631f; 179 | const float f = 0.092864f; 180 | const float cut1 = 0.00089f; 181 | const float cut2 = 0.1005377752f; 182 | 183 | if (inv == 1) { 184 | return x < cut2 ? (x-f)/e : (_exp10f(((x - d)/c))/a - b/a); 185 | } else { 186 | return x < cut1 ? e*x+f : c*_log10f(a*x + b) + d; 187 | } 188 | } 189 | 190 | __DEVICE__ float oetf_fujifilm_flog2(float x, int inv) { 191 | /* Fujifilm F-Log2 192 | https://dl.fujifilm-x.com/support/lut/F-Log2_DataSheet_E_Ver.1.0.pdf 193 | */ 194 | const float a = 5.555556f; 195 | const float b = 0.064829f; 196 | const float c = 0.245281f; 197 | const float d = 0.384316f; 198 | const float e = 8.799461f; 199 | const float f = 0.092864f; 200 | const float cut1 = 0.000889f; 201 | const float cut2 = 0.100686685370811f; 202 | 203 | if (inv == 1) { 204 | return x < cut2 ? (x-f)/e : (_exp10f(((x - d)/c))/a - b/a); 205 | } else { 206 | return x < cut1 ? e*x+f : c*_log10f(a*x + b) + d; 207 | } 208 | } 209 | 210 | __DEVICE__ float oetf_gopro_protune(float x, int inv) { 211 | /* GoPro Protune Flat log curve 212 | Unable to find whitepaper on this but it is described in this file from the original HPD opencolorio ACES config: 213 | https://github.com/hpd/OpenColorIO-Configs/blob/master/aces_1.0.3/python/aces_ocio/colorspaces/gopro.py 214 | */ 215 | if (inv == 1) { 216 | return (_powf(113.0f, x) - 1.0f)/112.0f; 217 | } else { 218 | return _logf(x*112.0f + 1.0f)/_logf(113.0f); 219 | } 220 | } 221 | 222 | __DEVICE__ float oetf_leica_llog(float x, int inv) { 223 | /* Leica L-Log 224 | https://leica-camera.com/sites/default/files/pm-65977-210914__L-Log_Reference_Manual_EN.pdf 225 | */ 226 | const float a = 8.0f; 227 | const float b = 0.09f; 228 | const float c = 0.27f; 229 | const float d = 1.3f; 230 | const float e = 0.0115f; 231 | const float f = 0.6f; 232 | const float c0 = 0.006f; 233 | const float c1 = 0.138f; 234 | 235 | if (inv == 1) { 236 | return x < c1 ? (x - b)/a : (_exp10f((x - f)/c) - e)/d; 237 | } else { 238 | return x < c0 ? a*x + b : c*_log10f(d*x + e) + f; 239 | } 240 | } 241 | 242 | __DEVICE__ float oetf_nikon_nlog(float x, int inv) { 243 | /* Nikon N-Log 244 | http://download.nikonimglib.com/archive3/hDCmK00m9JDI03RPruD74xpoU905/N-Log_Specification_(En)01.pdf 245 | */ 246 | const float a = 619.0f/1023.0f; 247 | const float b = 150.0f/1023.0f; 248 | const float c = 650.0f/1023.0f; 249 | const float d = 0.0075f; 250 | const float c0 = 452.0f/1023.0f; 251 | const float c1 = 0.328f; 252 | 253 | if (inv == 1) { 254 | return x > c0 ? _expf((x - a)/b) : _powf(x/c, 3.0f) - d; 255 | } else { 256 | return x > c1 ? b*_logf(x) + a : c*_powf(x + d, 1.0f/3.0f); 257 | } 258 | } 259 | 260 | __DEVICE__ float oetf_panasonic_vlog(float x, int inv) { 261 | /* Panasonic V-Log 262 | https://pro-av.panasonic.net/en/cinema_camera_varicam_eva/support/pdf/VARICAM_V-Log_V-Gamut.pdf 263 | */ 264 | const float cut1 = 0.01f; 265 | const float cut2 = 0.181f; 266 | const float b = 0.00873f; 267 | const float c = 0.241514f; 268 | const float d = 0.598206f; 269 | 270 | if (inv == 1) { 271 | return x < cut2 ? (x - 0.125f)/5.6f : _exp10f((x - d)/c) - b; 272 | } else { 273 | return x < cut1 ? 5.6f*x + 0.125f : c*_log10f(x + b) + d; 274 | } 275 | } 276 | 277 | __DEVICE__ float oetf_red_log3g10(float x, int inv) { 278 | /* Red Log3G10 279 | https://docs.red.com/955-0187/PDF/915-0187%20Rev-C%20%20%20RED%20OPS,%20White%20Paper%20on%20REDWideGamutRGB%20and%20Log3G10.pdf 280 | */ 281 | const float a = 0.224282f; 282 | const float b = 155.975327f; 283 | const float c = 0.01f; 284 | const float g = 15.1927f; 285 | 286 | if (inv == 1) { 287 | return x < 0.0f ? (x/g) - c : (_exp10f(x/a) - 1.0f)/b - c; 288 | } else { 289 | return x < -c ? (x + c)*g : a*_log10f((x + c)*b + 1.0f); 290 | } 291 | } 292 | 293 | __DEVICE__ float oetf_sony_slog2(float x, int inv) { 294 | /* Sony S-Log2 295 | from the pdf originally retrieved from : 296 | https://pro.sony/ue_US/?sonyref=pro.sony.com/bbsccms/assets/files/micro/dmpc/training/S-Log2_Technical_PaperV1_0.pdf 297 | Link is down, here is a mirror: 298 | https://mega.nz/file/e6hDxC5b#YaRzePfGFFPkx_hRtmqw2gTT0NIPuzlJycwCP38H720 299 | */ 300 | const float c0 = 0.432699f; 301 | const float c1 = 155.0f; 302 | const float c2 = 219.0f; 303 | const float c3 = 0.037584f; 304 | const float c4 = 0.616596f; 305 | const float c5 = 0.03f; 306 | const float c6 = 3.53881278538813f; 307 | const float c7 = 0.030001222851889303f; 308 | 309 | if (inv == 1) { 310 | x = (x - 64.0f/1023.0f)/(876.0f/1023.0f); 311 | x = x < c7 ? (x - c7)/c6 : c2*(_exp10f((x - c4 - c5)/c0) - c3)/c1; 312 | return x*0.9f; 313 | } else { 314 | x /= 0.9f; 315 | x = x < 0.0f ? x*c6 + c7 : (c0*_log10f(c1*x/c2 + c3) + c4) + c5; 316 | return x*(876.0f/1023.0f) + 64.0f/1023.0f; 317 | } 318 | } 319 | 320 | __DEVICE__ float oetf_sony_slog3(float x, int inv) { 321 | /* Sony S-Log3 322 | https://pro.sony/s3/cms-static-content/uploadfile/06/1237494271406.pdf 323 | */ 324 | const float a = 0.01125f; 325 | const float b = 420.0f; 326 | const float c = 261.5f; 327 | const float d = 171.2102946929f; 328 | const float e = 95.0f; 329 | const float f = 0.18f; 330 | const float o = 0.01f; 331 | 332 | if (inv == 1) { 333 | return x < d/1023.0f ? (x*1023.0f - e)*a/(d-e) : (_exp10f(((x*1023.0f - b)/c))*(f + o) - o); 334 | } else { 335 | return x < a ? (x*(d - e)/a + e)/1023.0f : (b + _log10f((x + o)/(f + o))*c)/1023.0f; 336 | } 337 | } 338 | 339 | __DEVICE__ float oetf_davinci_intermediate(float x, int inv) { 340 | /* DaVinci Intermediate Log 341 | https://documents.blackmagicdesign.com/InformationNotes/DaVinci_Resolve_17_Wide_Gamut_Intermediate.pdf 342 | */ 343 | 344 | const float A = 0.0075f; 345 | const float B = 7.0f; 346 | const float C = 0.07329248f; 347 | const float M = 10.44426855f; 348 | const float LIN_CUT = 0.00262409f; 349 | const float LOG_CUT = 0.02740668f; 350 | 351 | if (inv == 1) { 352 | return x <= LOG_CUT ? x/M : _exp2f(x/C - B) - A; 353 | } else { 354 | return x <= LIN_CUT ? x*M : (_log2f(x + A) + B)*C; 355 | } 356 | } 357 | 358 | __DEVICE__ float oetf_filmlight_tlog(float x, int inv) { 359 | /* Filmlight T-Log 360 | Specified in the flspace file included with the Baselight software 361 | /etc/colourspaces/FilmLight_TLog_EGamut.flspace 362 | */ 363 | 364 | const float o = 0.075f; 365 | const float A = 0.5520126568606655f; 366 | const float B = 0.09232902596577353f; 367 | const float C = 0.0057048244042473785f; 368 | const float G = 16.184376489665897f; 369 | 370 | if (inv == 1) { 371 | return x < o ? (x-o)/G : _expf((x - A)/B) - C; 372 | } else { 373 | return x < 0.0f ? G*x + o : _logf(x + C)*B + A; 374 | } 375 | } 376 | 377 | __DEVICE__ float oetf_kodak_cineon(float x, int inv) { 378 | /* Kodak Cineon Log 379 | https://github.com/imageworks/OpenColorIO-Configs/blob/master/nuke-default/make.py 380 | */ 381 | const float a = 685.0f; 382 | const float b = 300.0f; 383 | const float c = 95.0f; 384 | const float off = _exp10f((c - a)/b); 385 | 386 | if (inv == 1) { 387 | return (_exp10f(((1023.0f*x - a)/b)) - off)/(1.0f - off); 388 | } else { 389 | return (a + b*_log10f(x*(1.0f - off) + off))/1023.0f; 390 | } 391 | } 392 | 393 | // __DEVICE__ float oetf_(float x, int inv) { 394 | // /* 395 | // 396 | // */ 397 | // if (inv == 1) { 398 | // return x; 399 | // } else { 400 | // return x; 401 | // } 402 | // } 403 | 404 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) 405 | { 406 | 407 | float3 rgb = make_float3(p_R, p_G, p_B); 408 | 409 | if (curve == acescc) { 410 | rgb.x = oetf_acescc(rgb.x, invert); 411 | rgb.y = oetf_acescc(rgb.y, invert); 412 | rgb.z = oetf_acescc(rgb.z, invert); 413 | } else if (curve == acescct) { 414 | rgb.x = oetf_acescct(rgb.x, invert); 415 | rgb.y = oetf_acescct(rgb.y, invert); 416 | rgb.z = oetf_acescct(rgb.z, invert); 417 | } else if (curve == arri_logc3) { 418 | rgb.x = oetf_arri_logc3(rgb.x, invert); 419 | rgb.y = oetf_arri_logc3(rgb.y, invert); 420 | rgb.z = oetf_arri_logc3(rgb.z, invert); 421 | } else if (curve == arri_logc4) { 422 | rgb.x = oetf_arri_logc4(rgb.x, invert); 423 | rgb.y = oetf_arri_logc4(rgb.y, invert); 424 | rgb.z = oetf_arri_logc4(rgb.z, invert); 425 | } else if (curve == blackmagic_filmgen5) { 426 | rgb.x = oetf_blackmagic_filmgen5(rgb.x, invert); 427 | rgb.y = oetf_blackmagic_filmgen5(rgb.y, invert); 428 | rgb.z = oetf_blackmagic_filmgen5(rgb.z, invert); 429 | } else if (curve == canon_clog2) { 430 | rgb.x = oetf_canon_clog2(rgb.x, invert); 431 | rgb.y = oetf_canon_clog2(rgb.y, invert); 432 | rgb.z = oetf_canon_clog2(rgb.z, invert); 433 | } else if (curve == canon_clog3) { 434 | rgb.x = oetf_canon_clog3(rgb.x, invert); 435 | rgb.y = oetf_canon_clog3(rgb.y, invert); 436 | rgb.z = oetf_canon_clog3(rgb.z, invert); 437 | } else if (curve == dji_dlog) { 438 | rgb.x = oetf_dji_dlog(rgb.x, invert); 439 | rgb.y = oetf_dji_dlog(rgb.y, invert); 440 | rgb.z = oetf_dji_dlog(rgb.z, invert); 441 | } else if (curve == fujifilm_flog) { 442 | rgb.x = oetf_fujifilm_flog(rgb.x, invert); 443 | rgb.y = oetf_fujifilm_flog(rgb.y, invert); 444 | rgb.z = oetf_fujifilm_flog(rgb.z, invert); 445 | } else if (curve == fujifilm_flog2) { 446 | rgb.x = oetf_fujifilm_flog2(rgb.x, invert); 447 | rgb.y = oetf_fujifilm_flog2(rgb.y, invert); 448 | rgb.z = oetf_fujifilm_flog2(rgb.z, invert); 449 | } else if (curve == gopro_protune) { 450 | rgb.x = oetf_gopro_protune(rgb.x, invert); 451 | rgb.y = oetf_gopro_protune(rgb.y, invert); 452 | rgb.z = oetf_gopro_protune(rgb.z, invert); 453 | } else if (curve == leica_llog) { 454 | rgb.x = oetf_leica_llog(rgb.x, invert); 455 | rgb.y = oetf_leica_llog(rgb.y, invert); 456 | rgb.z = oetf_leica_llog(rgb.z, invert); 457 | } else if (curve == nikon_nlog) { 458 | rgb.x = oetf_nikon_nlog(rgb.x, invert); 459 | rgb.y = oetf_nikon_nlog(rgb.y, invert); 460 | rgb.z = oetf_nikon_nlog(rgb.z, invert); 461 | } else if (curve == panasonic_vlog) { 462 | rgb.x = oetf_panasonic_vlog(rgb.x, invert); 463 | rgb.y = oetf_panasonic_vlog(rgb.y, invert); 464 | rgb.z = oetf_panasonic_vlog(rgb.z, invert); 465 | } else if (curve == red_log3g10) { 466 | rgb.x = oetf_red_log3g10(rgb.x, invert); 467 | rgb.y = oetf_red_log3g10(rgb.y, invert); 468 | rgb.z = oetf_red_log3g10(rgb.z, invert); 469 | } else if (curve == sony_slog2) { 470 | rgb.x = oetf_sony_slog2(rgb.x, invert); 471 | rgb.y = oetf_sony_slog2(rgb.y, invert); 472 | rgb.z = oetf_sony_slog2(rgb.z, invert); 473 | } else if (curve == sony_slog3) { 474 | rgb.x = oetf_sony_slog3(rgb.x, invert); 475 | rgb.y = oetf_sony_slog3(rgb.y, invert); 476 | rgb.z = oetf_sony_slog3(rgb.z, invert); 477 | } else if (curve == davinci_intermediate) { 478 | rgb.x = oetf_davinci_intermediate(rgb.x, invert); 479 | rgb.y = oetf_davinci_intermediate(rgb.y, invert); 480 | rgb.z = oetf_davinci_intermediate(rgb.z, invert); 481 | } else if (curve == filmlight_tlog) { 482 | rgb.x = oetf_filmlight_tlog(rgb.x, invert); 483 | rgb.y = oetf_filmlight_tlog(rgb.y, invert); 484 | rgb.z = oetf_filmlight_tlog(rgb.z, invert); 485 | } else if (curve == kodak_cineon) { 486 | rgb.x = oetf_kodak_cineon(rgb.x, invert); 487 | rgb.y = oetf_kodak_cineon(rgb.y, invert); 488 | rgb.z = oetf_kodak_cineon(rgb.z, invert); 489 | } 490 | 491 | return rgb; 492 | 493 | } -------------------------------------------------------------------------------- /utilities/README.md: -------------------------------------------------------------------------------- 1 | # Utilities 2 | Here are a couple of utility DCTLs for doing basic operations in Resolve. 3 | 4 | ## GamutConvert 5 | Converts from one gamut to another. Calculates a 3x3 Matrix at machine precision, does not rely on pre-defined matrices. 6 | 7 | ## LogConvert 8 | Convert from to or from a log encoding. Implemented directly in code (no luts), so good precision. Includes links to the original source whitepapers where possible. --------------------------------------------------------------------------------