diff --git a/dev/obs/obs_codegen/__init__.py b/dev/obs/obs_codegen/__init__.py deleted file mode 100644 index e574996..0000000 --- a/dev/obs/obs_codegen/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import c diff --git a/dev/obs/obs_codegen/__main__.py b/dev/obs/obs_codegen/__main__.py deleted file mode 100644 index 1c5933e..0000000 --- a/dev/obs/obs_codegen/__main__.py +++ /dev/null @@ -1,199 +0,0 @@ -import logging -import colour -import argparse - -from obs_codegen.entitities import Whitepoint -from obs_codegen.entitities import Cat -from obs_codegen.entitities import AssemblyColorspace -from obs_codegen.entitities import ColorspaceGamut -from obs_codegen.entitities import TransferFunction -from obs_codegen.hlsl.generator import HlslGenerator -from obs_codegen.lua.generator import LuaGenerator - -logger = logging.getLogger(__name__) - - -def generate(language: str): - - illuminant1931: dict = colour.CCS_ILLUMINANTS["CIE 1931 2 Degree Standard Observer"] - - transfer_function_power_2_2 = TransferFunction("Power 2.2") - transfer_function_sRGB_EOTF = TransferFunction("sRGB EOTF") - transfer_function_BT709 = TransferFunction("BT.709") - transfer_function_DCIP3 = TransferFunction("DCI-P3") - transfer_function_Display_P3 = TransferFunction("Display P3") - transfer_function_Adobe_RGB_1998 = TransferFunction("Adobe RGB 1998") - transfer_function_BT2020 = TransferFunction("BT.2020") - - transfer_function_list = [ - transfer_function_power_2_2, - transfer_function_sRGB_EOTF, - transfer_function_BT709, - transfer_function_DCIP3, - transfer_function_Display_P3, - transfer_function_Adobe_RGB_1998, - transfer_function_BT2020, - ] - - # fmt: off - colorspace_gamut_sRGB = ColorspaceGamut.fromColourColorspaceName("sRGB") - colorspace_gamut_DCIP3 = ColorspaceGamut.fromColourColorspaceName("DCI-P3") - colorspace_gamut_Display_P3 = ColorspaceGamut.fromColourColorspaceName("Display P3") - colorspace_gamut_Adobe_RGB_1998 = ColorspaceGamut.fromColourColorspaceName("Adobe RGB (1998)") - colorspace_gamut_ITUR_BT_2020 = ColorspaceGamut.fromColourColorspaceName("ITU-R BT.2020") - colorspace_gamut_list = [ - colorspace_gamut_sRGB, - colorspace_gamut_DCIP3, - colorspace_gamut_Display_P3, - colorspace_gamut_Adobe_RGB_1998, - colorspace_gamut_ITUR_BT_2020, - ] - # fmt: on - - whitepoint_D60 = Whitepoint("D60", illuminant1931["D60"]) - whitepoint_D65 = Whitepoint("D65", illuminant1931["D65"]) - whitepoint_DCIP3 = Whitepoint("DCI-P3", illuminant1931["DCI-P3"]) - whitepoint_list = [whitepoint_D60, whitepoint_D65, whitepoint_DCIP3] - - assembly_colorspace_Passthrough = AssemblyColorspace( - "Passthrough", - None, - None, - None, - ) - assembly_colorspace_sRGB_Display_EOTF = AssemblyColorspace( - "sRGB Display (EOTF)", - colorspace_gamut_sRGB, - whitepoint_D65, - transfer_function_sRGB_EOTF, - ) - assembly_colorspace_sRGB_Display_2_2 = AssemblyColorspace( - "sRGB Display (2.2)", - colorspace_gamut_sRGB, - whitepoint_D65, - transfer_function_power_2_2, - ) - assembly_colorspace_sRGB_Linear = AssemblyColorspace( - "sRGB Linear", - colorspace_gamut_sRGB, - whitepoint_D65, - None, - ) - assembly_colorspace_BT_709_Display_2_4 = AssemblyColorspace( - "BT.709 Display (2.4)", - colorspace_gamut_sRGB, - whitepoint_D65, - transfer_function_BT709, - ) - assembly_colorspace_DCIP3_Display_2_6 = AssemblyColorspace( - "DCI-P3 Display (2.6)", - colorspace_gamut_DCIP3, - whitepoint_DCIP3, - transfer_function_DCIP3, - ) - assembly_colorspace_DCIP3_D65_Display_2_6 = AssemblyColorspace( - "DCI-P3 D65 Display (2.6)", - colorspace_gamut_DCIP3, - whitepoint_D65, - transfer_function_DCIP3, - ) - assembly_colorspace_DCIP3_D60_Display_2_6 = AssemblyColorspace( - "DCI-P3 D60 Display (2.6)", - colorspace_gamut_DCIP3, - whitepoint_D60, - transfer_function_DCIP3, - ) - assembly_colorspace_Apple_Display_P3 = AssemblyColorspace( - "Apple Display P3", - colorspace_gamut_Display_P3, - whitepoint_DCIP3, - transfer_function_Display_P3, - ) - assembly_colorspace_Adobe_RGB_1998_Display = AssemblyColorspace( - "Adobe RGB 1998 Display", - colorspace_gamut_Adobe_RGB_1998, - whitepoint_D65, - transfer_function_Adobe_RGB_1998, - ) - assembly_colorspace_BT_2020_Display_OETF = AssemblyColorspace( - "BT.2020 Display (OETF)", - colorspace_gamut_ITUR_BT_2020, - whitepoint_D65, - transfer_function_BT2020, - ) - assembly_colorspace_BT_2020_Linear = AssemblyColorspace( - "BT.2020 Linear", - colorspace_gamut_ITUR_BT_2020, - whitepoint_D65, - None, - ) - assembly_colorspace_DCIP3_Linear = AssemblyColorspace( - "DCI-P3 Linear", - colorspace_gamut_DCIP3, - whitepoint_DCIP3, - None, - ) - assembly_colorspace_list = [ - assembly_colorspace_Passthrough, - assembly_colorspace_sRGB_Display_EOTF, - assembly_colorspace_sRGB_Display_2_2, - assembly_colorspace_sRGB_Linear, - assembly_colorspace_BT_709_Display_2_4, - assembly_colorspace_DCIP3_Display_2_6, - assembly_colorspace_DCIP3_D65_Display_2_6, - assembly_colorspace_DCIP3_D60_Display_2_6, - assembly_colorspace_Apple_Display_P3, - assembly_colorspace_Adobe_RGB_1998_Display, - assembly_colorspace_BT_2020_Display_OETF, - assembly_colorspace_BT_2020_Linear, - assembly_colorspace_DCIP3_Linear, - ] - - generator_kwargs = { - "colorspaces_gamut": colorspace_gamut_list, - "whitepoints": whitepoint_list, - "cats": [ - Cat("XYZ Scaling"), - Cat("Bradford"), - Cat("CAT02"), - Cat("Von Kries"), - ], - "colorspaces_assemblies": assembly_colorspace_list, - "transfer_functions": transfer_function_list, - } - - if language == "hlsl": - - generator_hlsl = HlslGenerator(**generator_kwargs) - print(generator_hlsl.generateCode()) - - elif language == "lua": - - generator_lua = LuaGenerator(**generator_kwargs) - print(generator_lua.generateCode()) - - else: - raise ValueError(f"Unsupported {language=}") - - return - - -def cli(): - - parser = argparse.ArgumentParser( - description="OBS code generator. Just print in console." - ) - parser.add_argument( - "language", - choices=["hlsl", "lua"], - help="For which language shoudl teh code be generated", - ) - args = parser.parse_args() - language: str = args.language.lower() - - generate(language=language) - - -if __name__ == "__main__": - - cli() diff --git a/dev/obs/obs_codegen/hlsl/__init__.py b/dev/obs/obs_codegen/hlsl/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/dev/obs/obs_codegen/lua/__init__.py b/dev/obs/obs_codegen/lua/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/obs/README.md b/obs/README.md index 7e9a586..dd73351 100644 --- a/obs/README.md +++ b/obs/README.md @@ -2,26 +2,31 @@ Implementation of AgX for [OBS](https://obsproject.com/) as a script. -![screenshot of OBS interface while in the Filters section](doc/img/obs-main.png) +This is mainly intended to be applied on live camera feeds as this would not have +many benefits applied on desktop capture. -This is mainly intended to be applied on live camera feeds as this would have not much benefit -to apply this on desktop captures. +![screenshot of OBS interface while in the Filters section](doc/img/obs-main.png) -![screenshot of obs interface while camera is pointing at various colored objects like legos](doc/img/obs-c922-default.jpg) -![screenshot of obs interface while camera is pointing at various colored objects like legos](doc/img/obs-c922-agx.jpg) -> bottom image has the AgX filter applied in OBS, top is default rendering -- standard C922 webcam +| default rendering | with AgX filter | +|-----------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------| +| ![screenshot of obs interface while camera is pointing at various colored objects like legos](doc/img/obs-c922-default.jpg) | ![screenshot of obs interface while camera is pointing at various colored objects like legos](doc/img/obs-c922-agx.jpg) | +> video device is a "standard" Logitech C922 webcam # Requirements -- This has been developed on OBS 28.1.2 for Windows but should work for lower version -and other operating systems. +- This has been developed on OBS `28.1.2` for Windows but should work for lower +versions, and other operating systems. - Nothing more than the content of this directory. # Installation -Put the **whole** content of the [obs-script](obs-script) directory anywhere you want. +[Download](https://github.com/MrLixm/AgXc/archive/refs/heads/main.zip) this whole +GitHub repository. + +Put the **whole** content of the [obs/obs-script](obs-script) directory +anywhere you want on your system (you DON'T need the `src/` or the `doc/` directory). 1. Open OBS 2. In the top menu > Tools > Scripts @@ -39,21 +44,22 @@ All done ! You can now configure it. ![screenshot of OBS interface while in the Filters section](doc/img/obs-filter-options.png) -> **Note** Reminder that AgX being a display transform it should be placed at the -> very end of the image processing chain. (so at the bottom in OBS) +> ![NOTE] +> Reminder that AgX being a display transform it should be placed at +> **the very end** of the image processing chain (= at the bottom in OBS). The camera/video-source and your lighting setup will affect how much you need -to tweak the paramaters. There is no setup that work for all cases (but once -configured for your camera/usual lighting, you will not need to touch it anymore) +to tweak the parameters. There is no setup that work for all cases, but once +configured for your camera/usual lighting, you should not need to touch it anymore. -## Recommended +## Recommended Options I recommend to always start by : -- boosting the Grading Exposure by +1.0 stop. +- boosting the `Grading Exposure` by +1.0 stop. - boosting `Highligh Gain` by 2.0 -## Available +## Available Options ### Input Colorspace @@ -65,20 +71,20 @@ Passthrough means no decoding is applied. Target colorspace encoding. Must correspond to your monitor calibration. -> **Note** You can request adding new colorspace by opening an issue ! +> ![NOTE] +> You can request adding new colorspace by opening an issue on GitHub ! ### DRT Pick the DRT to use. Technically here we could include other DRT than AgX. But for now only None and AgX are available. -None means you can use all the options like grading, input colorspace, ... but -you will get a look similar to the usual broken imagery workflow. +`None` will not apply AgX but still allow you to use the grading options. ### Pre-Grading/... -Adjust imagery look in a Linear space, before AgX is applied. +Adjust imagery look in a linear space, before AgX is applied. ### Grading/Exposure @@ -108,7 +114,7 @@ See above. Grading modifications applied after AgX on display encoded data. This will introduce skews, clipping and other artefacts. -Recommended to change small values if used. +Not recommended to use or with very small values. ### Debug/Use OCIO Log Transform @@ -120,6 +126,7 @@ Does not create any change visually. Not originally included in the first AgX version but should be in the future. Restore chroma and avoid having to use Punchy saturation. +Might bring back some hue skews so better left off. ### Debug/CAT Method diff --git a/obs/doc/DEV.md b/obs/doc/DEV.md index 1b8eae4..eb2480f 100644 --- a/obs/doc/DEV.md +++ b/obs/doc/DEV.md @@ -4,16 +4,14 @@ - `AgX.lua` : direct interface with OBS used for building the GUI - `AgX.hlsl` : GPU shader with the actual AgX code. -- `colorspace.hlsl` : side-module imported in `AgX.hlsl` +- `colorspace.hlsl` : side-library imported in `AgX.hlsl` + - this is actually the public interface of the `colorscience/` "package". +- `colorscience/` library of hlsl modules for color manipulation. some of the modules +are code-generated and not intended to be edited directly. Directly editable modules are : + - `math.hlsl` + - `cctf.hlsl` -An important point is that part of the code in `colorspace.hlsl` is "procedurally" -generated from python code. - -To keep scalability on such a pontentatilly big dataset and reduce human mistakes, -a good part of the code is generated in python. - -This can be found in [{root}/dev/obs/obs_codegen](../../dev/obs/obs_codegen) -package. More details below. +The "procedurally" generated code can be found in the [../src/](../src) directory. # Add a new colorspace. @@ -21,20 +19,19 @@ package. More details below. You will need : -1. Modify the `/dev/obs/obs_codegen/__main__.py` by adding the new colorspace. -This is done by adding a new instance of `AssemblyColorspace`. - -2. Generate the HLSL code by running `python -m obs_codegen hlsl` -3. Copy the code generated in `colorspace.hlsl` (using the `//region` `//endregion` comment as marks) -4. Generate the LUA code `python -m obs_codegen lua` -5. Copy the code generated in `AgX.lua` where it "seems" to belong. -(for now just adding entries to the properties dropdown) +1. Modify the `../src/scripts/build-colorspace_core.hlsl.py` by adding the new colorspace. + 1. This is done by adding a new instance of `AssemblyColorspace`. +2. Run the script, this will automatically take care of the hlsl code. +3. You will need to manually update the LUA code : + 1. copy the lua code generated and print in the console to `AgX.lua` where it "seems" to belong. + (for now just adding entries to the properties dropdown) ## Case 2 : whole new colorspace Similar to Case 1 but : -- the step 1. is more complex : you also have to add a new Gamut/TransferFunction/Whitepoint +- the step 1.1 is more complex : you also have to add a new Gamut/TransferFunction/Whitepoint instance if needed. -- After step 3 you migth need to manually add the corresponding cctf function -(the name is generated automatically but you have to manually create it) +- If you added a new `TransferFunction` you will need to manually write its +hlsl code in the `colorscience/cctf.hlsl` module. Note the name of the function +can be found in `cctf-auto.hlsl` after running the build script. diff --git a/obs/obs-script/AgX.lua b/obs/obs-script/AgX.lua index 7fca189..abc8768 100644 --- a/obs/obs-script/AgX.lua +++ b/obs/obs-script/AgX.lua @@ -9,7 +9,7 @@ tutorial for learning the basics. ]] obs = obslua -local __version__ = "1.1.0" +local __version__ = "1.2.0" -- dependencies : local hlsl_shader_file_path = script_path() .. 'AgX.hlsl' @@ -18,7 +18,7 @@ local agx_lut_file_path = script_path() .. 'AgX-default_contrast.lut.png' function script_description() return ([[

