|
| 1 | +# SPDX-License-Identifier: BSD-3-Clause |
| 2 | +# Copyright Contributors to the OpenColorIO Project. |
| 3 | +""" |
| 4 | +*Blackmagic* CLF Transforms Generation |
| 5 | +======================================= |
| 6 | +
|
| 7 | +Defines procedures for generating Blackmagic *Common LUT Format* (CLF) |
| 8 | +transforms for the OpenColorIO project. |
| 9 | +""" |
| 10 | + |
| 11 | +import PyOpenColorIO as ocio |
| 12 | +from pathlib import Path |
| 13 | +import math |
| 14 | + |
| 15 | +from opencolorio_config_aces.clf import ( |
| 16 | + create_conversion_matrix, |
| 17 | + generate_clf, |
| 18 | +) |
| 19 | + |
| 20 | +__author__ = "OpenColorIO Contributors" |
| 21 | +__copyright__ = "Copyright Contributors to the OpenColorIO Project." |
| 22 | +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" |
| 23 | +__maintainer__ = "OpenColorIO Contributors" |
| 24 | +__email__ = "ocio-dev@lists.aswf.io" |
| 25 | +__status__ = "Production" |
| 26 | + |
| 27 | +__all__ = [ |
| 28 | + "main", |
| 29 | +] |
| 30 | + |
| 31 | +DEST_DIR = Path(__file__).parent.resolve() / "input" |
| 32 | + |
| 33 | +TF_ID_PREFIX = "urn:aswf:ocio:transformId:1.0:" |
| 34 | +TF_ID_SUFFIX = ":1.0" |
| 35 | + |
| 36 | +CLF_SUFFIX = ".clf" |
| 37 | + |
| 38 | + |
| 39 | +def _generate_clf_bmdfilm(): |
| 40 | + """Make the CLF file for BMDFilm_WideGamut_Gen5 plus matrix/curve CLFs.""" |
| 41 | + |
| 42 | + # Based on the document "Blackmagic Generation 5 Color Technical Reference.pdf" |
| 43 | + # dated May 2021. The resulting CLF was reviewed by Blackmagic. |
| 44 | + |
| 45 | + cut = 0.005 |
| 46 | + a = 0.08692876065491224 |
| 47 | + b = 0.005494072432257808 |
| 48 | + c = 0.5300133392291939 |
| 49 | + # d = 8.283605932402494 |
| 50 | + # e = 0.09246575342465753 |
| 51 | + |
| 52 | + BASE = math.e |
| 53 | + LIN_SB = cut |
| 54 | + LOG_SLP = a |
| 55 | + LOG_OFF = c |
| 56 | + LIN_SLP = 1.0 |
| 57 | + LIN_OFF = b |
| 58 | + |
| 59 | + # It is not necessary to set the linear_slope value in the LogCameraTransform |
| 60 | + # since the values automatically calculated by OCIO match the published values |
| 61 | + # to within double precision. This may be verified using the following formulas: |
| 62 | + # LINEAR_SLOPE = |
| 63 | + # LOG_SLP * LIN_SLP / ( (LIN_SLP * LIN_SB + LIN_OFF) * math.log(BASE) ) |
| 64 | + # LOG_SB = LOG_SLP * math.log(LIN_SLP * LIN_SB + LIN_OFF) + LOG_OFF |
| 65 | + # LINEAR_OFFSET = LOG_SB - LINEAR_SLOPE * LIN_SB |
| 66 | + # print(LINEAR_SLOPE, LINEAR_OFFSET) |
| 67 | + # This prints 8.283605932402494 0.09246575342465779, which is sufficiently close |
| 68 | + # to the specified d and e above. |
| 69 | + |
| 70 | + lct = ocio.LogCameraTransform( |
| 71 | + base=BASE, |
| 72 | + linSideBreak=[LIN_SB] * 3, |
| 73 | + logSideSlope=[LOG_SLP] * 3, |
| 74 | + logSideOffset=[LOG_OFF] * 3, |
| 75 | + linSideSlope=[LIN_SLP] * 3, |
| 76 | + linSideOffset=[LIN_OFF] * 3, |
| 77 | + direction=ocio.TRANSFORM_DIR_INVERSE, |
| 78 | + ) |
| 79 | + |
| 80 | + mtx = create_conversion_matrix( |
| 81 | + "Blackmagic Wide Gamut", "ACES2065-1", "CAT02" |
| 82 | + ) |
| 83 | + |
| 84 | + # Taking the color space name and IDT transform ID from: |
| 85 | + # https://github.com/ampas/aces-dev/pull/126/files |
| 86 | + aces_transform_id = ( |
| 87 | + "urn:ampas:aces:transformId:v1.5:" |
| 88 | + "IDT.BlackmagicDesign.BMDFilm_WideGamut_Gen5.a1.v1" |
| 89 | + ) |
| 90 | + |
| 91 | + # Generate full transform. |
| 92 | + |
| 93 | + generate_clf( |
| 94 | + ocio.GroupTransform( |
| 95 | + transforms=[ |
| 96 | + lct, |
| 97 | + mtx, |
| 98 | + ] |
| 99 | + ), |
| 100 | + TF_ID_PREFIX |
| 101 | + + "BlackmagicDesign:Input:BMDFilm_WideGamut_Gen5_to_ACES2065-1" |
| 102 | + + TF_ID_SUFFIX, |
| 103 | + "Blackmagic Film Wide Gamut (Gen 5) to ACES2065-1", |
| 104 | + DEST_DIR / ("BMDFilm-WideGamut-Gen5_to_ACES2065-1" + CLF_SUFFIX), |
| 105 | + "Blackmagic Film Wide Gamut (Gen 5)", |
| 106 | + "ACES2065-1", |
| 107 | + aces_transform_id, |
| 108 | + ) |
| 109 | + |
| 110 | + # Generate transform for primaries only. |
| 111 | + |
| 112 | + generate_clf( |
| 113 | + ocio.GroupTransform([mtx]), |
| 114 | + TF_ID_PREFIX |
| 115 | + + "BlackmagicDesign:Input:Linear_BMD_WideGamut_Gen5_to_ACES2065-1" |
| 116 | + + TF_ID_SUFFIX, |
| 117 | + "Linear Blackmagic Wide Gamut (Gen 5) to ACES2065-1", |
| 118 | + DEST_DIR / ("Linear-BMD-WideGamut-Gen5_to_ACES2065-1" + CLF_SUFFIX), |
| 119 | + "Linear Blackmagic Wide Gamut (Gen 5)", |
| 120 | + "ACES2065-1", |
| 121 | + None, |
| 122 | + ) |
| 123 | + |
| 124 | + # Generate named transform for log curve only. |
| 125 | + |
| 126 | + generate_clf( |
| 127 | + ocio.GroupTransform([lct]), |
| 128 | + TF_ID_PREFIX |
| 129 | + + "BlackmagicDesign:Input:BMDFilm_Gen5_Log_to_Linear" |
| 130 | + + TF_ID_SUFFIX, |
| 131 | + "Blackmagic Film (Gen 5) Log to Linear Curve", |
| 132 | + DEST_DIR / ("BMDFilm-WideGamut-Gen5-Curve" + CLF_SUFFIX), |
| 133 | + "Blackmagic Film (Gen 5) Log", |
| 134 | + "Blackmagic Film (Gen 5) Linear", |
| 135 | + None, |
| 136 | + ) |
| 137 | + |
| 138 | + |
| 139 | +def _generate_clf_davinci(): |
| 140 | + """Make the CLF file for DaVinci Intermediate Wide Gamut plus matrix/curve CLFs.""" |
| 141 | + |
| 142 | + # Based on the document "DaVinci_Resolve_17_Wide_Gamut_Intermediate.pdf" |
| 143 | + # dated 2021-07-31. The resulting CLF was reviewed by Blackmagic. |
| 144 | + |
| 145 | + cut = 0.00262409 |
| 146 | + a = 0.0075 |
| 147 | + b = 7.0 |
| 148 | + c = 0.07329248 |
| 149 | + m = 10.44426855 |
| 150 | + |
| 151 | + BASE = 2.0 |
| 152 | + LIN_SB = cut |
| 153 | + LOG_SLP = c |
| 154 | + LOG_OFF = c * b |
| 155 | + LIN_SLP = 1.0 |
| 156 | + LIN_OFF = a |
| 157 | + |
| 158 | + # The linear slope that would be calculated by OCIO based on continuity of the |
| 159 | + # derivatives is 10.444266836 vs. the published value of 10.44426855. Based on |
| 160 | + # input from Blackmagic, it is preferable to set the linear slope value explicitly. |
| 161 | + LINEAR_SLOPE = m |
| 162 | + |
| 163 | + lct = ocio.LogCameraTransform( |
| 164 | + base=BASE, |
| 165 | + linSideBreak=[LIN_SB] * 3, |
| 166 | + logSideSlope=[LOG_SLP] * 3, |
| 167 | + logSideOffset=[LOG_OFF] * 3, |
| 168 | + linSideSlope=[LIN_SLP] * 3, |
| 169 | + linSideOffset=[LIN_OFF] * 3, |
| 170 | + linearSlope=[LINEAR_SLOPE] * 3, |
| 171 | + direction=ocio.TRANSFORM_DIR_INVERSE, |
| 172 | + ) |
| 173 | + |
| 174 | + mtx = create_conversion_matrix("DaVinci Wide Gamut", "ACES2065-1", "CAT02") |
| 175 | + |
| 176 | + # This transform is not yet part of aces-dev, but an ID will be needed for AMF. |
| 177 | + # Proposing the following ID: |
| 178 | + aces_transform_id = ( |
| 179 | + "urn:ampas:aces:transformId:v1.5:" |
| 180 | + "ACEScsc.Academy.DaVinci_Intermediate_WideGamut_to_ACES.a1.v1" |
| 181 | + ) |
| 182 | + |
| 183 | + # Generate full transform. |
| 184 | + |
| 185 | + generate_clf( |
| 186 | + ocio.GroupTransform( |
| 187 | + transforms=[ |
| 188 | + lct, |
| 189 | + mtx, |
| 190 | + ] |
| 191 | + ), |
| 192 | + TF_ID_PREFIX |
| 193 | + + "BlackmagicDesign:Input:DaVinci_Intermediate_WideGamut_to_ACES2065-1" |
| 194 | + + TF_ID_SUFFIX, |
| 195 | + "DaVinci Intermediate Wide Gamut to ACES2065-1", |
| 196 | + DEST_DIR |
| 197 | + / ("DaVinci-Intermediate-WideGamut_to_ACES2065-1" + CLF_SUFFIX), |
| 198 | + "DaVinci Intermediate Wide Gamut", |
| 199 | + "ACES2065-1", |
| 200 | + aces_transform_id, |
| 201 | + ) |
| 202 | + |
| 203 | + # Generate transform for primaries only. |
| 204 | + |
| 205 | + generate_clf( |
| 206 | + ocio.GroupTransform([mtx]), |
| 207 | + TF_ID_PREFIX |
| 208 | + + "BlackmagicDesign:Input:Linear_DaVinci_WideGamut_to_ACES2065-1" |
| 209 | + + TF_ID_SUFFIX, |
| 210 | + "Linear DaVinci Wide Gamut to ACES2065-1", |
| 211 | + DEST_DIR / ("Linear-DaVinci-WideGamut_to_ACES2065-1" + CLF_SUFFIX), |
| 212 | + "Linear DaVinci Wide Gamut", |
| 213 | + "ACES2065-1", |
| 214 | + None, |
| 215 | + ) |
| 216 | + |
| 217 | + # Generate named transform for log curve only. |
| 218 | + |
| 219 | + generate_clf( |
| 220 | + ocio.GroupTransform([lct]), |
| 221 | + TF_ID_PREFIX |
| 222 | + + "BlackmagicDesign:Input:DaVinci_Intermediate_Log_to_Linear" |
| 223 | + + TF_ID_SUFFIX, |
| 224 | + "DaVinci Intermediate Log to Linear Curve", |
| 225 | + DEST_DIR / ("DaVinci-Intermediate-Curve" + CLF_SUFFIX), |
| 226 | + "DaVinci Intermediate Log", |
| 227 | + "DaVinci Intermediate Linear", |
| 228 | + None, |
| 229 | + ) |
| 230 | + |
| 231 | + |
| 232 | +def main(): |
| 233 | + """Make all the Blackmagic CLFs.""" |
| 234 | + |
| 235 | + if not DEST_DIR.exists(): |
| 236 | + DEST_DIR.mkdir() |
| 237 | + |
| 238 | + _generate_clf_bmdfilm() |
| 239 | + _generate_clf_davinci() |
| 240 | + |
| 241 | + return 0 |
| 242 | + |
| 243 | + |
| 244 | +if __name__ == "__main__": |
| 245 | + import sys |
| 246 | + |
| 247 | + sys.exit(main()) |
0 commit comments