nob_luma_chroma_forward (Compatible with IFFS 2026.2.2 and up)
This Matchbox shader performs forward luma/chroma (or RGB/XYZ) conversions for storage and compression.
The available operations performed depend on the exact colour-model of the source image, selected by [Source] in the column of the same name:
[Linear XYZ]: input is treated as display-referred linear CIE XYZ with absolute chromatic destination white point - transfer characteristic, all colourmatrices and range are selectable;
[Encoded]: the input is already encoded to destination colour primaries and transfer characteristic - only non-constant-luminance YCbCr colourmatrices and range are selectable;
[Luma/Chroma]: indicates the input is in luma-chroma representation itself - no further colour transformation is applicable.
Note that chroma subsampling is available for all source colour-models.
[Colour Primaries] then defines the colourspace to transform to if [Source] is [Linear XYZ], or serves as an indicator set to [Encoded]. Its options conform to the code-points defined in ITU-T H.273.
[P3] refers to DCI white, which in Flame 2026 is no longer accommodated by the default viewing transformations.
In the [Characteristics] column, [Transfer Function] denotes the encoding to apply for [Linear XYZ] sources, also conforming to the code-points defined in ITU-T H.273 where applicable.
Note that:
[Rec.709] represents the traditional piecewise linear transfer characteristic;
[Rec.1886] is a pure power function with exponent 1/2.4;
as is [Gamma] for the customizable exponent 1/[Gamma];
for [PQ], this shader expects the input to linearly represent the achromatic luminance of 100 nits with Y=1 (this is consistent with Flame’s own handling of such formats), instead of mapping Y=1 to the reference white (as per ITU-T H.273); and
the luminance of the reference white for [HLG] can be chosen by the parameter [L_W] (in nits), analogous to [PQ] expecting the white to be encoded by the linear value of [L_W]/100.
Likewise, [Colourmatrix] options map to their respective definitions of ITU-T H.273.
Note that the selection is dependent on [Source] and may change with modifications to the latter.
[Full Range] toggles usage of data or SMPTE video levels. The specific range hereby depends on the target bit depth, which is set via [Bit Depth].
Only formats with an equal number of bits per component for luma and chroma planes are supported by this shader (as is Flame limited to writing such formats).
Finally, the [Chroma Subsampling] column provides parameters controlling just that.
[Type] defines the horizontal and vertical downsampling ratios, supporting the three formats defined by ITU-T H.273: [4:2:0], [4:2:2] & [4:4:4].
For [4:2:0], [Chromaloc] provides a subset of the sampling position values defined by the aforementioned specification, supporting: [0 (left)], [1 (center)] & [2 (top-left)]. The locations are to be understood as relative to the centre of the 2×2 luma sample rectangle of the full-resolution plane, offset in steps of half a unit.
Note that in accordance with the specification, [4:2:2] is always sampled as 0 (left).
The filtering kernel for downsampling can be chosen by [Filter], supporting area-aware [Box] and [Bilinear] methods.
This shader does a rudimentary conformance check on the chosen parameters, and if a dubious configuration is detected, overlays the output with a repeating pattern of coloured exclamation marks.
However, This behaviour can be overridden by toggling [Allow Non-Conformance] in the [Advanced] column. If active, no such pattern is ever produced no matter the configuration.
It is recommended to use this option cautiously, the shader indeed always works precisely as formally requested - and every permutation of available input parameters is mathematically realizable. It never falls back to a ‘closest sensible’ state.
Configurations raising this safeguard are:
narrow-gamut primaries ([Rec.709], [Rec.601 (PAL)] or [Rec.601 (NTSC)]) with an HDR [Transfer Function] ([PQ] or [HLG]),
primaries other than [XYZ] with [SMPTE ST 428-1] [Transfer Function],
mis-matching primaries with native colourmatrices,
primaries other than [Rec.2020] with [ICtCp (PQ)], [ICtCp (HLG)] or [IPT-C2] [Colourmatrix],
[Transfer Function] other than [PQ] with [ICtCp (PQ)], or [IPT-C2] [Colourmatrix],
[Transfer Function] other than [HLG] with the [ICtCp (HLG)] [Colourmatrix],
[Identity] [Colourmatrix] with chroma subsampling [Type] other than [4:4:4].
This feature does NOT protect from mis-matching the indicated input format with the actual input, and no such information is inferred from colourspace tags. Neither does it detect errors in prior colour-management or tagging.
All operations are performed unclamped; specifically, the transfer characteristics are mirrored for negative input values.
For [Colourmatrix] equal to [Identity], the output maps RGB/XYZ planes to RGB/XYZ output; otherwise R stores Cr/Cp/P, G stores Y/I and B stores Cb/Ct/T (depending on the luma/chroma format).
This might be uncommon a layout for planes, yet it translates better to perceptual contexts where the respective channels are most strongly correlated with R, G ∧ B.
For inspecting these encoded values, the Flame viewer and scopes colour management can be set to Bypass, allowing to probe raw values with the Colour Sampler, or display luma/chroma Waveform-Parades as RGB. To display only select planes, use Flame’s View Options, particularly Channels with Source- or Display Isolation.
Moreover, for further processing, FFmpeg (among others) internally maps planar RGB formats to GBR, in turn producing the more common GBR/YZX/YCbCr/ICtCp/IPT layouts.
The downsampled chroma planes are stored top-left justified, padded with neutral values. In case of [Colourmatrix] equal to [Identity], R & B / X & Z planes are padded to range-adjusted black (though if not overridden, the latter trips the conformance safeguard).
Note that if [Source] is [Luma/Chroma], padding is always done analogous to luma/chroma formats instead of RGB/XYZ.
For maximum flexibility (within the context of this shader), using a [Linear XYZ] source is preferable.
Such can be provided by Flame in for example an ACES workflow via a Colour Mgmt node set to {Colour Transform} ({Custom} active):
the first entry removing the working Colour Space, via {Type}: {OCIO → Colour Spaces} and selecting the correct space in {Transform}, do not toggle on {Invert}; and
the second entry being the RRT, via {Type}: {OCIO → View Transforms} and {Transform} set to the desired RRT instance, do not invert this either.
For context: in this case, the colour-space-journey goes from the working space to ACES2065-1 - both scene-referred with the first entry, and from scene-referred ACES2065-1 to display-referred CIE-XYZ with the second one.
The result of this shader is designed to be stored entirely unprocessed, save for the rounding from the working 32fp precision down to the desired integer bit-depth (matching the setting of [Bit Depth]) via the Media Hub export or Write File node in Batch.
Because for most use-cases, lossy compression is to be applied externally, a mathematically lossless intermediate format is desirable; such as a packed DPX sequence, or RAW/R210 QuickTime formats (for 8/10 bit, respectively).
Since the resulting video stream encodes a potentially chroma-subsampled luma/format in an RGB image container, the tool importing it is to be manually set up in order to correctly interpret it.
As an example, taking the default configuration of this shader, for FFmpeg the 10-bit 4:2:0 encode (read as ‘gbrp10le’ pixel format) can be cast to the actual ‘yuv420p10’ data using the following video filtergraph (‘-vf’): ‘split=2[orig][tmp];[tmp]crop=in_w/2:in_h/2:0:0[crop];[orig][crop]mergeplanes=0x001112:yuv420p10’.
From there, it behaves like usual 4:2:0 content and can be directly encoded to (for example) H.265 using libx265.
The use of the ‘-noautoscale’ option before the filtergraph is encouraged, since for mismatching formats it leads to FFmpeg throwing an error instead of silently (for default ‘loglevel’) reformatting the source at a loss of image information.
The appropriate colour tags can be set as options to ‘-x265-params’, in this case: ‘range=limited:colorprim=bt2020:transfer=bt2020-10:colormatrix=bt2020nc:chromaloc=2’.
The full FFmpeg prompt can then be customized further.
Note that this shader does not perform any image scaling or reformatting (other than chroma subsampling), so the operation may be incorrect if the result image format does not match the input image format.
It is recommended to leave the [Output Resolution] as [Same As Input 1], and instead of tagging colourspaces, treat the result as non-colourimetric data, examinable via the methods described above.
This shader is licensed under the terms of the MIT license.
For questions contact:
nobbl211 _at_ gmail.com
Version notes
Initial publish
Older versions that shader
Something wrong with this page or the download?
Contact the site custodians via email, if:
- This shader is obviously incomplete (missing files, not loading) etc.
- This shader violates IP rules (is pirated) or contains harmful content
- You are having problems with the shader installer (INSTALL.command) or the download.
How to get help with this particular shader
Sadly, the custodians likely will not be able to explain to you how a shader works or debug its code, or fix it for you. That is the (volountary) role of the shader author.
If the shader does not work on your system or you have questions about it - read the shader description, and try to find the email address of the shader author. Contact them for any issues – letting them know whether you are on Mac or Linux, what version of IFFS you are running etc. will likely help. Be kind and respectful. If you can't get hold of the author - you can try asking in the Logik forum at logik.tv and ask whether anyone could help you debug a particular shader not working.