- AgX is a display rendering transform to improve image formation. + AgX is a display rendering transform to improve imagery rendering.

Visit https://github.com/MrLixm/AgXc @@ -126,6 +126,15 @@ source_info.get_properties = function(data) obs.obs_property_list_add_int(propInputColorspace, "BT.2020 Display (OETF)", 10) obs.obs_property_list_add_int(propInputColorspace, "BT.2020 Linear", 11) obs.obs_property_list_add_int(propInputColorspace, "DCI-P3 Linear", 12) + obs.obs_property_list_add_int(propInputColorspace, "Cinema Gamut (Canon)", 13) + obs.obs_property_list_add_int(propInputColorspace, "F-Gamut FLog (Fujifilm)", 14) + obs.obs_property_list_add_int(propInputColorspace, "F-Gamut FLog2 (Fujifilm)", 15) + obs.obs_property_list_add_int(propInputColorspace, "N-Gamut (Nikon)", 16) + obs.obs_property_list_add_int(propInputColorspace, "S-Gamut (Sony)", 17) + obs.obs_property_list_add_int(propInputColorspace, "S-Gamut2 (Sony)", 18) + obs.obs_property_list_add_int(propInputColorspace, "S-Gamut3 (Sony)", 19) + obs.obs_property_list_add_int(propInputColorspace, "S-Gamut3.Cine (Sony)", 20) + obs.obs_property_list_add_int(propInputColorspace, "V-Gamut (Panasonic)", 21) local propOutputColorspace = obs.obs_properties_add_list(masterProperty, "OUTPUT_COLORSPACE", "Output Colorspace", obs.OBS_COMBO_TYPE_LIST, obs.OBS_COMBO_FORMAT_INT) -- In which colorspace is encoded the input. obs.obs_property_list_add_int(propOutputColorspace, "Passthrough", 0) @@ -141,6 +150,15 @@ source_info.get_properties = function(data) obs.obs_property_list_add_int(propOutputColorspace, "BT.2020 Display (OETF)", 10) obs.obs_property_list_add_int(propOutputColorspace, "BT.2020 Linear", 11) obs.obs_property_list_add_int(propOutputColorspace, "DCI-P3 Linear", 12) + obs.obs_property_list_add_int(propOutputColorspace, "Cinema Gamut (Canon)", 13) + obs.obs_property_list_add_int(propOutputColorspace, "F-Gamut FLog (Fujifilm)", 14) + obs.obs_property_list_add_int(propOutputColorspace, "F-Gamut FLog2 (Fujifilm)", 15) + obs.obs_property_list_add_int(propOutputColorspace, "N-Gamut (Nikon)", 16) + obs.obs_property_list_add_int(propOutputColorspace, "S-Gamut (Sony)", 17) + obs.obs_property_list_add_int(propOutputColorspace, "S-Gamut2 (Sony)", 18) + obs.obs_property_list_add_int(propOutputColorspace, "S-Gamut3 (Sony)", 19) + obs.obs_property_list_add_int(propOutputColorspace, "S-Gamut3.Cine (Sony)", 20) + obs.obs_property_list_add_int(propOutputColorspace, "V-Gamut (Panasonic)", 21) local propDrt = obs.obs_properties_add_list(masterProperty, "DRT", "DRT", obs.OBS_COMBO_TYPE_LIST, obs.OBS_COMBO_FORMAT_INT) obs.obs_property_list_add_int(propDrt, "None", 0) diff --git a/obs/obs-script/colorscience/cat.hlsl b/obs/obs-script/colorscience/cat.hlsl new file mode 100644 index 0000000..f652901 --- /dev/null +++ b/obs/obs-script/colorscience/cat.hlsl @@ -0,0 +1,163 @@ +// code generated by automatic build; do not manually edit +/* -------------------------------------------------------------------------------- +Chromatic Adaptation Transforms +-------------------------------------------------------------------------------- */ + +#define matrix_cat_XYZ_Scaling_D60_to_D65 float3x3(\ + 0.997749312, 0.0, 0.0,\ + 0.0, 1.0, 0.0,\ + 0.0, 0.0, 1.079011464\ +) +#define matrix_cat_XYZ_Scaling_D60_to_DCIP3 float3x3(\ + 0.939100313, 0.0, 0.0,\ + 0.0, 1.0, 0.0,\ + 0.0, 0.0, 0.945611705\ +) +#define matrix_cat_XYZ_Scaling_D65_to_D60 float3x3(\ + 1.002255765, 0.0, 0.0,\ + 0.0, 1.0, 0.0,\ + 0.0, 0.0, 0.926774212\ +) +#define matrix_cat_XYZ_Scaling_D65_to_DCIP3 float3x3(\ + 0.941218703, 0.0, 0.0,\ + 0.0, 1.0, 0.0,\ + 0.0, 0.0, 0.876368543\ +) +#define matrix_cat_XYZ_Scaling_DCIP3_to_D60 float3x3(\ + 1.064848969, 0.0, 0.0,\ + 0.0, 1.0, 0.0,\ + 0.0, 0.0, 1.05751652\ +) +#define matrix_cat_XYZ_Scaling_DCIP3_to_D65 float3x3(\ + 1.062452326, 0.0, 0.0,\ + 0.0, 1.0, 0.0,\ + 0.0, 0.0, 1.141072449\ +) +#define matrix_cat_Bradford_D60_to_D65 float3x3(\ + 0.987323904, -0.006062169, 0.015845876,\ + -0.007531959, 1.001832321, 0.005293338,\ + 0.00305302, -0.005064257, 1.081147527\ +) +#define matrix_cat_Bradford_D60_to_DCIP3 float3x3(\ + 0.964265012, -0.021300233, -0.002647012,\ + -0.033122492, 1.030598686, 0.000944999,\ + -0.003057139, 0.006720893, 0.941838177\ +) +#define matrix_cat_Bradford_D65_to_D60 float3x3(\ + 1.012931026, 0.006054132, -0.0148757,\ + 0.007630325, 0.998191932, -0.004999018,\ + -0.002824644, 0.004658585, 0.924961741\ +) +#define matrix_cat_Bradford_D65_to_DCIP3 float3x3(\ + 0.976578897, -0.015436265, -0.016686022,\ + -0.025689666, 1.028539168, -0.003785174,\ + -0.005705746, 0.011077866, 0.871176159\ +) +#define matrix_cat_Bradford_DCIP3_to_D60 float3x3(\ + 1.037804611, 0.021430283, 0.002895221,\ + 0.033351213, 0.971004834, -0.00088053,\ + 0.003130647, -0.006859463, 1.061769201\ +) +#define matrix_cat_Bradford_DCIP3_to_D65 float3x3(\ + 1.024496728, 0.015163541, 0.019688522,\ + 0.025612193, 0.972586306, 0.004716352,\ + 0.006384231, -0.012268083, 1.147942445\ +) +#define matrix_cat_CAT02_D60_to_D65 float3x3(\ + 0.988317991, -0.007816256, 0.016645551,\ + -0.00564353, 0.998686699, 0.00662762,\ + 0.00035077, 0.001116791, 1.077573915\ +) +#define matrix_cat_CAT02_D60_to_DCIP3 float3x3(\ + 0.979655622, -0.035093475, -0.003506859,\ + -0.024670911, 1.024631944, -0.001120007,\ + 0.000239512, -0.000975875, 0.946352523\ +) +#define matrix_cat_CAT02_D65_to_D60 float3x3(\ + 1.011870978, 0.007936977, -0.015679437,\ + 0.005720259, 1.001366784, -0.00624727,\ + -0.000335311, -0.001040394, 0.928022164\ +) +#define matrix_cat_CAT02_D65_to_DCIP3 float3x3(\ + 0.991085525, -0.027362287, -0.018395654,\ + -0.019102244, 1.025837747, -0.007053718,\ + -8.0549e-05, -0.001959887, 0.878238458\ +) +#define matrix_cat_CAT02_DCIP3_to_D60 float3x3(\ + 1.021647216, 0.034994893, 0.003827292,\ + 0.024598791, 0.976803896, 0.001247201,\ + -0.000233203, 0.00099842, 1.056688999\ +) +#define matrix_cat_CAT02_DCIP3_to_D65 float3x3(\ + 1.009516172, 0.026967753, 0.021362003,\ + 0.018799243, 0.97533018, 0.008227297,\ + 0.000134542, 0.002179032, 1.138663236\ +) +#define matrix_cat_Von_Kries_D60_to_D65 float3x3(\ + 0.995663132, -0.014998519, 0.016829124,\ + -0.001647481, 1.001234102, 0.000332195,\ + 0.0, 0.0, 1.079011464\ +) +#define matrix_cat_Von_Kries_D60_to_DCIP3 float3x3(\ + 0.9888443, -0.038575341, -0.0087295,\ + -0.004237228, 1.003172521, 0.000855893,\ + 0.0, 0.0, 0.945611705\ +) +#define matrix_cat_Von_Kries_D65_to_D60 float3x3(\ + 1.004380654, 0.015045655, -0.015669755,\ + 0.001652658, 0.998792176, -0.000333274,\ + 0.0, 0.0, 0.926774212\ +) +#define matrix_cat_Von_Kries_D65_to_DCIP3 float3x3(\ + 0.993112333, -0.023650939, -0.023572367,\ + -0.002597888, 1.001897113, 0.000525285,\ + 0.0, 0.0, 0.876368543\ +) +#define matrix_cat_Von_Kries_DCIP3_to_D60 float3x3(\ + 1.011448214, 0.038893569, 0.009302073,\ + 0.004272183, 0.997001792, -0.000862968,\ + 0.0, 0.0, 1.05751652\ +) +#define matrix_cat_Von_Kries_DCIP3_to_D65 float3x3(\ + 1.00699762, 0.023771342, 0.027071751,\ + 0.002611113, 0.998168118, -0.000528057,\ + 0.0, 0.0, 1.141072449\ +) + +uniform int catid_XYZ_Scaling = 0; +uniform int catid_Bradford = 1; +uniform int catid_CAT02 = 2; +uniform int catid_Von_Kries = 3; + +uniform int whitepointid_D60 = 0; +uniform int whitepointid_D65 = 1; +uniform int whitepointid_DCIP3 = 2; + + +float3x3 get_chromatic_adaptation_transform_matrix(int cat_id, int whitepoint_source, int whitepoint_target){ + if (cat_id == 0 && whitepoint_source == 0 && whitepoint_target == 1) return matrix_cat_XYZ_Scaling_D60_to_D65; + if (cat_id == 0 && whitepoint_source == 0 && whitepoint_target == 2) return matrix_cat_XYZ_Scaling_D60_to_DCIP3; + if (cat_id == 0 && whitepoint_source == 1 && whitepoint_target == 0) return matrix_cat_XYZ_Scaling_D65_to_D60; + if (cat_id == 0 && whitepoint_source == 1 && whitepoint_target == 2) return matrix_cat_XYZ_Scaling_D65_to_DCIP3; + if (cat_id == 0 && whitepoint_source == 2 && whitepoint_target == 0) return matrix_cat_XYZ_Scaling_DCIP3_to_D60; + if (cat_id == 0 && whitepoint_source == 2 && whitepoint_target == 1) return matrix_cat_XYZ_Scaling_DCIP3_to_D65; + if (cat_id == 1 && whitepoint_source == 0 && whitepoint_target == 1) return matrix_cat_Bradford_D60_to_D65; + if (cat_id == 1 && whitepoint_source == 0 && whitepoint_target == 2) return matrix_cat_Bradford_D60_to_DCIP3; + if (cat_id == 1 && whitepoint_source == 1 && whitepoint_target == 0) return matrix_cat_Bradford_D65_to_D60; + if (cat_id == 1 && whitepoint_source == 1 && whitepoint_target == 2) return matrix_cat_Bradford_D65_to_DCIP3; + if (cat_id == 1 && whitepoint_source == 2 && whitepoint_target == 0) return matrix_cat_Bradford_DCIP3_to_D60; + if (cat_id == 1 && whitepoint_source == 2 && whitepoint_target == 1) return matrix_cat_Bradford_DCIP3_to_D65; + if (cat_id == 2 && whitepoint_source == 0 && whitepoint_target == 1) return matrix_cat_CAT02_D60_to_D65; + if (cat_id == 2 && whitepoint_source == 0 && whitepoint_target == 2) return matrix_cat_CAT02_D60_to_DCIP3; + if (cat_id == 2 && whitepoint_source == 1 && whitepoint_target == 0) return matrix_cat_CAT02_D65_to_D60; + if (cat_id == 2 && whitepoint_source == 1 && whitepoint_target == 2) return matrix_cat_CAT02_D65_to_DCIP3; + if (cat_id == 2 && whitepoint_source == 2 && whitepoint_target == 0) return matrix_cat_CAT02_DCIP3_to_D60; + if (cat_id == 2 && whitepoint_source == 2 && whitepoint_target == 1) return matrix_cat_CAT02_DCIP3_to_D65; + if (cat_id == 3 && whitepoint_source == 0 && whitepoint_target == 1) return matrix_cat_Von_Kries_D60_to_D65; + if (cat_id == 3 && whitepoint_source == 0 && whitepoint_target == 2) return matrix_cat_Von_Kries_D60_to_DCIP3; + if (cat_id == 3 && whitepoint_source == 1 && whitepoint_target == 0) return matrix_cat_Von_Kries_D65_to_D60; + if (cat_id == 3 && whitepoint_source == 1 && whitepoint_target == 2) return matrix_cat_Von_Kries_D65_to_DCIP3; + if (cat_id == 3 && whitepoint_source == 2 && whitepoint_target == 0) return matrix_cat_Von_Kries_DCIP3_to_D60; + if (cat_id == 3 && whitepoint_source == 2 && whitepoint_target == 1) return matrix_cat_Von_Kries_DCIP3_to_D65; + return matrix_identity_3x3; +} \ No newline at end of file diff --git a/obs/obs-script/colorscience/cctf-auto.hlsl b/obs/obs-script/colorscience/cctf-auto.hlsl new file mode 100644 index 0000000..14d10db --- /dev/null +++ b/obs/obs-script/colorscience/cctf-auto.hlsl @@ -0,0 +1,53 @@ +// code generated by automatic build; do not manually edit + +uniform int cctf_id_Power_2_2 = 0; // Power 2.2 +uniform int cctf_id_sRGB_EOTF = 1; // sRGB EOTF +uniform int cctf_id_BT_709 = 2; // BT.709 +uniform int cctf_id_DCIP3 = 3; // DCI-P3 +uniform int cctf_id_Display_P3 = 4; // Display P3 +uniform int cctf_id_Adobe_RGB_1998 = 5; // Adobe RGB 1998 +uniform int cctf_id_BT_2020 = 6; // BT.2020 +uniform int cctf_id_FLog = 7; // FLog +uniform int cctf_id_FLog2 = 8; // FLog2 +uniform int cctf_id_NLog = 9; // NLog +uniform int cctf_id_SLog = 10; // SLog +uniform int cctf_id_SLog2 = 11; // SLog2 +uniform int cctf_id_SLog3 = 12; // SLog3 +uniform int cctf_id_VLog = 13; // VLog + + +float3 apply_cctf_decoding(float3 color, int cctf_id){ + if (cctf_id == cctf_id_Power_2_2 ) return cctf_decoding_Power_2_2(color); + if (cctf_id == cctf_id_sRGB_EOTF ) return cctf_decoding_sRGB_EOTF(color); + if (cctf_id == cctf_id_BT_709 ) return cctf_decoding_BT_709(color); + if (cctf_id == cctf_id_DCIP3 ) return cctf_decoding_DCIP3(color); + if (cctf_id == cctf_id_Display_P3 ) return cctf_decoding_Display_P3(color); + if (cctf_id == cctf_id_Adobe_RGB_1998 ) return cctf_decoding_Adobe_RGB_1998(color); + if (cctf_id == cctf_id_BT_2020 ) return cctf_decoding_BT_2020(color); + if (cctf_id == cctf_id_FLog ) return cctf_decoding_FLog(color); + if (cctf_id == cctf_id_FLog2 ) return cctf_decoding_FLog2(color); + if (cctf_id == cctf_id_NLog ) return cctf_decoding_NLog(color); + if (cctf_id == cctf_id_SLog ) return cctf_decoding_SLog(color); + if (cctf_id == cctf_id_SLog2 ) return cctf_decoding_SLog2(color); + if (cctf_id == cctf_id_SLog3 ) return cctf_decoding_SLog3(color); + if (cctf_id == cctf_id_VLog ) return cctf_decoding_VLog(color); + return color; +} + +float3 apply_cctf_encoding(float3 color, int cctf_id){ + if (cctf_id == cctf_id_Power_2_2 ) return cctf_encoding_Power_2_2(color); + if (cctf_id == cctf_id_sRGB_EOTF ) return cctf_encoding_sRGB_EOTF(color); + if (cctf_id == cctf_id_BT_709 ) return cctf_encoding_BT_709(color); + if (cctf_id == cctf_id_DCIP3 ) return cctf_encoding_DCIP3(color); + if (cctf_id == cctf_id_Display_P3 ) return cctf_encoding_Display_P3(color); + if (cctf_id == cctf_id_Adobe_RGB_1998 ) return cctf_encoding_Adobe_RGB_1998(color); + if (cctf_id == cctf_id_BT_2020 ) return cctf_encoding_BT_2020(color); + if (cctf_id == cctf_id_FLog ) return cctf_encoding_FLog(color); + if (cctf_id == cctf_id_FLog2 ) return cctf_encoding_FLog2(color); + if (cctf_id == cctf_id_NLog ) return cctf_encoding_NLog(color); + if (cctf_id == cctf_id_SLog ) return cctf_encoding_SLog(color); + if (cctf_id == cctf_id_SLog2 ) return cctf_encoding_SLog2(color); + if (cctf_id == cctf_id_SLog3 ) return cctf_encoding_SLog3(color); + if (cctf_id == cctf_id_VLog ) return cctf_encoding_VLog(color); + return color; +} \ No newline at end of file diff --git a/obs/obs-script/colorscience/cctf.hlsl b/obs/obs-script/colorscience/cctf.hlsl new file mode 100644 index 0000000..e7a9a76 --- /dev/null +++ b/obs/obs-script/colorscience/cctf.hlsl @@ -0,0 +1,288 @@ +/* -------------------------------------------------------------------------------- +Transfer functions + +References +---------- + +All data without explicit reference can assumed to be extracted/generated from `colour-science` python library. + +- [1] https://github.com/sobotka/AgX-S2O3/blob/main/AgX.py +- [2] https://github.com/colour-science/colour/blob/develop/colour/models/rgb/transfer_functions/srgb.py#L99 +- [3] https://dl.fujifilm-x.com/support/lut/F-Log_DataSheet_E_Ver.1.0.pdf +- [4] https://dl.fujifilm-x.com/support/lut/F-Log2_DataSheet_E_Ver.1.0.pdf +- [5] https://github.com/colour-science/colour/blob/develop/colour/models/rgb/transfer_functions/fujifilm_f_log.py +- [6] http://download.nikonimglib.com/archive3/hDCmK00m9JDI03RPruD74xpoU905/N-Log_Specification_(En)01.pdf +- [7] https://github.com/colour-science/colour/blob/develop/colour/models/rgb/transfer_functions/sony.py +- [8] https://drive.google.com/file/d/1Q1RYri6BaxtYYxX0D4zVD6lAmbwmgikc/view +- [9] https://pro-av.panasonic.net/en/cinema_camera_varicam_eva/support/pdf/VARICAM_V-Log_V-Gamut.pdf +-------------------------------------------------------------------------------- */ + +float3 cctf_log2_normalized_from_open_domain(float3 color, float minimum_ev, float maximum_ev) +/* + Output log domain encoded data. + + Similar to OCIO lg2 AllocationTransform. + + --ref[1] +*/ +{ + float in_midgrey = 0.18; + + // remove negative before log transform + color = max(0.0, color); + // avoid infinite issue with log -- ref[1] + color = (color < 0.00003051757) ? (0.00001525878 + color) : (color); + color = clamp( + log2(color / in_midgrey), + float3(minimum_ev, minimum_ev, minimum_ev), + float3(maximum_ev,maximum_ev,maximum_ev) + ); + float total_exposure = maximum_ev - minimum_ev; + + return (color - minimum_ev) / total_exposure; +} + +// exactly the same as above but I let it for reference +float3 cctf_log2_ocio_transform(float3 color) +/* + Output log domain encoded data. + + Copy of OCIO lg2 AllocationTransform with the AgX Log values. + + :param color: rgba linear color data +*/ +{ + // remove negative before log transform + color = max(0.0, color); + color = (color < 0.00003051757) ? (log2(0.00001525878 + color * 0.5)) : (log2(color)); + + // obtained via m = ocio.MatrixTransform.Fit(oldMin=[-12.47393, -12.47393, -12.47393, 0.0], oldMax=[4.026069, 4.026069, 4.026069, 1.0]) + float3x3 fitMatrix = float3x3( + 0.060606064279155415, 0.0, 0.0, + 0.0, 0.060606064279155415, 0.0, + 0.0, 0.0, 0.060606064279155415 + ); + // obtained via same as above + float fitMatrixOffset = 0.7559958033936851; + color = mul(fitMatrix, color); + color += fitMatrixOffset.xxx; + + return color; +} + +float3 cctf_decoding_sRGB_EOTF(float3 color){ + // ref[2] + return (color <= 0.04045) ? (color / 12.92) : (powsafe((color + 0.055) / 1.055, 2.4)); +} +float3 cctf_encoding_sRGB_EOTF(float3 color){ + // ref[2] + return (color <= 0.0031308) ? (color * 12.92) : (1.055 * powsafe(color, 1/2.4) - 0.055); +} + +float3 cctf_decoding_Power_2_2(float3 color){return powsafe(color, 2.2);} +float3 cctf_encoding_Power_2_2(float3 color){return powsafe(color, 1/2.2);} + +float3 cctf_decoding_BT_709(float3 color){return powsafe(color, 2.4);} +float3 cctf_encoding_BT_709(float3 color){return powsafe(color, 1/2.4);} + +float3 cctf_decoding_DCIP3(float3 color){return powsafe(color, 2.6);} +float3 cctf_encoding_DCIP3(float3 color){return powsafe(color, 1/2.6);} + +float3 cctf_encoding_BT_2020(float3 color){ + return (color < 0.0181) ? color * 4.5 : 1.0993 * powsafe(color, 0.45) - (1.0993 - 1); +} +float3 cctf_decoding_BT_2020(float3 color){ + return (color < cctf_encoding_BT_2020(0.0181)) ? color / 4.5 : powsafe((color + (1.0993 - 1)) / 1.0993, 1 / 0.45) ; +} + +float3 cctf_decoding_Display_P3(float3 color){return cctf_decoding_sRGB_EOTF(color);} +float3 cctf_encoding_Display_P3(float3 color){return cctf_encoding_sRGB_EOTF(color);} + +float3 cctf_decoding_Adobe_RGB_1998(float3 color){return powsafe(color, 2.19921875);} +float3 cctf_encoding_Adobe_RGB_1998(float3 color){return powsafe(color, 1/2.19921875);} + + +struct _FLogConstants { + float a; + float b; + float c; + float d; + float e; + float f; + float cut1; + float cut2; +}; +// ref[3] +_FLogConstants FLogConstants(){ + _FLogConstants output; + output.a = 0.555556; + output.b = 0.009468; + output.c = 0.344676; + output.d = 0.790453; + output.e = 8.735631; + output.f = 0.092864; + output.cut1 = 0.00089; + output.cut2 = 0.10053777522386; + return output; +} +// ref[4] +_FLogConstants FLog2Constants(){ + _FLogConstants output; + output.a = 5.555556; + output.b = 0.064829; + output.c = 0.245281; + output.d = 0.384316; + output.e = 8.799461; + output.f = 0.092864; + output.cut1 = 0.000889; + output.cut2 = 0.100686685370811; + return output; +} + +// ref[3][4][5] +float3 _cctf_decoding_FLog(float3 color, _FLogConstants flconst){ + return color < flconst.cut2 ? + (color - flconst.f) / flconst.e : + pow(10.0, ((color - flconst.d) / flconst.c)) / flconst.a - flconst.b / flconst.a; +} +float3 _cctf_encoding_FLog(float3 color, _FLogConstants flconst){ + return color < flconst.cut1 ? + flconst.e * color + flconst.f : + flconst.c * log10(flconst.a * color + flconst.b) + flconst.d; +} + +float3 cctf_decoding_FLog(float3 color){return _cctf_decoding_FLog(color, FLogConstants());} +float3 cctf_encoding_FLog(float3 color){return _cctf_encoding_FLog(color, FLogConstants());} + +float3 cctf_decoding_FLog2(float3 color){return _cctf_decoding_FLog(color, FLog2Constants());} +float3 cctf_encoding_FLog2(float3 color){return _cctf_encoding_FLog(color, FLog2Constants());} + +struct _NLogConstants { + float a; + float b; + float c; + float d; + float cut1; + float cut2; +}; +// ref[6] +_NLogConstants NLogConstants(){ + _NLogConstants output; + output.a = 650.0/1023.0; + output.b = 0.0075; + output.c = 150.0/1023.0; + output.d = 619.0/1023.0; + output.cut1 = 0.328; + output.cut2 = 452.0/1023.0; + return output; +} +// ref[6] +float3 cctf_decoding_NLog(float3 color){ + _NLogConstants nlconst = NLogConstants(); + return color < nlconst.cut2 ? + powsafe(color/nlconst.a, 3.0) - nlconst.b: + exp((color - nlconst.d) / nlconst.c); +} +float3 cctf_encoding_NLog(float3 color){ + _NLogConstants nlconst = NLogConstants(); + return color < nlconst.cut1 ? + nlconst.a * powsafe(color + nlconst.b, 1.0/3.0): + nlconst.c * log(color) + nlconst.d; +} + +struct _SLogConstants { + float a; + float b; + float c; + float d; + float e; + float f; + float g; + float h; +}; +// ref[7][8] +_SLogConstants SLogConstants(){ + _SLogConstants output; + output.a = 0.432699; + output.b = 0.616596; + output.c = 0.030001222851889303; + output.d = 3.53881278538813; + output.e = 0.03; + output.f = 155.0; + output.g = 219.0; + output.h = 0.037584; + return output; +} +// ref[7] +float3 cctf_encoding_SLog(float3 color){ + _SLogConstants slconst = SLogConstants(); + // convert from reflection to IRE + float3 outcolor = color / 0.9; + outcolor = color >= 0.0 ? + (slconst.a * log10(outcolor + slconst.h) + slconst.b) + slconst.e: + outcolor * 5.0 + slconst.c; + // asume bitdepth=10 and out_normalised_code_value=True compared to colour + return convert_cctf_full_to_legal(outcolor); + +} +float3 cctf_decoding_SLog(float3 color){ + _SLogConstants slconst = SLogConstants(); + // asume bitdepth=10 and in_normalised_code_value=True compared to colour + float3 outcolor = convert_cctf_legal_to_full(color); + outcolor = color >= cctf_encoding_SLog(0.0) ? + pow(10.0, (color - slconst.b - slconst.e) / slconst.a) - slconst.h: + (color - slconst.c) / 5.0; + // convert IRE to reflection + return outcolor * 0.9; + +} + +float3 cctf_decoding_SLog2(float3 color){return 219.0 * cctf_decoding_SLog(color) / 155.0;} +float3 cctf_encoding_SLog2(float3 color){return cctf_encoding_SLog(color * 155.0 / 219.0);} + + +// ref[7] +float3 cctf_decoding_SLog3(float3 color){ + float slconst_a = 0.01125000; + float slconst_b = 171.2102946929; + return color >= slconst_b / 1023.0 ? + pow(10.0, (color * 1023.0 - 420.0) / 261.5) * (0.18 + 0.01) - 0.01: + (color * 1023.0 - 95.0) * slconst_a / (slconst_b - 95.0); +} +float3 cctf_encoding_SLog3(float3 color){ + float slconst_a = 0.01125000; + float slconst_b = 171.2102946929; + return color >= slconst_a ? + (420.0 + log10((color + 0.01) / (0.18 + 0.01)) * 261.5) / 1023.0: + (color * (slconst_b - 95.0) / slconst_a + 95.0) / 1023.0; +} + +struct _VLogConstants { + float b; + float c; + float d; + float cut1; + float cut2; +}; +// ref[9] +_VLogConstants VLogConstants(){ + _VLogConstants output; + output.b = 0.00873; + output.c = 0.241514; + output.d = 0.598206; + output.cut1 = 0.01; + output.cut2 = 0.181; + return output; +} +float3 cctf_decoding_VLog(float3 color){ + _VLogConstants vlconst = VLogConstants(); + return color < vlconst.cut2 ? + (color - 0.125) / 5.6: + pow(10.0, (color - vlconst.d) / vlconst.c) - vlconst.b; +} +float3 cctf_encoding_VLog(float3 color){ + _VLogConstants vlconst = VLogConstants(); + return color < vlconst.cut1 ? + 5.6 * color + 0.125: + vlconst.c * log10(color + vlconst.b) + vlconst.d; +} diff --git a/obs/obs-script/colorscience/colorspace.hlsl b/obs/obs-script/colorscience/colorspace.hlsl new file mode 100644 index 0000000..8d06e6f --- /dev/null +++ b/obs/obs-script/colorscience/colorspace.hlsl @@ -0,0 +1,150 @@ +// code generated by automatic build; do not manually edit +/* -------------------------------------------------------------------------------- +Colorspaces +-------------------------------------------------------------------------------- */ + +struct Colorspace{ + int gamut_id; + int whitepoint_id; + int cctf_id; +}; + +uniform int colorspaceid_Passthrough = 0; +uniform int colorspaceid_sRGB_Display_EOTF = 1; +uniform int colorspaceid_sRGB_Display_2_2 = 2; +uniform int colorspaceid_sRGB_Linear = 3; +uniform int colorspaceid_BT_709_Display_2_4 = 4; +uniform int colorspaceid_DCIP3_Display_2_6 = 5; +uniform int colorspaceid_DCIP3_D65_Display_2_6 = 6; +uniform int colorspaceid_DCIP3_D60_Display_2_6 = 7; +uniform int colorspaceid_Apple_Display_P3 = 8; +uniform int colorspaceid_Adobe_RGB_1998_Display = 9; +uniform int colorspaceid_BT_2020_Display_OETF = 10; +uniform int colorspaceid_BT_2020_Linear = 11; +uniform int colorspaceid_DCIP3_Linear = 12; +uniform int colorspaceid_Cinema_Gamut_Canon = 13; +uniform int colorspaceid_FGamut_FLog_Fujifilm = 14; +uniform int colorspaceid_FGamut_FLog2_Fujifilm = 15; +uniform int colorspaceid_NGamut_Nikon = 16; +uniform int colorspaceid_SGamut_Sony = 17; +uniform int colorspaceid_SGamut2_Sony = 18; +uniform int colorspaceid_SGamut3_Sony = 19; +uniform int colorspaceid_SGamut3_Cine_Sony = 20; +uniform int colorspaceid_VGamut_Panasonic = 21; + +Colorspace getColorspaceFromId(int colorspace_id){ + + Colorspace colorspace; + + if (colorspace_id == colorspaceid_Passthrough){ + colorspace.gamut_id = -1; + colorspace.whitepoint_id = -1; + colorspace.cctf_id = -1; + }; + if (colorspace_id == colorspaceid_sRGB_Display_EOTF){ + colorspace.gamut_id = gamutid_sRGB; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_sRGB_EOTF; + }; + if (colorspace_id == colorspaceid_sRGB_Display_2_2){ + colorspace.gamut_id = gamutid_sRGB; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_Power_2_2; + }; + if (colorspace_id == colorspaceid_sRGB_Linear){ + colorspace.gamut_id = gamutid_sRGB; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = -1; + }; + if (colorspace_id == colorspaceid_BT_709_Display_2_4){ + colorspace.gamut_id = gamutid_sRGB; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_BT_709; + }; + if (colorspace_id == colorspaceid_DCIP3_Display_2_6){ + colorspace.gamut_id = gamutid_DCIP3; + colorspace.whitepoint_id = whitepointid_DCIP3; + colorspace.cctf_id = cctf_id_DCIP3; + }; + if (colorspace_id == colorspaceid_DCIP3_D65_Display_2_6){ + colorspace.gamut_id = gamutid_DCIP3; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_DCIP3; + }; + if (colorspace_id == colorspaceid_DCIP3_D60_Display_2_6){ + colorspace.gamut_id = gamutid_DCIP3; + colorspace.whitepoint_id = whitepointid_D60; + colorspace.cctf_id = cctf_id_DCIP3; + }; + if (colorspace_id == colorspaceid_Apple_Display_P3){ + colorspace.gamut_id = gamutid_Display_P3; + colorspace.whitepoint_id = whitepointid_DCIP3; + colorspace.cctf_id = cctf_id_Display_P3; + }; + if (colorspace_id == colorspaceid_Adobe_RGB_1998_Display){ + colorspace.gamut_id = gamutid_Adobe_RGB_1998; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_Adobe_RGB_1998; + }; + if (colorspace_id == colorspaceid_BT_2020_Display_OETF){ + colorspace.gamut_id = gamutid_ITUR_BT_2020; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_BT_2020; + }; + if (colorspace_id == colorspaceid_BT_2020_Linear){ + colorspace.gamut_id = gamutid_ITUR_BT_2020; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = -1; + }; + if (colorspace_id == colorspaceid_DCIP3_Linear){ + colorspace.gamut_id = gamutid_DCIP3; + colorspace.whitepoint_id = whitepointid_DCIP3; + colorspace.cctf_id = -1; + }; + if (colorspace_id == colorspaceid_Cinema_Gamut_Canon){ + colorspace.gamut_id = gamutid_Cinema_Gamut; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = -1; + }; + if (colorspace_id == colorspaceid_FGamut_FLog_Fujifilm){ + colorspace.gamut_id = gamutid_ITUR_BT_2020; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_FLog; + }; + if (colorspace_id == colorspaceid_FGamut_FLog2_Fujifilm){ + colorspace.gamut_id = gamutid_ITUR_BT_2020; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_FLog2; + }; + if (colorspace_id == colorspaceid_NGamut_Nikon){ + colorspace.gamut_id = gamutid_ITUR_BT_2020; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_NLog; + }; + if (colorspace_id == colorspaceid_SGamut_Sony){ + colorspace.gamut_id = gamutid_SGamut; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_SLog; + }; + if (colorspace_id == colorspaceid_SGamut2_Sony){ + colorspace.gamut_id = gamutid_SGamut; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_SLog2; + }; + if (colorspace_id == colorspaceid_SGamut3_Sony){ + colorspace.gamut_id = gamutid_SGamut; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_SLog3; + }; + if (colorspace_id == colorspaceid_SGamut3_Cine_Sony){ + colorspace.gamut_id = gamutid_SGamut3_Cine; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_SLog3; + }; + if (colorspace_id == colorspaceid_VGamut_Panasonic){ + colorspace.gamut_id = gamutid_VGamut; + colorspace.whitepoint_id = whitepointid_D65; + colorspace.cctf_id = cctf_id_VLog; + }; + return colorspace; +} \ No newline at end of file diff --git a/obs/obs-script/colorscience/gamut.hlsl b/obs/obs-script/colorscience/gamut.hlsl new file mode 100644 index 0000000..3ff663e --- /dev/null +++ b/obs/obs-script/colorscience/gamut.hlsl @@ -0,0 +1,150 @@ +// code generated by automatic build; do not manually edit +/* -------------------------------------------------------------------------------- +Matrices +-------------------------------------------------------------------------------- */ + +// sRGB +#define matrix_sRGB_to_XYZ float3x3(\ + 0.4124, 0.3576, 0.1805,\ + 0.2126, 0.7152, 0.0722,\ + 0.0193, 0.1192, 0.9505\ +) +#define matrix_sRGB_from_XYZ float3x3(\ + 3.2406, -1.5372, -0.4986,\ + -0.9689, 1.8758, 0.0415,\ + 0.0557, -0.204, 1.057\ +) + +// DCI-P3 +#define matrix_DCIP3_to_XYZ float3x3(\ + 0.445169816, 0.277134409, 0.17228267,\ + 0.209491678, 0.721595254, 0.068913068,\ + -0.0, 0.04706056, 0.907355394\ +) +#define matrix_DCIP3_from_XYZ float3x3(\ + 2.72539403, -1.018003006, -0.440163195,\ + -0.795168026, 1.689732055, 0.022647191,\ + 0.041241891, -0.087639019, 1.100929379\ +) + +// Display P3 +#define matrix_Display_P3_to_XYZ float3x3(\ + 0.486570949, 0.265667693, 0.198217285,\ + 0.228974564, 0.691738522, 0.079286914,\ + -0.0, 0.045113382, 1.043944369\ +) +#define matrix_Display_P3_from_XYZ float3x3(\ + 2.493496912, -0.931383618, -0.402710784,\ + -0.82948897, 1.76266406, 0.023624686,\ + 0.03584583, -0.076172389, 0.956884524\ +) + +// Adobe RGB (1998) +#define matrix_Adobe_RGB_1998_to_XYZ float3x3(\ + 0.57667, 0.18556, 0.18823,\ + 0.29734, 0.62736, 0.07529,\ + 0.02703, 0.07069, 0.99134\ +) +#define matrix_Adobe_RGB_1998_from_XYZ float3x3(\ + 2.04159, -0.56501, -0.34473,\ + -0.96924, 1.87597, 0.04156,\ + 0.01344, -0.11836, 1.01517\ +) + +// ITU-R BT.2020 +#define matrix_ITUR_BT_2020_to_XYZ float3x3(\ + 0.636958048, 0.144616904, 0.168880975,\ + 0.262700212, 0.677998072, 0.059301716,\ + 0.0, 0.028072693, 1.060985058\ +) +#define matrix_ITUR_BT_2020_from_XYZ float3x3(\ + 1.716651188, -0.355670784, -0.253366281,\ + -0.666684352, 1.616481237, 0.015768546,\ + 0.017639857, -0.042770613, 0.942103121\ +) + +// Cinema Gamut +#define matrix_Cinema_Gamut_to_XYZ float3x3(\ + 0.716049647, 0.129683478, 0.104722803,\ + 0.261261358, 0.869642146, -0.130903503,\ + -0.009676347, -0.236481636, 1.335215733\ +) +#define matrix_Cinema_Gamut_from_XYZ float3x3(\ + 1.489818275, -0.260895902, -0.142426522,\ + -0.458166574, 1.261627783, 0.159623632,\ + -0.070349668, 0.221557667, 0.776181604\ +) + +// S-Gamut +#define matrix_SGamut_to_XYZ float3x3(\ + 0.706482713, 0.12880105, 0.115172164,\ + 0.270979671, 0.786606411, -0.057586082,\ + -0.009677845, 0.004600038, 1.094135559\ +) +#define matrix_SGamut_from_XYZ float3x3(\ + 1.507399899, -0.245822137, -0.171611681,\ + -0.518151727, 1.355391241, 0.125878668,\ + 0.015511698, -0.007872771, 0.911916366\ +) + +// S-Gamut3.Cine +#define matrix_SGamut3_Cine_to_XYZ float3x3(\ + 0.599083921, 0.248925516, 0.10244649,\ + 0.21507582, 0.885068502, -0.100144322,\ + -0.03206585, -0.027658391, 1.148781991\ +) +#define matrix_SGamut3_Cine_from_XYZ float3x3(\ + 1.846778969, -0.525986123, -0.210545211,\ + -0.444153263, 1.259442903, 0.149399973,\ + 0.040855421, 0.015640889, 0.868207249\ +) + +// V-Gamut +#define matrix_VGamut_to_XYZ float3x3(\ + 0.679644, 0.152211, 0.1186,\ + 0.260686, 0.774894, -0.03558,\ + -0.00931, -0.004612, 1.10298\ +) +#define matrix_VGamut_from_XYZ float3x3(\ + 1.589012, -0.313204, -0.180965,\ + -0.534053, 1.396011, 0.102458,\ + 0.011179, 0.003194, 0.905535\ +) + + +uniform int gamutid_sRGB = 0; +uniform int gamutid_DCIP3 = 1; +uniform int gamutid_Display_P3 = 2; +uniform int gamutid_Adobe_RGB_1998 = 3; +uniform int gamutid_ITUR_BT_2020 = 4; +uniform int gamutid_Cinema_Gamut = 5; +uniform int gamutid_SGamut = 6; +uniform int gamutid_SGamut3_Cine = 7; +uniform int gamutid_VGamut = 8; + + +float3x3 get_gamut_matrix_to_XYZ(int gamutid){ + if (gamutid == gamutid_sRGB ) return matrix_sRGB_to_XYZ; + if (gamutid == gamutid_DCIP3 ) return matrix_DCIP3_to_XYZ; + if (gamutid == gamutid_Display_P3 ) return matrix_Display_P3_to_XYZ; + if (gamutid == gamutid_Adobe_RGB_1998 ) return matrix_Adobe_RGB_1998_to_XYZ; + if (gamutid == gamutid_ITUR_BT_2020 ) return matrix_ITUR_BT_2020_to_XYZ; + if (gamutid == gamutid_Cinema_Gamut ) return matrix_Cinema_Gamut_to_XYZ; + if (gamutid == gamutid_SGamut ) return matrix_SGamut_to_XYZ; + if (gamutid == gamutid_SGamut3_Cine ) return matrix_SGamut3_Cine_to_XYZ; + if (gamutid == gamutid_VGamut ) return matrix_VGamut_to_XYZ; + return matrix_identity_3x3; +} + +float3x3 get_gamut_matrix_from_XYZ(int gamutid){ + if (gamutid == gamutid_sRGB ) return matrix_sRGB_from_XYZ; + if (gamutid == gamutid_DCIP3 ) return matrix_DCIP3_from_XYZ; + if (gamutid == gamutid_Display_P3 ) return matrix_Display_P3_from_XYZ; + if (gamutid == gamutid_Adobe_RGB_1998 ) return matrix_Adobe_RGB_1998_from_XYZ; + if (gamutid == gamutid_ITUR_BT_2020 ) return matrix_ITUR_BT_2020_from_XYZ; + if (gamutid == gamutid_Cinema_Gamut ) return matrix_Cinema_Gamut_from_XYZ; + if (gamutid == gamutid_SGamut ) return matrix_SGamut_from_XYZ; + if (gamutid == gamutid_SGamut3_Cine ) return matrix_SGamut3_Cine_from_XYZ; + if (gamutid == gamutid_VGamut ) return matrix_VGamut_from_XYZ; + return matrix_identity_3x3; +} \ No newline at end of file diff --git a/obs/obs-script/colorscience/math.hlsl b/obs/obs-script/colorscience/math.hlsl new file mode 100644 index 0000000..9b9e6ad --- /dev/null +++ b/obs/obs-script/colorscience/math.hlsl @@ -0,0 +1,66 @@ +/* +References +---------- + +- [1] https://github.com/ampas/aces-dev/blob/master/transforms/ctl/lib/ACESlib.Utilities_Color.ctl#L492 +- [2] https://github.com/colour-science/colour/blob/develop/colour/models/rgb/transfer_functions/common.py +*/ +#define matrix_identity_3x3 float3x3(\ + 1.0, 0.0, 0.0,\ + 0.0, 1.0, 0.0,\ + 0.0, 0.0, 1.0\ +) + +#define luma_coefs_bt709 float3(0.2126, 0.7152, 0.0722) + +float3 powsafe(float3 color, float power){ + // pow() but safe for NaNs/negatives + return pow(abs(color), power) * sign(color); +} + +float3 apply_matrix(float3 color, float3x3 inputMatrix){ + // seems you can't just use mul() with OBS, and we have to split per component like that : + float r = dot(color, inputMatrix[0]); + float g = dot(color, inputMatrix[1]); + float b = dot(color, inputMatrix[2]); + return float3(r, g, b); +} + +float get_luminance(float3 image){ + // Return approximative perceptive luminance of the image. + return dot(image, luma_coefs_bt709); +} + +float3 saturation(float3 color, float saturationAmount){ + /* + + Increase color saturation of the given color data. + + :param color: expected sRGB primaries input + :oaram saturationAmount: expected 0-1 range with 1=neutral, 0=no saturation. + + -- ref[1] + */ + float luma = get_luminance(color); + return lerp(luma, color, saturationAmount); +} + +float3 convert_cctf_full_to_legal(float3 color){ + // ref[2] but we assume bitdepth=10, in_int=False, out_int=False + float bitdepth = 10.0; + float MV = pow(2.0, bitdepth) - 1.0; + float B = 64.0; + float W = 940.0; + float3 CV_legal = (W - B) * color + B; + return CV_legal / MV; +} + +float3 convert_cctf_legal_to_full(float3 color){ + // ref[2] but we assume bitdepth=10, in_int=False, out_int=False + float bitdepth = 10.0; + float MV = pow(2.0, bitdepth) - 1.0; + float B = 64.0; + float W = 940.0; + float3 CV_full = color * MV; + return (CV_full - B) / (W - B); +} \ No newline at end of file diff --git a/obs/obs-script/colorspace.hlsl b/obs/obs-script/colorspace.hlsl index b2489e2..07ef37d 100644 --- a/obs/obs-script/colorspace.hlsl +++ b/obs/obs-script/colorspace.hlsl @@ -6,532 +6,17 @@ References ---------- All data without explicit reference can assumed to be extracted/generated from `colour-science` python library. - -- [1] https://github.com/sobotka/AgX-S2O3/blob/main/AgX.py -- [2] https://github.com/colour-science/colour/blob/develop/colour/models/rgb/transfer_functions/srgb.py#L99 -- [3] https://github.com/colour-science/colour/blob/develop/colour/models/rgb/transfer_functions/st_2084.py -- [4] https://github.com/ampas/aces-dev/blob/master/transforms/ctl/lib/ACESlib.Utilities_Color.ctl#L492 -- [5] https://github.com/ampas/aces-dev/blob/master/transforms/ctl/lib/ACESlib.ODT_Common.ctl#L42 */ - uniform int CAT_METHOD = 0; // See Chromatic Adapatation transform section for availables ids +#include "colorscience/math.hlsl" +#include "colorscience/cctf.hlsl" +#include "colorscience/cctf-auto.hlsl" +#include "colorscience/cat.hlsl" +#include "colorscience/gamut.hlsl" +#include "colorscience/colorspace.hlsl" -#define luma_coefs_bt709 float3(0.2126, 0.7152, 0.0722) - -#define matrix_identity_3x3 float3x3(\ - 1.0, 0.0, 0.0,\ - 0.0, 1.0, 0.0,\ - 0.0, 0.0, 1.0\ -) - -float3 powsafe(float3 color, float power){ - // pow() but safe for NaNs/negatives - return pow(abs(color), power) * sign(color); -} - -float3 apply_matrix(float3 color, float3x3 inputMatrix){ - // seems you can't just use mul() with OBS, and we have to split per component like that : - float r = dot(color, inputMatrix[0]); - float g = dot(color, inputMatrix[1]); - float b = dot(color, inputMatrix[2]); - return float3(r, g, b); -} - -float get_luminance(float3 image){ - // Return approximative perceptive luminance of the image. - return dot(image, luma_coefs_bt709); -} - -float3 saturation(float3 color, float saturationAmount){ - /* - - Increase color saturation of the given color data. - - :param color: expected sRGB primaries input - :oaram saturationAmount: expected 0-1 range with 1=neutral, 0=no saturation. - - -- ref[2] [4] - */ - float luma = get_luminance(color); - return lerp(luma, color, saturationAmount); -} - -/* -------------------------------------------------------------------------------- -Transfer functions --------------------------------------------------------------------------------- */ - -float3 cctf_log2_normalized_from_open_domain(float3 color, float minimum_ev, float maximum_ev) -/* - Output log domain encoded data. - - Similar to OCIO lg2 AllocationTransform. - - ref[1] -*/ -{ - float in_midgrey = 0.18; - - // remove negative before log transform - color = max(0.0, color); - // avoid infinite issue with log -- ref[1] - color = (color < 0.00003051757) ? (0.00001525878 + color) : (color); - color = clamp( - log2(color / in_midgrey), - float3(minimum_ev, minimum_ev, minimum_ev), - float3(maximum_ev,maximum_ev,maximum_ev) - ); - float total_exposure = maximum_ev - minimum_ev; - - return (color - minimum_ev) / total_exposure; -} - -// exactly the same as above but I let it for reference -float3 cctf_log2_ocio_transform(float3 color) -/* - Output log domain encoded data. - - Copy of OCIO lg2 AllocationTransform with the AgX Log values. - - :param color: rgba linear color data -*/ -{ - // remove negative before log transform - color = max(0.0, color); - color = (color < 0.00003051757) ? (log2(0.00001525878 + color * 0.5)) : (log2(color)); - - // obtained via m = ocio.MatrixTransform.Fit(oldMin=[-12.47393, -12.47393, -12.47393, 0.0], oldMax=[4.026069, 4.026069, 4.026069, 1.0]) - float3x3 fitMatrix = float3x3( - 0.060606064279155415, 0.0, 0.0, - 0.0, 0.060606064279155415, 0.0, - 0.0, 0.0, 0.060606064279155415 - ); - // obtained via same as above - float fitMatrixOffset = 0.7559958033936851; - color = mul(fitMatrix, color); - color += fitMatrixOffset.xxx; - - return color; -} - -float3 cctf_decoding_sRGB_EOTF(float3 color){ - // ref[2] - return (color <= 0.04045) ? (color / 12.92) : (powsafe((color + 0.055) / 1.055, 2.4)); -} - -float3 cctf_encoding_sRGB_EOTF(float3 color){ - // ref[2] - return (color <= 0.0031308) ? (color * 12.92) : (1.055 * powsafe(color, 1/2.4) - 0.055); -} - -float3 cctf_decoding_Power_2_2(float3 color){return powsafe(color, 2.2);} - -float3 cctf_encoding_Power_2_2(float3 color){return powsafe(color, 1/2.2);} - -float3 cctf_decoding_BT_709(float3 color){return powsafe(color, 2.4);} - -float3 cctf_encoding_BT_709(float3 color){return powsafe(color, 1/2.4);} - -float3 cctf_decoding_DCIP3(float3 color){return powsafe(color, 2.6);} - -float3 cctf_encoding_DCIP3(float3 color){return powsafe(color, 1/2.6);} - -float3 cctf_encoding_BT_2020(float3 color){return (color < 0.0181) ? color * 4.5 : 1.0993 * powsafe(color, 0.45) - (1.0993 - 1);} - -float3 cctf_decoding_BT_2020(float3 color){return (color < cctf_encoding_BT_2020(0.0181)) ? color / 4.5 : powsafe((color + (1.0993 - 1)) / 1.0993, 1 / 0.45) ;} - -float3 cctf_decoding_Display_P3(float3 color){return cctf_decoding_sRGB_EOTF(color);} - -float3 cctf_encoding_Display_P3(float3 color){return cctf_encoding_sRGB_EOTF(color);} - -float3 cctf_decoding_Adobe_RGB_1998(float3 color){return powsafe(color, 2.19921875);} - -float3 cctf_encoding_Adobe_RGB_1998(float3 color){return powsafe(color, 1/2.19921875);} - - -// region WARNING code is procedurally generated - -uniform int cctf_id_Power_2_2 = 0; // Power 2.2 -uniform int cctf_id_sRGB_EOTF = 1; // sRGB EOTF -uniform int cctf_id_BT_709 = 2; // BT.709 -uniform int cctf_id_DCIP3 = 3; // DCI-P3 -uniform int cctf_id_Display_P3 = 4; // Display P3 -uniform int cctf_id_Adobe_RGB_1998 = 5; // Adobe RGB 1998 -uniform int cctf_id_BT_2020 = 6; // BT.2020 - - -float3 apply_cctf_decoding(float3 color, int cctf_id){ - if (cctf_id == cctf_id_Power_2_2 ) return cctf_decoding_Power_2_2(color); - if (cctf_id == cctf_id_sRGB_EOTF ) return cctf_decoding_sRGB_EOTF(color); - if (cctf_id == cctf_id_BT_709 ) return cctf_decoding_BT_709(color); - if (cctf_id == cctf_id_DCIP3 ) return cctf_decoding_DCIP3(color); - if (cctf_id == cctf_id_Display_P3 ) return cctf_decoding_Display_P3(color); - if (cctf_id == cctf_id_Adobe_RGB_1998 ) return cctf_decoding_Adobe_RGB_1998(color); - if (cctf_id == cctf_id_BT_2020 ) return cctf_decoding_BT_2020(color); - return color; -} - -float3 apply_cctf_encoding(float3 color, int cctf_id){ - if (cctf_id == cctf_id_Power_2_2 ) return cctf_encoding_Power_2_2(color); - if (cctf_id == cctf_id_sRGB_EOTF ) return cctf_encoding_sRGB_EOTF(color); - if (cctf_id == cctf_id_BT_709 ) return cctf_encoding_BT_709(color); - if (cctf_id == cctf_id_DCIP3 ) return cctf_encoding_DCIP3(color); - if (cctf_id == cctf_id_Display_P3 ) return cctf_encoding_Display_P3(color); - if (cctf_id == cctf_id_Adobe_RGB_1998 ) return cctf_encoding_Adobe_RGB_1998(color); - if (cctf_id == cctf_id_BT_2020 ) return cctf_encoding_BT_2020(color); - return color; -} - -/* -------------------------------------------------------------------------------- -Chromatic Adaptation Transforms --------------------------------------------------------------------------------- */ - -#define matrix_cat_XYZ_Scaling_D60_to_D65 float3x3(\ - 0.997749312, 0.0, 0.0,\ - 0.0, 1.0, 0.0,\ - 0.0, 0.0, 1.079011464\ -) -#define matrix_cat_XYZ_Scaling_D60_to_DCIP3 float3x3(\ - 0.939100313, 0.0, 0.0,\ - 0.0, 1.0, 0.0,\ - 0.0, 0.0, 0.945611705\ -) -#define matrix_cat_XYZ_Scaling_D65_to_D60 float3x3(\ - 1.002255765, 0.0, 0.0,\ - 0.0, 1.0, 0.0,\ - 0.0, 0.0, 0.926774212\ -) -#define matrix_cat_XYZ_Scaling_D65_to_DCIP3 float3x3(\ - 0.941218703, 0.0, 0.0,\ - 0.0, 1.0, 0.0,\ - 0.0, 0.0, 0.876368543\ -) -#define matrix_cat_XYZ_Scaling_DCIP3_to_D60 float3x3(\ - 1.064848969, 0.0, 0.0,\ - 0.0, 1.0, 0.0,\ - 0.0, 0.0, 1.05751652\ -) -#define matrix_cat_XYZ_Scaling_DCIP3_to_D65 float3x3(\ - 1.062452326, 0.0, 0.0,\ - 0.0, 1.0, 0.0,\ - 0.0, 0.0, 1.141072449\ -) -#define matrix_cat_Bradford_D60_to_D65 float3x3(\ - 0.987323904, -0.006062169, 0.015845876,\ - -0.007531959, 1.001832321, 0.005293338,\ - 0.00305302, -0.005064257, 1.081147527\ -) -#define matrix_cat_Bradford_D60_to_DCIP3 float3x3(\ - 0.964265012, -0.021300233, -0.002647012,\ - -0.033122492, 1.030598686, 0.000944999,\ - -0.003057139, 0.006720893, 0.941838177\ -) -#define matrix_cat_Bradford_D65_to_D60 float3x3(\ - 1.012931026, 0.006054132, -0.0148757,\ - 0.007630325, 0.998191932, -0.004999018,\ - -0.002824644, 0.004658585, 0.924961741\ -) -#define matrix_cat_Bradford_D65_to_DCIP3 float3x3(\ - 0.976578897, -0.015436265, -0.016686022,\ - -0.025689666, 1.028539168, -0.003785174,\ - -0.005705746, 0.011077866, 0.871176159\ -) -#define matrix_cat_Bradford_DCIP3_to_D60 float3x3(\ - 1.037804611, 0.021430283, 0.002895221,\ - 0.033351213, 0.971004834, -0.00088053,\ - 0.003130647, -0.006859463, 1.061769201\ -) -#define matrix_cat_Bradford_DCIP3_to_D65 float3x3(\ - 1.024496728, 0.015163541, 0.019688522,\ - 0.025612193, 0.972586306, 0.004716352,\ - 0.006384231, -0.012268083, 1.147942445\ -) -#define matrix_cat_CAT02_D60_to_D65 float3x3(\ - 0.988317991, -0.007816256, 0.016645551,\ - -0.00564353, 0.998686699, 0.00662762,\ - 0.00035077, 0.001116791, 1.077573915\ -) -#define matrix_cat_CAT02_D60_to_DCIP3 float3x3(\ - 0.979655622, -0.035093475, -0.003506859,\ - -0.024670911, 1.024631944, -0.001120007,\ - 0.000239512, -0.000975875, 0.946352523\ -) -#define matrix_cat_CAT02_D65_to_D60 float3x3(\ - 1.011870978, 0.007936977, -0.015679437,\ - 0.005720259, 1.001366784, -0.00624727,\ - -0.000335311, -0.001040394, 0.928022164\ -) -#define matrix_cat_CAT02_D65_to_DCIP3 float3x3(\ - 0.991085525, -0.027362287, -0.018395654,\ - -0.019102244, 1.025837747, -0.007053718,\ - -8.0549e-05, -0.001959887, 0.878238458\ -) -#define matrix_cat_CAT02_DCIP3_to_D60 float3x3(\ - 1.021647216, 0.034994893, 0.003827292,\ - 0.024598791, 0.976803896, 0.001247201,\ - -0.000233203, 0.00099842, 1.056688999\ -) -#define matrix_cat_CAT02_DCIP3_to_D65 float3x3(\ - 1.009516172, 0.026967753, 0.021362003,\ - 0.018799243, 0.97533018, 0.008227297,\ - 0.000134542, 0.002179032, 1.138663236\ -) -#define matrix_cat_Von_Kries_D60_to_D65 float3x3(\ - 0.995663132, -0.014998519, 0.016829124,\ - -0.001647481, 1.001234102, 0.000332195,\ - 0.0, 0.0, 1.079011464\ -) -#define matrix_cat_Von_Kries_D60_to_DCIP3 float3x3(\ - 0.9888443, -0.038575341, -0.0087295,\ - -0.004237228, 1.003172521, 0.000855893,\ - 0.0, 0.0, 0.945611705\ -) -#define matrix_cat_Von_Kries_D65_to_D60 float3x3(\ - 1.004380654, 0.015045655, -0.015669755,\ - 0.001652658, 0.998792176, -0.000333274,\ - 0.0, 0.0, 0.926774212\ -) -#define matrix_cat_Von_Kries_D65_to_DCIP3 float3x3(\ - 0.993112333, -0.023650939, -0.023572367,\ - -0.002597888, 1.001897113, 0.000525285,\ - 0.0, 0.0, 0.876368543\ -) -#define matrix_cat_Von_Kries_DCIP3_to_D60 float3x3(\ - 1.011448214, 0.038893569, 0.009302073,\ - 0.004272183, 0.997001792, -0.000862968,\ - 0.0, 0.0, 1.05751652\ -) -#define matrix_cat_Von_Kries_DCIP3_to_D65 float3x3(\ - 1.00699762, 0.023771342, 0.027071751,\ - 0.002611113, 0.998168118, -0.000528057,\ - 0.0, 0.0, 1.141072449\ -) - -uniform int catid_XYZ_Scaling = 0; -uniform int catid_Bradford = 1; -uniform int catid_CAT02 = 2; -uniform int catid_Von_Kries = 3; - -uniform int whitepointid_D60 = 0; -uniform int whitepointid_D65 = 1; -uniform int whitepointid_DCIP3 = 2; - - -float3x3 get_chromatic_adaptation_transform_matrix(int cat_id, int whitepoint_source, int whitepoint_target){ - if (cat_id == 0 && whitepoint_source == 0 && whitepoint_target == 1) return matrix_cat_XYZ_Scaling_D60_to_D65; - if (cat_id == 0 && whitepoint_source == 0 && whitepoint_target == 2) return matrix_cat_XYZ_Scaling_D60_to_DCIP3; - if (cat_id == 0 && whitepoint_source == 1 && whitepoint_target == 0) return matrix_cat_XYZ_Scaling_D65_to_D60; - if (cat_id == 0 && whitepoint_source == 1 && whitepoint_target == 2) return matrix_cat_XYZ_Scaling_D65_to_DCIP3; - if (cat_id == 0 && whitepoint_source == 2 && whitepoint_target == 0) return matrix_cat_XYZ_Scaling_DCIP3_to_D60; - if (cat_id == 0 && whitepoint_source == 2 && whitepoint_target == 1) return matrix_cat_XYZ_Scaling_DCIP3_to_D65; - if (cat_id == 1 && whitepoint_source == 0 && whitepoint_target == 1) return matrix_cat_Bradford_D60_to_D65; - if (cat_id == 1 && whitepoint_source == 0 && whitepoint_target == 2) return matrix_cat_Bradford_D60_to_DCIP3; - if (cat_id == 1 && whitepoint_source == 1 && whitepoint_target == 0) return matrix_cat_Bradford_D65_to_D60; - if (cat_id == 1 && whitepoint_source == 1 && whitepoint_target == 2) return matrix_cat_Bradford_D65_to_DCIP3; - if (cat_id == 1 && whitepoint_source == 2 && whitepoint_target == 0) return matrix_cat_Bradford_DCIP3_to_D60; - if (cat_id == 1 && whitepoint_source == 2 && whitepoint_target == 1) return matrix_cat_Bradford_DCIP3_to_D65; - if (cat_id == 2 && whitepoint_source == 0 && whitepoint_target == 1) return matrix_cat_CAT02_D60_to_D65; - if (cat_id == 2 && whitepoint_source == 0 && whitepoint_target == 2) return matrix_cat_CAT02_D60_to_DCIP3; - if (cat_id == 2 && whitepoint_source == 1 && whitepoint_target == 0) return matrix_cat_CAT02_D65_to_D60; - if (cat_id == 2 && whitepoint_source == 1 && whitepoint_target == 2) return matrix_cat_CAT02_D65_to_DCIP3; - if (cat_id == 2 && whitepoint_source == 2 && whitepoint_target == 0) return matrix_cat_CAT02_DCIP3_to_D60; - if (cat_id == 2 && whitepoint_source == 2 && whitepoint_target == 1) return matrix_cat_CAT02_DCIP3_to_D65; - if (cat_id == 3 && whitepoint_source == 0 && whitepoint_target == 1) return matrix_cat_Von_Kries_D60_to_D65; - if (cat_id == 3 && whitepoint_source == 0 && whitepoint_target == 2) return matrix_cat_Von_Kries_D60_to_DCIP3; - if (cat_id == 3 && whitepoint_source == 1 && whitepoint_target == 0) return matrix_cat_Von_Kries_D65_to_D60; - if (cat_id == 3 && whitepoint_source == 1 && whitepoint_target == 2) return matrix_cat_Von_Kries_D65_to_DCIP3; - if (cat_id == 3 && whitepoint_source == 2 && whitepoint_target == 0) return matrix_cat_Von_Kries_DCIP3_to_D60; - if (cat_id == 3 && whitepoint_source == 2 && whitepoint_target == 1) return matrix_cat_Von_Kries_DCIP3_to_D65; - return matrix_identity_3x3; -} - -/* -------------------------------------------------------------------------------- -Matrices --------------------------------------------------------------------------------- */ - -// sRGB -#define matrix_sRGB_to_XYZ float3x3(\ - 0.4124, 0.3576, 0.1805,\ - 0.2126, 0.7152, 0.0722,\ - 0.0193, 0.1192, 0.9505\ -) -#define matrix_sRGB_from_XYZ float3x3(\ - 3.2406, -1.5372, -0.4986,\ - -0.9689, 1.8758, 0.0415,\ - 0.0557, -0.204, 1.057\ -) - -// DCI-P3 -#define matrix_DCIP3_to_XYZ float3x3(\ - 0.445169816, 0.277134409, 0.17228267,\ - 0.209491678, 0.721595254, 0.068913068,\ - -0.0, 0.04706056, 0.907355394\ -) -#define matrix_DCIP3_from_XYZ float3x3(\ - 2.72539403, -1.018003006, -0.440163195,\ - -0.795168026, 1.689732055, 0.022647191,\ - 0.041241891, -0.087639019, 1.100929379\ -) - -// Display P3 -#define matrix_Display_P3_to_XYZ float3x3(\ - 0.486570949, 0.265667693, 0.198217285,\ - 0.228974564, 0.691738522, 0.079286914,\ - -0.0, 0.045113382, 1.043944369\ -) -#define matrix_Display_P3_from_XYZ float3x3(\ - 2.493496912, -0.931383618, -0.402710784,\ - -0.82948897, 1.76266406, 0.023624686,\ - 0.03584583, -0.076172389, 0.956884524\ -) - -// Adobe RGB (1998) -#define matrix_Adobe_RGB_1998_to_XYZ float3x3(\ - 0.57667, 0.18556, 0.18823,\ - 0.29734, 0.62736, 0.07529,\ - 0.02703, 0.07069, 0.99134\ -) -#define matrix_Adobe_RGB_1998_from_XYZ float3x3(\ - 2.04159, -0.56501, -0.34473,\ - -0.96924, 1.87597, 0.04156,\ - 0.01344, -0.11836, 1.01517\ -) - -// ITU-R BT.2020 -#define matrix_ITUR_BT_2020_to_XYZ float3x3(\ - 0.636958048, 0.144616904, 0.168880975,\ - 0.262700212, 0.677998072, 0.059301716,\ - 0.0, 0.028072693, 1.060985058\ -) -#define matrix_ITUR_BT_2020_from_XYZ float3x3(\ - 1.716651188, -0.355670784, -0.253366281,\ - -0.666684352, 1.616481237, 0.015768546,\ - 0.017639857, -0.042770613, 0.942103121\ -) - - -uniform int gamutid_sRGB = 0; -uniform int gamutid_DCIP3 = 1; -uniform int gamutid_Display_P3 = 2; -uniform int gamutid_Adobe_RGB_1998 = 3; -uniform int gamutid_ITUR_BT_2020 = 4; - - -float3x3 get_gamut_matrix_to_XYZ(int gamutid){ - if (gamutid == gamutid_sRGB ) return matrix_sRGB_to_XYZ; - if (gamutid == gamutid_DCIP3 ) return matrix_DCIP3_to_XYZ; - if (gamutid == gamutid_Display_P3 ) return matrix_Display_P3_to_XYZ; - if (gamutid == gamutid_Adobe_RGB_1998 ) return matrix_Adobe_RGB_1998_to_XYZ; - if (gamutid == gamutid_ITUR_BT_2020 ) return matrix_ITUR_BT_2020_to_XYZ; - return matrix_identity_3x3; -} - -float3x3 get_gamut_matrix_from_XYZ(int gamutid){ - if (gamutid == gamutid_sRGB ) return matrix_sRGB_from_XYZ; - if (gamutid == gamutid_DCIP3 ) return matrix_DCIP3_from_XYZ; - if (gamutid == gamutid_Display_P3 ) return matrix_Display_P3_from_XYZ; - if (gamutid == gamutid_Adobe_RGB_1998 ) return matrix_Adobe_RGB_1998_from_XYZ; - if (gamutid == gamutid_ITUR_BT_2020 ) return matrix_ITUR_BT_2020_from_XYZ; - return matrix_identity_3x3; -} - -/* -------------------------------------------------------------------------------- -Colorspaces --------------------------------------------------------------------------------- */ - -struct Colorspace{ - int gamut_id; - int whitepoint_id; - int cctf_id; -}; - -uniform int colorspaceid_Passthrough = 0; -uniform int colorspaceid_sRGB_Display_EOTF = 1; -uniform int colorspaceid_sRGB_Display_2_2 = 2; -uniform int colorspaceid_sRGB_Linear = 3; -uniform int colorspaceid_BT_709_Display_2_4 = 4; -uniform int colorspaceid_DCIP3_Display_2_6 = 5; -uniform int colorspaceid_DCIP3_D65_Display_2_6 = 6; -uniform int colorspaceid_DCIP3_D60_Display_2_6 = 7; -uniform int colorspaceid_Apple_Display_P3 = 8; -uniform int colorspaceid_Adobe_RGB_1998_Display = 9; -uniform int colorspaceid_BT_2020_Display_OETF = 10; -uniform int colorspaceid_BT_2020_Linear = 11; -uniform int colorspaceid_DCIP3_Linear = 12; - -Colorspace getColorspaceFromId(int colorspace_id){ - - Colorspace colorspace; - - if (colorspace_id == colorspaceid_Passthrough){ - colorspace.gamut_id = -1; - colorspace.whitepoint_id = -1; - colorspace.cctf_id = -1; - }; - if (colorspace_id == colorspaceid_sRGB_Display_EOTF){ - colorspace.gamut_id = gamutid_sRGB; - colorspace.whitepoint_id = whitepointid_D65; - colorspace.cctf_id = cctf_id_sRGB_EOTF; - }; - if (colorspace_id == colorspaceid_sRGB_Display_2_2){ - colorspace.gamut_id = gamutid_sRGB; - colorspace.whitepoint_id = whitepointid_D65; - colorspace.cctf_id = cctf_id_Power_2_2; - }; - if (colorspace_id == colorspaceid_sRGB_Linear){ - colorspace.gamut_id = gamutid_sRGB; - colorspace.whitepoint_id = whitepointid_D65; - colorspace.cctf_id = -1; - }; - if (colorspace_id == colorspaceid_BT_709_Display_2_4){ - colorspace.gamut_id = gamutid_sRGB; - colorspace.whitepoint_id = whitepointid_D65; - colorspace.cctf_id = cctf_id_BT_709; - }; - if (colorspace_id == colorspaceid_DCIP3_Display_2_6){ - colorspace.gamut_id = gamutid_DCIP3; - colorspace.whitepoint_id = whitepointid_DCIP3; - colorspace.cctf_id = cctf_id_DCIP3; - }; - if (colorspace_id == colorspaceid_DCIP3_D65_Display_2_6){ - colorspace.gamut_id = gamutid_DCIP3; - colorspace.whitepoint_id = whitepointid_D65; - colorspace.cctf_id = cctf_id_DCIP3; - }; - if (colorspace_id == colorspaceid_DCIP3_D60_Display_2_6){ - colorspace.gamut_id = gamutid_DCIP3; - colorspace.whitepoint_id = whitepointid_D60; - colorspace.cctf_id = cctf_id_DCIP3; - }; - if (colorspace_id == colorspaceid_Apple_Display_P3){ - colorspace.gamut_id = gamutid_Display_P3; - colorspace.whitepoint_id = whitepointid_DCIP3; - colorspace.cctf_id = cctf_id_Display_P3; - }; - if (colorspace_id == colorspaceid_Adobe_RGB_1998_Display){ - colorspace.gamut_id = gamutid_Adobe_RGB_1998; - colorspace.whitepoint_id = whitepointid_D65; - colorspace.cctf_id = cctf_id_Adobe_RGB_1998; - }; - if (colorspace_id == colorspaceid_BT_2020_Display_OETF){ - colorspace.gamut_id = gamutid_ITUR_BT_2020; - colorspace.whitepoint_id = whitepointid_D65; - colorspace.cctf_id = cctf_id_BT_2020; - }; - if (colorspace_id == colorspaceid_BT_2020_Linear){ - colorspace.gamut_id = gamutid_ITUR_BT_2020; - colorspace.whitepoint_id = whitepointid_D65; - colorspace.cctf_id = -1; - }; - if (colorspace_id == colorspaceid_DCIP3_Linear){ - colorspace.gamut_id = gamutid_DCIP3; - colorspace.whitepoint_id = whitepointid_DCIP3; - colorspace.cctf_id = -1; - }; - return colorspace; -} -// endregion float3 convertColorspaceToColorspace(float3 color, int sourceColorspaceId, int targetColorspaceId){ @@ -549,7 +34,14 @@ float3 convertColorspaceToColorspace(float3 color, int sourceColorspaceId, int t // apply Chromatic adaptation transform if any if (source_colorspace.whitepoint_id != target_colorspace.whitepoint_id && (source_colorspace.whitepoint_id != -1) && (target_colorspace.whitepoint_id != -1)){ - color = apply_matrix(color, get_chromatic_adaptation_transform_matrix(CAT_METHOD, source_colorspace.whitepoint_id, target_colorspace.whitepoint_id)); + color = apply_matrix( + color, + get_chromatic_adaptation_transform_matrix( + CAT_METHOD, + source_colorspace.whitepoint_id, + target_colorspace.whitepoint_id + ) + ); } if (source_colorspace.gamut_id != target_colorspace.gamut_id && (source_colorspace.gamut_id != -1) && (target_colorspace.gamut_id != -1)){ diff --git a/obs/src/python/obs_codegen/__init__.py b/obs/src/python/obs_codegen/__init__.py new file mode 100644 index 0000000..bea400b --- /dev/null +++ b/obs/src/python/obs_codegen/__init__.py @@ -0,0 +1,9 @@ +from . import c +from .generators import BaseGenerator +from .generators import LuaGenerator +from .generators import HlslGenerator +from ._colorcomponents import Whitepoint +from ._colorcomponents import Cat +from ._colorcomponents import AssemblyColorspace +from ._colorcomponents import ColorspaceGamut +from ._colorcomponents import TransferFunction diff --git a/dev/obs/obs_codegen/entitities.py b/obs/src/python/obs_codegen/_colorcomponents.py similarity index 100% rename from dev/obs/obs_codegen/entitities.py rename to obs/src/python/obs_codegen/_colorcomponents.py diff --git a/dev/obs/obs_codegen/c.py b/obs/src/python/obs_codegen/c.py similarity index 100% rename from dev/obs/obs_codegen/c.py rename to obs/src/python/obs_codegen/c.py diff --git a/obs/src/python/obs_codegen/generators/__init__.py b/obs/src/python/obs_codegen/generators/__init__.py new file mode 100644 index 0000000..8f43914 --- /dev/null +++ b/obs/src/python/obs_codegen/generators/__init__.py @@ -0,0 +1,3 @@ +from ._base import BaseGenerator +from ._lua import LuaGenerator +from ._hlsl import HlslGenerator diff --git a/dev/obs/obs_codegen/generator.py b/obs/src/python/obs_codegen/generators/_base.py similarity index 69% rename from dev/obs/obs_codegen/generator.py rename to obs/src/python/obs_codegen/generators/_base.py index f506f45..cee65f0 100644 --- a/dev/obs/obs_codegen/generator.py +++ b/obs/src/python/obs_codegen/generators/_base.py @@ -4,11 +4,11 @@ import logging from abc import abstractmethod -from .entitities import Whitepoint -from .entitities import Cat -from .entitities import AssemblyColorspace -from .entitities import ColorspaceGamut -from .entitities import TransferFunction +from obs_codegen._colorcomponents import Whitepoint +from obs_codegen._colorcomponents import Cat +from obs_codegen._colorcomponents import AssemblyColorspace +from obs_codegen._colorcomponents import ColorspaceGamut +from obs_codegen._colorcomponents import TransferFunction logger = logging.getLogger(__name__) diff --git a/dev/obs/obs_codegen/hlsl/generator.py b/obs/src/python/obs_codegen/generators/_hlsl.py similarity index 91% rename from dev/obs/obs_codegen/hlsl/generator.py rename to obs/src/python/obs_codegen/generators/_hlsl.py index a32095f..f808f1c 100644 --- a/dev/obs/obs_codegen/hlsl/generator.py +++ b/obs/src/python/obs_codegen/generators/_hlsl.py @@ -5,19 +5,18 @@ import colour from obs_codegen.c import HLSL_INDENT as INDENT -from obs_codegen.generator import BaseGenerator -from obs_codegen.entitities import Whitepoint -from obs_codegen.entitities import Cat -from obs_codegen.entitities import ColorspaceGamut -from .util import convert3x3MatrixToHlslStr -from .util import generateCommentHeader +from obs_codegen.generators import BaseGenerator +from obs_codegen._colorcomponents import Whitepoint +from obs_codegen._colorcomponents import Cat +from obs_codegen._colorcomponents import ColorspaceGamut +from obs_codegen.hlsl_utils import convert3x3MatrixToHlslStr +from obs_codegen.hlsl_utils import generateCommentHeader logger = logging.getLogger(__name__) @dataclasses.dataclass class HlslVariable: - name: str definition: str @@ -27,7 +26,6 @@ def processCat( whitepoint_target: Whitepoint, cat: Cat, ) -> HlslVariable: - matrix_cat = colour.adaptation.matrix_chromatic_adaptation_VonKries( colour.xy_to_XYZ(whitepoint_source.coordinates), colour.xy_to_XYZ(whitepoint_target.coordinates), @@ -67,10 +65,10 @@ def generateCode(self) -> str: Returns: valid HLSL code snippet """ - str_cctf = self._generateTransferFunctionBlock() - str_matrices = self._generateMatricesBlock() - str_cat = self._generateCatBlock() - str_colorspace = self._generateColorspacesBlock() + str_cctf = self.generateTransferFunctionBlock() + str_matrices = self.generateMatricesBlock() + str_cat = self.generateCatBlock() + str_colorspace = self.generateColorspacesBlock() return ( "// region WARNING code is procedurally generated\n" @@ -78,22 +76,18 @@ def generateCode(self) -> str: "// endregion\n" ) - def _generateTransferFunctionBlock(self) -> str: - + def generateTransferFunctionBlock(self) -> str: out_str = "" out_str += "\n" for transfer_function in self.transfer_functions: - out_str += f"uniform int {transfer_function.id_variable_name} = {transfer_function.id}; // {transfer_function.name}\n" for cctf_mode in ["decoding", "encoding"]: - out_str += "\n\n" out_str += f"float3 apply_cctf_{cctf_mode}(float3 color, int cctf_id){{\n" for transfer_function in self.transfer_functions: - skip = not transfer_function.has_decoding and cctf_mode == "decoding" if skip: continue @@ -113,13 +107,11 @@ def _generateTransferFunctionBlock(self) -> str: return out_str - def _generateMatricesBlock(self) -> str: - + def generateMatricesBlock(self) -> str: out_str = generateCommentHeader("Matrices") out_str += "\n" for colorspace in self.colorspaces_gamut: - out_str += processColorspaceMatrix(colorspace) + "\n" out_str += "\n" @@ -128,7 +120,6 @@ def _generateMatricesBlock(self) -> str: out_str += f"uniform int {colorspace.id_variable_name} = {colorspace.id};\n" for gamut_direction in ["to_XYZ", "from_XYZ"]: - out_str += "\n\n" out_str += f"float3x3 get_gamut_matrix_{gamut_direction}(int gamutid){{\n" @@ -143,8 +134,7 @@ def _generateMatricesBlock(self) -> str: return out_str - def _generateCatBlock(self) -> str: - + def generateCatBlock(self) -> str: out_str = generateCommentHeader("Chromatic Adaptation Transforms") out_str += "\n" @@ -155,9 +145,7 @@ def _generateCatBlock(self) -> str: cat_variable_dict = dict() for cat in self.cats: - for whitepoint_combinaison in whitepoint_combinaison_list: - whitepoint_source = whitepoint_combinaison[0] whitepoint_target = whitepoint_combinaison[1] @@ -196,8 +184,7 @@ def _generateCatBlock(self) -> str: return out_str - def _generateColorspacesBlock(self) -> str: - + def generateColorspacesBlock(self) -> str: out_str = generateCommentHeader("Colorspaces") out_str += "\n" @@ -210,7 +197,6 @@ def _generateColorspacesBlock(self) -> str: out_str += "};\n\n" for assembly_colorspace in self.colorspaces_assemblies: - out_str += f"uniform int {assembly_colorspace.id_variable_name} = {assembly_colorspace.id};\n" out_str += "\n" @@ -219,7 +205,6 @@ def _generateColorspacesBlock(self) -> str: out_str += f"\n{INDENT}Colorspace colorspace;\n\n" for assembly_colorspace in self.colorspaces_assemblies: - out_str += INDENT out_str += ( f"if (colorspace_id == {assembly_colorspace.id_variable_name}){{\n" diff --git a/dev/obs/obs_codegen/lua/generator.py b/obs/src/python/obs_codegen/generators/_lua.py similarity index 95% rename from dev/obs/obs_codegen/lua/generator.py rename to obs/src/python/obs_codegen/generators/_lua.py index 0ac363b..05a1630 100644 --- a/dev/obs/obs_codegen/lua/generator.py +++ b/obs/src/python/obs_codegen/generators/_lua.py @@ -2,7 +2,7 @@ import logging from obs_codegen.c import LUA_IDENT as INDENT -from obs_codegen.generator import BaseGenerator +from obs_codegen.generators import BaseGenerator logger = logging.getLogger(__name__) @@ -23,25 +23,21 @@ def generateCode(self) -> str: return f"{str_props}" def _generatePropertyList(self) -> str: - out_str = "" for colorspace in self.colorspaces_assemblies: - out_str += INDENT out_str += f'obs.obs_property_list_add_int(propOutputColorspace, "{colorspace.name}", {colorspace.id})\n' out_str += "\n----------\n" for colorspace in self.colorspaces_assemblies: - out_str += INDENT out_str += f'obs.obs_property_list_add_int(propInputColorspace, "{colorspace.name}", {colorspace.id})\n' out_str += "\n----------\n" for cat in self.cats: - out_str += INDENT out_str += f'obs.obs_property_list_add_int(propCatMethod, "{cat.name}", {cat.id})\n' diff --git a/dev/obs/obs_codegen/hlsl/util.py b/obs/src/python/obs_codegen/hlsl_utils.py similarity index 100% rename from dev/obs/obs_codegen/hlsl/util.py rename to obs/src/python/obs_codegen/hlsl_utils.py diff --git a/dev/obs/obs_codegen/util.py b/obs/src/python/obs_codegen/util.py similarity index 100% rename from dev/obs/obs_codegen/util.py rename to obs/src/python/obs_codegen/util.py diff --git a/obs/src/scripts/build-colorspace_core.hlsl.py b/obs/src/scripts/build-colorspace_core.hlsl.py new file mode 100644 index 0000000..47d7b7b --- /dev/null +++ b/obs/src/scripts/build-colorspace_core.hlsl.py @@ -0,0 +1,329 @@ +import dataclasses +import logging +import sys +from pathlib import Path +from typing import Type +from typing import TypeVar + +import colour + +from obs_codegen import Whitepoint +from obs_codegen import Cat +from obs_codegen import AssemblyColorspace +from obs_codegen import ColorspaceGamut +from obs_codegen import TransferFunction +from obs_codegen import BaseGenerator +from obs_codegen import HlslGenerator +from obs_codegen import LuaGenerator + +LOGGER = logging.getLogger(__name__) + + +BaseGeneratorType = TypeVar("BaseGeneratorType", bound=BaseGenerator) + + +@dataclasses.dataclass +class ColorManagementConfig: + colorspaces_gamut: list[ColorspaceGamut] + whitepoints: list[Whitepoint] + cats: list[Cat] + colorspaces_assemblies: list[AssemblyColorspace] + transfer_functions: list[TransferFunction] + + def use_with_generator( + self, generator_class: Type[BaseGeneratorType] + ) -> BaseGeneratorType: + instance = generator_class( + colorspaces_gamut=self.colorspaces_gamut, + whitepoints=self.whitepoints, + cats=self.cats, + colorspaces_assemblies=self.colorspaces_assemblies, + transfer_functions=self.transfer_functions, + ) + return instance + + +def get_config(): + illuminant1931: dict = colour.CCS_ILLUMINANTS["CIE 1931 2 Degree Standard Observer"] + + transfer_function_power_2_2 = TransferFunction("Power 2.2") + transfer_function_sRGB_EOTF = TransferFunction("sRGB EOTF") + transfer_function_BT709 = TransferFunction("BT.709") + transfer_function_DCIP3 = TransferFunction("DCI-P3") + transfer_function_Display_P3 = TransferFunction("Display P3") + transfer_function_Adobe_RGB_1998 = TransferFunction("Adobe RGB 1998") + transfer_function_BT2020 = TransferFunction("BT.2020") + transfer_function_FLog = TransferFunction("FLog") + transfer_function_FLog2 = TransferFunction("FLog2") + transfer_function_NLog = TransferFunction("NLog") + transfer_function_SLog = TransferFunction("SLog") + transfer_function_SLog2 = TransferFunction("SLog2") + transfer_function_SLog3 = TransferFunction("SLog3") + transfer_function_VLog = TransferFunction("VLog") + + transfer_function_list = [ + transfer_function_power_2_2, + transfer_function_sRGB_EOTF, + transfer_function_BT709, + transfer_function_DCIP3, + transfer_function_Display_P3, + transfer_function_Adobe_RGB_1998, + transfer_function_BT2020, + transfer_function_FLog, + transfer_function_FLog2, + transfer_function_NLog, + transfer_function_SLog, + transfer_function_SLog2, + transfer_function_SLog3, + transfer_function_VLog, + ] + + # fmt: off + colorspace_gamut_sRGB = ColorspaceGamut.fromColourColorspaceName("sRGB") + colorspace_gamut_DCIP3 = ColorspaceGamut.fromColourColorspaceName("DCI-P3") + colorspace_gamut_Display_P3 = ColorspaceGamut.fromColourColorspaceName("Display P3") + colorspace_gamut_Adobe_RGB_1998 = ColorspaceGamut.fromColourColorspaceName("Adobe RGB (1998)") + colorspace_gamut_ITUR_BT_2020 = ColorspaceGamut.fromColourColorspaceName("ITU-R BT.2020") + colorspace_gamut_Cinema_Gamut = ColorspaceGamut.fromColourColorspaceName("Cinema Gamut") + colorspace_gamut_S_Gamut = ColorspaceGamut.fromColourColorspaceName("S-Gamut") + colorspace_gamut_S_Gamut3_Cine = ColorspaceGamut.fromColourColorspaceName("S-Gamut3.Cine") + colorspace_gamut_V_Gamut = ColorspaceGamut.fromColourColorspaceName("V-Gamut") + colorspace_gamut_list = [ + colorspace_gamut_sRGB, + colorspace_gamut_DCIP3, + colorspace_gamut_Display_P3, + colorspace_gamut_Adobe_RGB_1998, + colorspace_gamut_ITUR_BT_2020, + colorspace_gamut_Cinema_Gamut, + colorspace_gamut_S_Gamut, + colorspace_gamut_S_Gamut3_Cine, + colorspace_gamut_V_Gamut, + ] + # fmt: on + + whitepoint_D60 = Whitepoint("D60", illuminant1931["D60"]) + whitepoint_D65 = Whitepoint("D65", illuminant1931["D65"]) + whitepoint_DCIP3 = Whitepoint("DCI-P3", illuminant1931["DCI-P3"]) + whitepoint_list = [whitepoint_D60, whitepoint_D65, whitepoint_DCIP3] + + assembly_colorspace_Passthrough = AssemblyColorspace( + "Passthrough", + None, + None, + None, + ) + assembly_colorspace_sRGB_Display_EOTF = AssemblyColorspace( + "sRGB Display (EOTF)", + colorspace_gamut_sRGB, + whitepoint_D65, + transfer_function_sRGB_EOTF, + ) + assembly_colorspace_sRGB_Display_2_2 = AssemblyColorspace( + "sRGB Display (2.2)", + colorspace_gamut_sRGB, + whitepoint_D65, + transfer_function_power_2_2, + ) + assembly_colorspace_sRGB_Linear = AssemblyColorspace( + "sRGB Linear", + colorspace_gamut_sRGB, + whitepoint_D65, + None, + ) + assembly_colorspace_BT_709_Display_2_4 = AssemblyColorspace( + "BT.709 Display (2.4)", + colorspace_gamut_sRGB, + whitepoint_D65, + transfer_function_BT709, + ) + assembly_colorspace_DCIP3_Display_2_6 = AssemblyColorspace( + "DCI-P3 Display (2.6)", + colorspace_gamut_DCIP3, + whitepoint_DCIP3, + transfer_function_DCIP3, + ) + assembly_colorspace_DCIP3_D65_Display_2_6 = AssemblyColorspace( + "DCI-P3 D65 Display (2.6)", + colorspace_gamut_DCIP3, + whitepoint_D65, + transfer_function_DCIP3, + ) + assembly_colorspace_DCIP3_D60_Display_2_6 = AssemblyColorspace( + "DCI-P3 D60 Display (2.6)", + colorspace_gamut_DCIP3, + whitepoint_D60, + transfer_function_DCIP3, + ) + assembly_colorspace_Apple_Display_P3 = AssemblyColorspace( + "Apple Display P3", + colorspace_gamut_Display_P3, + whitepoint_DCIP3, + transfer_function_Display_P3, + ) + assembly_colorspace_Adobe_RGB_1998_Display = AssemblyColorspace( + "Adobe RGB 1998 Display", + colorspace_gamut_Adobe_RGB_1998, + whitepoint_D65, + transfer_function_Adobe_RGB_1998, + ) + assembly_colorspace_BT_2020_Display_OETF = AssemblyColorspace( + "BT.2020 Display (OETF)", + colorspace_gamut_ITUR_BT_2020, + whitepoint_D65, + transfer_function_BT2020, + ) + assembly_colorspace_BT_2020_Linear = AssemblyColorspace( + "BT.2020 Linear", + colorspace_gamut_ITUR_BT_2020, + whitepoint_D65, + None, + ) + assembly_colorspace_DCIP3_Linear = AssemblyColorspace( + "DCI-P3 Linear", + colorspace_gamut_DCIP3, + whitepoint_DCIP3, + None, + ) + assembly_colorspace_Cinema_Gamut = AssemblyColorspace( + "Cinema Gamut (Canon)", + colorspace_gamut_Cinema_Gamut, + whitepoint_D65, + None, + ) + assembly_colorspace_F_Gamut_FLog = AssemblyColorspace( + "F-Gamut FLog (Fujifilm)", + colorspace_gamut_ITUR_BT_2020, + whitepoint_D65, + transfer_function_FLog, + ) + assembly_colorspace_F_Gamut_FLog2 = AssemblyColorspace( + "F-Gamut FLog2 (Fujifilm)", + colorspace_gamut_ITUR_BT_2020, + whitepoint_D65, + transfer_function_FLog2, + ) + assembly_colorspace_N_Gamut = AssemblyColorspace( + "N-Gamut (Nikon)", + colorspace_gamut_ITUR_BT_2020, + whitepoint_D65, + transfer_function_NLog, + ) + assembly_colorspace_S_Gamut = AssemblyColorspace( + "S-Gamut (Sony)", + colorspace_gamut_S_Gamut, + whitepoint_D65, + transfer_function_SLog, + ) + assembly_colorspace_S_Gamut2 = AssemblyColorspace( + "S-Gamut2 (Sony)", + colorspace_gamut_S_Gamut, + whitepoint_D65, + transfer_function_SLog2, + ) + assembly_colorspace_S_Gamut3 = AssemblyColorspace( + "S-Gamut3 (Sony)", + colorspace_gamut_S_Gamut, + whitepoint_D65, + transfer_function_SLog3, + ) + assembly_colorspace_S_Gamut3_Cine = AssemblyColorspace( + "S-Gamut3.Cine (Sony)", + colorspace_gamut_S_Gamut3_Cine, + whitepoint_D65, + transfer_function_SLog3, + ) + assembly_colorspace_V_Gamut = AssemblyColorspace( + "V-Gamut (Panasonic)", + colorspace_gamut_V_Gamut, + whitepoint_D65, + transfer_function_VLog, + ) + assembly_colorspace_list = [ + assembly_colorspace_Passthrough, + assembly_colorspace_sRGB_Display_EOTF, + assembly_colorspace_sRGB_Display_2_2, + assembly_colorspace_sRGB_Linear, + assembly_colorspace_BT_709_Display_2_4, + assembly_colorspace_DCIP3_Display_2_6, + assembly_colorspace_DCIP3_D65_Display_2_6, + assembly_colorspace_DCIP3_D60_Display_2_6, + assembly_colorspace_Apple_Display_P3, + assembly_colorspace_Adobe_RGB_1998_Display, + assembly_colorspace_BT_2020_Display_OETF, + assembly_colorspace_BT_2020_Linear, + assembly_colorspace_DCIP3_Linear, + assembly_colorspace_Cinema_Gamut, + assembly_colorspace_F_Gamut_FLog, + assembly_colorspace_F_Gamut_FLog2, + assembly_colorspace_N_Gamut, + assembly_colorspace_S_Gamut, + assembly_colorspace_S_Gamut2, + assembly_colorspace_S_Gamut3, + assembly_colorspace_S_Gamut3_Cine, + assembly_colorspace_V_Gamut, + ] + + config = ColorManagementConfig( + colorspaces_gamut=colorspace_gamut_list, + whitepoints=whitepoint_list, + cats=[ + Cat("XYZ Scaling"), + Cat("Bradford"), + Cat("CAT02"), + Cat("Von Kries"), + ], + colorspaces_assemblies=assembly_colorspace_list, + transfer_functions=transfer_function_list, + ) + return config + + +class BuildPaths: + root = Path(__file__).parent.parent.parent / "obs-script" + assert root.exists() + + hlsl_colorscience_root = root / "colorscience" + assert hlsl_colorscience_root.exists() + + hlsl_colorscience_cctfa = hlsl_colorscience_root / "cctf-auto.hlsl" + hlsl_colorscience_colorspace = hlsl_colorscience_root / "colorspace.hlsl" + hlsl_colorscience_gamut = hlsl_colorscience_root / "gamut.hlsl" + hlsl_colorscience_cat = hlsl_colorscience_root / "cat.hlsl" + + +def build(): + LOGGER.info("started build.") + + colormanagement_config = get_config() + + generator_hlsl = colormanagement_config.use_with_generator(HlslGenerator) + + hlsl_code_mapping = { + BuildPaths.hlsl_colorscience_cctfa: generator_hlsl.generateTransferFunctionBlock(), + BuildPaths.hlsl_colorscience_cat: generator_hlsl.generateCatBlock(), + BuildPaths.hlsl_colorscience_gamut: generator_hlsl.generateMatricesBlock(), + BuildPaths.hlsl_colorscience_colorspace: generator_hlsl.generateColorspacesBlock(), + } + + for target_path, hlsl_code in hlsl_code_mapping.items(): + hlsl_code = ( + "// code generated by automatic build; do not manually edit\n" + hlsl_code + ) + LOGGER.info(f"writting <{target_path}> ...") + target_path.write_text(hlsl_code) + + LOGGER.info("generating lua code ...") + generator_lua = colormanagement_config.use_with_generator(LuaGenerator) + lua_code = generator_lua.generateCode() + print(lua_code) + LOGGER.info("finished build.") + + +if __name__ == "__main__": + logging.basicConfig( + level=logging.DEBUG, + format="{levelname: <7} | {asctime} [{name}] {message}", + style="{", + stream=sys.stdout, + ) + build() diff --git a/pyproject.toml b/pyproject.toml index 05395f0..490b51e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,13 +1,13 @@ [tool.poetry] name = "AgXc" -version = "0.5.3" +version = "0.6.0" description = "Fork of Troy.S AgX, a display rendering transform available via OCIO and more." authors = ["Liam Collod "] readme = "README.md" [tool.poetry.dependencies] python = ">=3.9,<3.11" -colour = { git = "https://github.com/colour-science/colour.git", branch = "develop" } +colour-science = { git = "https://github.com/colour-science/colour.git", tag = "v0.4.3" } numpy = "*" opencolorio = "2.1.*"