Log in

View Full Version : SafeColorLimiter


Pages : [1] 2

FranceBB
25th September 2020, 08:13
Hi there folks,
the idea is to automatize clipping to get a broadcast safe output in Limited TV Range (0.0-0.7V).

8bit sources will be limited to 16 - 235 luma and 16 - 240 chroma
10bit sources will be limited to 64 - 940 luma and 64 - 960 chroma
12bit sources will be limited to 256 - 3760 luma and 256 - 3840 chroma
14bit sources will be limited to 1024 - 15040 luma and 1024 - 15360 chroma
16bit sources will be limited to 4096 - 60160 luma and 4096 - 61440 chroma
32bit sources will be limited to 16/255.0 - 235/255.0 luma and -112/255.0 - -112/255.0 - 112/255.0 chroma

It supports y8, y10, y12, y14, y16, y32, yv12, YUY2, yv16, yv24 and YUV 4:2:0 planar, YUV 4:1:1 planar, YUV 4:2:2 planar, YUV 4:4:4 planar 10-12-14-16-32bit, including those with alpha channel.
If the input is in RGB, it will just return the input untouched.


Script: https://github.com/FranceBB/SafeColorLimiter

Alexkral
25th September 2020, 08:35
passthrough ? out=my_catched_out : out=my_out

FranceBB
25th September 2020, 09:05
passthrough ? out=my_catched_out : out=my_out

Ok, so "?" already evaluates if it's true, but there's still the problem with the line above and the 32bit float individuation.
Besides, I was trying something like:

ColorBars(848, 480, pixel_type="YV24")

ConvertBits(32)

Limiter(min_luma=0.0625, max_luma=0.91796875, min_chroma=0.0625, max_chroma=0.91796875)

but I get a completely wrong result:

https://i.imgur.com/e9rXqL3.png

which is weird, considering that in 32bit float min_luma is supposed to be 16/256 which is 0.0625 and max_luma is supposed to be 235/256 which is 0.91796875

Alexkral
25th September 2020, 09:32
Actually it is "value/255.0 for Y (luma) channel and (value-128)/255.0 for U/V chroma channels" according to this (http://avisynth.nl/index.php/Limiter) when using autoscale = true

FranceBB
25th September 2020, 09:52
Actually it is "value/255.0 for Y (luma) channel and (value-128)/255.0 for U/V chroma channels"

Ah, I see, I'm an idiot, so these are the correct values:

Limiter(min_luma=0.0627450980392157, max_luma=0.9215686274509804, min_chroma=-0.4392156862745098, max_chroma=0.4196078431372549)

In fact I get the right output:

https://i.imgur.com/npFWdqv.png

however that's an approximation; when I try to use the right float values through mathematical operations in Avisynth I get a completely black output:


ColorBars(848, 480, pixel_type="YV12")
ConvertBits(32)

min_luma_float=16/255
max_luma_float=235/255
min_chroma_float=-112/255
max_chroma_float=107/255


Limiter(min_luma=min_luma_float, max_luma=max_luma_float, min_chroma=min_chroma_float, max_chroma=max_chroma_float)

StvG
25th September 2020, 12:27
ColorBars(848, 480, pixel_type="yuv420ps")

min_luma_float=16/255.0
max_luma_float=235/255.0
min_chroma_float=-112/255.0
max_chroma_float=112/255.0


Limiter(min_luma=min_luma_float, max_luma=max_luma_float, min_chroma=min_chroma_float, max_chroma=max_chroma_float)

Or you can just do:
ColorBars(848, 480, pixel_type="yuv420ps")

Limiter(paramscale=true)
There is error in the wiki (http://avisynth.nl/index.php/Limiter). The last parameter is paramscale not autoscale.

FranceBB
25th September 2020, 13:13
Ah! Ok, thanks, I edited it.
I'll edit the wiki later as well, thanks.
So that's why the autoscale wasn't working, it's actually called paramscale.

EDIT: Fixed error in the wiki by swapping "autoscale" with "paramscale"

Thanks!

StvG
25th September 2020, 13:51
Btw here (https://github.com/FranceBB/FranceBB_Sample-Avisynth-Script/blob/master/TvRange%20Limiter%20Luma-Chroma.avs#L20) should be 112/255.0 ((240-128)/255.0).

poisondeathray
25th September 2020, 14:00
The >8bit chroma values for limited range should not be the same as Y
10bit CbCr 64-960
12bit CbCr 256-3840
14bit CbCr 1024-15360
16bit CbCr 4096-61440
32bit CbCr 0.0625-0.9375

StvG
25th September 2020, 14:05
Right, max_chroma=240d.
I didn't take a look at the other bit depths than float.

Edit:
...
32bit CbCr 0.0625-0.9375
0.0627-0.9412 (for chroma range 0..1)

Cary Knoop
25th September 2020, 15:52
Almost all software treats the visible range for floats between 0.0 and 1.0. Both limited and full range gets mapped onto this interval.
WTW and BTB are not clipped but exist outside those values.

FranceBB
26th September 2020, 17:40
The >8bit chroma values for limited range should not be the same as Y
10bit CbCr 64-960
12bit CbCr 256-3840
14bit CbCr 1024-15360
16bit CbCr 4096-61440
32bit CbCr 0.0625-0.9375

Got it. I changed them, thanks.

feisty2
27th September 2020, 08:50
there's no such thing as fp32 safe color, same as there's no limited range RGB.
YCbCr is always defined on [0.0, 1.0] for Y and [-1.0, 1.0] for CbCr for fp32
it is conceptually incorrect to assume there's a "hard" range for floating point samples

StainlessS
27th September 2020, 11:10
...
YCbCr is always defined on [0.0, 1.0] for Y and [-1.0, 1.0] for CbCr for fp32
...
Is that a mistake feisty ?

https://forum.doom9.org/showthread.php?p=1843058#post1843058
By Pinterf - release of AviSynthPlus-MT-r2693.exe, (Quoting from Locked thread dont work any more [if it ever did])

- Changed (finally): 32bit float YUV colorspaces: zero centered chroma channels.
U and V channels are now -0.5..+0.5 (if converted to full scale before) instead of 0..1
Note: filters that relied on having the U and V channel center as 0.5 will fail.
Why: the old UV 0..1 range was a very-very early decision in the high-bitdepth transition project. Also it is now
compatible with z_XXXXX resizers (zimg image library, external plugin at the moment).
- New function: bool IsFloatUvZeroBased()
For plugin or script writers who want to be compatible with pre r2672 Avisynth+ float YUV format:
Check function availablity with FunctionExists("IsFloatUvZeroBased").
When the function does not exists, the center value of 32 bit float U and V channel is 0.5
When IsFloatUvZeroBased function exists, it will return true (always for official releases) if U and V is 0 based (+/-0.5)
- Fix: RGB64 Turnleft/Turnright (which are also used in RGB64 Resizers)
- Fix: Rare crash in FrameRegistry
- Enhanced: Allow ConvertToRGB24-32-48-64 functions for any source bit depths
- Enhanced: ConvertBits: allow fulls-fulld combinations when either clip is 32bits
E.g. after a 8->32 bit fulls=false fulld=true:
Y: 16..235 -> 0..1
U/V: 16..240 -> -0.5..+0.5

feisty2
27th September 2020, 11:32
Is that a mistake feisty ?

https://forum.doom9.org/showthread.php?p=1843058#post1843058
By Pinterf - release of AviSynthPlus-MT-r2693.exe, (Quoting from Locked thread dont work any more [if it ever did])

- Changed (finally): 32bit float YUV colorspaces: zero centered chroma channels.
U and V channels are now -0.5..+0.5 (if converted to full scale before) instead of 0..1
Note: filters that relied on having the U and V channel center as 0.5 will fail.
Why: the old UV 0..1 range was a very-very early decision in the high-bitdepth transition project. Also it is now
compatible with z_XXXXX resizers (zimg image library, external plugin at the moment).
- New function: bool IsFloatUvZeroBased()
For plugin or script writers who want to be compatible with pre r2672 Avisynth+ float YUV format:
Check function availablity with FunctionExists("IsFloatUvZeroBased").
When the function does not exists, the center value of 32 bit float U and V channel is 0.5
When IsFloatUvZeroBased function exists, it will return true (always for official releases) if U and V is 0 based (+/-0.5)
- Fix: RGB64 Turnleft/Turnright (which are also used in RGB64 Resizers)
- Fix: Rare crash in FrameRegistry
- Enhanced: Allow ConvertToRGB24-32-48-64 functions for any source bit depths
- Enhanced: ConvertBits: allow fulls-fulld combinations when either clip is 32bits
E.g. after a 8->32 bit fulls=false fulld=true:
Y: 16..235 -> 0..1
U/V: 16..240 -> -0.5..+0.5


that kinda depends on how the conversion (to RGB) formula is defined.
for this particular formula listed on avisynth.nl (http://avisynth.nl/index.php/Colorimetry)

R = Y + Cr*(1-Kr)
G = Y - Cb*(1-Kb)*Kb/Kg - Cr*(1-Kr)*Kr/Kg
B = Y + Cb*(1-Kb)

Cb and Cr are defined on [-1, 1], you would need to scale some coefficients in the above formula for [-0.5, 0.5] chroma

StainlessS
27th September 2020, 11:48
OK, thanks, F2.

FranceBB
12th October 2020, 14:48
New version, see first post or: https://github.com/FranceBB/SafeColorLimiter

Update:

- Code cleanup.
- Moved project to Github.
- Introduced support to Y8, Y10, Y12, Y14, Y16, Y32 and YUV411
- Fixed a bug that would prevent the script from returning a clip when the input had an Alpha Channel

feisty2
12th October 2020, 17:11
You should really remove all that fp32 safe color nonsense before someone stupid had the chance to actually use this incorrect "feature"

Cary Knoop
12th October 2020, 17:17
You should really remove all that fp32 safe color nonsense before someone stupid had the chance to actually use this incorrect "feature"
^This.

Floats are levels agnostic!

poisondeathray
12th October 2020, 17:32
there's no limited range RGB.

There is such a thing as "limited range RGB" . It's also known as "studio range RGB" . In 8bit RGB , 16-235 is black to white (sRGB or "computer RGB" is 0-255 black to white in 8bit, it's far more common) . Limited range RGB is used in r103 compliance checks for broadcast, and some NLE's like vegas use studio range RGB .

But it usually makes more sense to limit at the end , not intermediate float processing; and you usually don't deliver a float format in the first place. (common exception would be intermediate stages for production, such as EXR for VFX ). I don't see a usage case where it would be used in float, so it probably is a good idea to remove it


For this filter - limiting the min/max limits does not make something necessarily "broadcast safe" . Many YUV values "map" to illegal broadcast values that lie in the middle of the Y,U,V ranges . So the name for the filter is a bit of a misnomer. But typically you're allowed <1% illegal values in scenarios like r103

feisty2
12th October 2020, 17:56
I'm 99.9% sure that the so called studio range RGB is nothing but a mistake made by unprofessional engineers in the earlier days, because:
a) no television system transmits video in RGB space, so it makes no sense to preserve some "headroom" from the 8-bit range for some metadata that does not exist in the first place.
b) YUV<->RGB conversions are ALWAYS defined on full range RGB, this limited range RGB could not be properly displayed (without some non-standard scaling applied first), or properly converted to YUV by any standard. it's an abomination

poisondeathray
12th October 2020, 18:14
I'm 99.9% sure that the so called studio range RGB is nothing but a mistake made by unprofessional engineers in the earlier days, because:
a) no television system transmits video in RGB space, so it makes no sense to preserve some "headroom" from the 8-bit range for some metadata that does not exist in the first place.
b) YUV<->RGB conversions are ALWAYS defined on full range RGB, this limited range RGB could not be properly displayed (without some non-standard scaling applied first), or properly converted to YUV by any standard. it's an abomination

Maybe - but these standards exist, you should be aware of them, and we have to live with it because it's still used today. A lot of it is historical, where they had to deal with broadcast compromises with bandwidth and equipment issues

For broadcast, the transmission is not in YUV, but the display is not in YUV either. A normal HDTV in your living room uses limited range RGB by default. A comptuer display/montior uses sRGB, no surprise, so computer range YUV<=>RGB equations are typically used in the latter. But not in the former

YUV<=> RGB conversions have a "full" and "limited" parameter, correct ?

When you use "full" range equations, that produces limited range RGB - that is (almost) studio range RGB (there is a slight offset to actual "studio RGB" , they are not exactly equivalent), but range is the same.

Pros/cons - there is no range contrast expansion in the full range equations - it's 1:1 mapping 0-255 to 0-255. So in some ways it's better, in others it's worse. (Any range scaling is technically worse)

This is how broadcast checks are done for r103 ; they specify using full range equations for the RGB check (where <1% illegal is ok) , and that is "limited range RGB"

feisty2
12th October 2020, 18:43
For broadcast, the transmission is not in YUV, but the display is not in YUV either.

I'm not sure what you meant by "transmissions not in YUV", display is always in RGB, it's the only colorspace (or should I say type of colorspaces) that directly corresponds to how display devices work in the physical world


YUV<=> RGB conversions have a "full" and "limited" parameter, correct ?

there is no mentioning of limited range RGB anywhere in Rec.601 (https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf). In fact, the quantization equations on page 4 already suggest that RGB must be full range, so E'y, E'cb and E'cr would also be range full as appeared in the equations. If certain programs support conversions between limited range RGB and YUV, it's a non-standard support for an illegal format.

A normal HDTV in your living room uses limited range RGB by default.
I don't know about this and I don't care, no one of my generation watches TV anyways

poisondeathray
12th October 2020, 18:59
I'm not sure what you meant by "transmissions not in YUV", display is always in RGB, it's the only colorspace (or should I say type of colorspaces) that directly corresponds how display devices work in the physical world


Sorry typo

That's correct. Transmission in YUV, display in RGB. That's the reason for the limited range RGB check

Your TV (if you had one...) uses limited range RGB.

Your graphics card should have a toggle for limited and full range RGB output - why ? Because a TV uses limited range RGB



there is no mentioning of limited range RGB anywhere in Rec.601 (https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf). In fact, the quantization equations on page 4 already suggest that RGB must be full range, so E'y, E'cb and E'cr would also be range full as appeared in the equations. If certain programs support conversions between limited range RGB and YUV, it's a non-standard support for an illegal format.


r103 specifies limits for Y,R,G,B as 16-235

The full range equations are used for the YUV=>RGB portion of the check





I don't know about this and I don't care, no one of my generation watches TV anyways

Sure, that's why you weren't aware - but some people still do

That's what this thread is supposed to be about - "broadcast safe", at least what the 1st post mentioned

feisty2
12th October 2020, 19:20
also regarding fp32 YCbCr, it is obvious that this format corresponds directly to E'y, E'cb and E'cr defined on page 3 of Rec601 (https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf), so the range should be [0, 1] and [-0.5, 0.5] accordingly. There is no definition of limited range E'y, E'cb and E'cr.

poisondeathray
12th October 2020, 20:10
also regarding fp32 YCbCr, it is obvious that this format corresponds directly to E'y, E'cb and E'cr defined on page 3 of Rec601 (https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf), so the range should be [0, 1] and [-0.5, 0.5] accordingly. There is no definition of limited range E'y, E'cb and E'cr.

f2 - maybe some confusion over terminology over what "range" refers to. It does not refer to absolute range. It refers to black and white point

1) "Limited range RGB" means 16-235 black to white (in 8bit). It does not mean that you cannot have RGB code value of 1. It describes the black to white range only . When you apply full range equations, with broadcast range input (legal range) YUV video Y 16-235 - You get limited range RGB 16-235. If you had a Y'CbCr overshoot of 236,128,128 the resulting RGB value would be 236,236,236 . It's still called "limited range RGB", because the black to white point is RGB 16-235. The 236 value doesn't get clipped

A large part of why we have "legal range video" in the first place is for historical broadcast reasons - 0,255 are reserved for sync , and the equipment/ bandwidth issues mentioned earlier



2)
"Full range RGB" means 0-255 black to white. This is what you're used to. Computer RGB. Y 16-235 => RGB 0-255. This is limited range equation application . Range expansion


But of you started with full range video (Y 0-255) , you would get clipping of Y <16, Y>235 values when limited range equation to RGB is applied. In this case, that same YCbCr 236,128,128 value does get clipped in the RGB conversion



If you look at BT.709 If you look under 4.6 - R,G,B,Y (not just Y) black level and nominal peak are listed as 16, 235 (and 64, 940 for 10bit) . Both full and limited range equations are valid for BT.709, but only the full range equation results in RGB 16-235 from legal range Y input . That's the default BT709 specification. Not surprisingly, r103 guidelines mirror that range for R,G,B,Y

https://i.postimg.cc/2jtZk1Nc/BT709-4-6.png



Hypothetically, you had unlimited bandwidth and if fp32 was a transmission format, and you still had restrictions (pretty stupid if you had unlimited bandwidth, that's the main reason for the existence of full vs. limited ranges in the first place. We'd just use RGB for everything) , then the concept of full and limited Y range would still be valid . But as mentioned earlier limiting in fp32 never exists in a real scenario. It's always done at the end

feisty2
12th October 2020, 20:31
I know exactly what range means. if you're talking about 8-bit limited range, any behavior on (236,128,128) is undefined because it is not in the (definition) domain.

If you had a Y'CbCr overshoot of 236,128,128 the resulting RGB value would be 236,236,236 . It's still called "limited range RGB", because the black to white point is RGB 16-235. The 236 value doesn't get clipped

this is called analytic continuation, basically you have extended the domain of the original definition, and whatever happens in the extended domain has nothing to do with the original definition. do you know that the sum of all natural numbers converges to -1/12?

poisondeathray
12th October 2020, 20:47
I know exactly what range means. if you're talking about 8-bit limited range, any behavior on (236,128,128) is undefined because it is not in the (definition) domain.

this is called analytic continuation, basically you have extended the domain of the original definition, and whatever happens in the extended domain has nothing to do with the original definition. do you know that the sum of all natural numbers converges to -1/12?


You can call it undefined, but it happens, and those code values can exist.

Do you see why limited range RGB exists, and why limiting functions are sometimes used ? It's to conform to 709 specs , and r103

But the problem is many of those "illegal" broadcast values are illegal combinations of Y,Cb,Cr that result in negative or >1 values in RGB in the [0,1] definition (they lie outside the RGB color cube) . They lie in the middle of the range and cannot be addressed by simple min/max compression or clipping adjustments

Simple manipluations like resizing, chroma subsampling can result in those illegal values.

feisty2
12th October 2020, 20:49
You can call it undefined, but it happens, and those code values can exist.



you know I had a hard time convincing my 10-year-old cousin that 1+2+3+... = -1/12

Cary Knoop
12th October 2020, 21:13
this is called analytic continuation, basically you have extended the domain of the original definition, and whatever happens in the extended domain has nothing to do with the original definition.
A good example of this is when you convert a linear video to log and there are negative code values (due to the noise floor being set to zero).
Without extending the domain to the (principal) complex plane you will get errors that can no longer be corrected by subsequent operations.

DTL
16th February 2021, 08:08
"the idea is to automatize clipping to get a broadcast safe output in Limited TV Range (0.0-0.7mV).

8bit sources will be limited to 16 - 235 luma and 16 - 240 chroma"

That is not great idea and looks like misunderstanding the Rec.601. Rec.601 warning about possible walking restored RGB 'out of gamut' if even YUV is in valid (1..254) range. So Rec.601 recommends to check YUV (actually Y Cr Cb) if additional limits required to keep RGB-restored 'gamut in range'. And to distort image data as low as possible if actual limiting will be applied it recommends to distort saturation in the first place.

So limiting may be applied after analysing of YUV triad data (being checked in RGB-space for gamut limits) - not by simple checking every luma and chroma data channel separately. Because simple checking and applying to each channel separately it introduce many more unnecessary distortions. And clipping to nominal YUV levels may be even not guaranteed results to be actually RGB-gamut limited.

So the actual limiter may be best to work internally in HSB color system to have ability for Saturation degrading in the first.

Also all these additional limits requirements may be just 'shadows of the past' where real data receivers where very cheap and poor 8bit integer processors and can not handle 'out of 601 gamut' RGB properly.

there's no limited range RGB.


Limited range RGB is exact 4:4:4 member of Rec.601.

It looks like misunderstanding of system RGB data encoding and physical display RGB data encoding.

System RGB must be always in limited data range (in integer encoding) to handle over/under shoots (negative under the 'black'). It is valid in numbers (math), not physics of positive-only brightness.

Physical display RGB is the end of system and for data_to_brightness operation conversion negative under_the_black levels are not valid and consumes some useful data range of low-bit encodings. So display YUV to RGB conversion is usually done to 'full' range with zero black. Also it is correctly done after scaling data to actual display size. It is final system conversion and it is not required to be 'math safe' for processing signals with limited spectrum. So only at the End of System we have right to cut-out under_the_black undershoots in RGB without degrading. Also display RGB with 'full range' is no more valid for correct signal data processing in between samples in space.

And system RGB data is just one form of describing data of limited spectrum and may be any times later scaled and other processed so it must be in math safe bipolar range against 'black' for keeping undershoots under black and also must have some headroom above nominal and better even above highest objects levels for keeping overshoots.

Same as the processing of edges of actual physical display have special workarounds against Gibbs ringing because typical moving image data is usually not conditioned against Gibbs ringing at the edges nowdays. It is applied to thread https://forum.doom9.org/showthread.php?t=182276 where it is recommended to use Avisynth AddBorders() to expand 4:3 to 16:9. Because special display workarounds applied only to actual image data buffer edges - adding 'unconditioned' borders with AddBorders() will cause Gibbs-ringing at the transition to added borders if data levels of old frame edge and new border do not match. For 'broadcast safe' levels transition operation the Avisynth's filter AddBorders() need to be fixed too. For example based on ITU-R-BT.1212 idea of using Blackman impulse response for simple conditioning for channel or any other conditioning for channel with Gibbs-distortion depressed. But still no hero to do this and core developers are busy with other things. I read some user-defined scripts exist for workaround.

>there is no mentioning of limited range RGB anywhere in Rec.601.

https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf
4:4:4 member of system - TABLE 4:

8) Correspondence between
video signal levels and
quantization level for each
sample:
– scale - 0.00d to 255.75d

– R, G, B or luminance
signal(1) - 220 (8-bit) or 877 (10-bit) quantization levels with the black level
corresponding to level 16.00d and the peak white level corresponding
to level 235.00d. The signal level may occasionally excurse beyond
level 235.00d or below level 16.00d

>Without extending the domain to the (principal) complex plane

Negative is simple real number. Not yet higher magic like complex numbers. Any video signal code value below 16 limited is actually 'negative' without any processing difficulties. In fp32 with correctly designed filters as was mentioned here there must be no difference in processing if data have some 'constant level shift'. And this shift may move all or part of data range to negative numbers too.

DTL
16th February 2021, 10:41
Some example what is going wrong when hardlimiting undershoots to 16 applied:

Giving some 'sharpness corrected' 1 video detail with local (blacker than black) undershoot samples sequence (16), 16, 7, 3, 120, 235, 3, 7, 16, (16):
https://i6.imageban.ru/out/2021/02/16/11cd7e6145968ff2bfd2be0175a8e422.png
It have good enough depressed Gibbs ringing and T-size in physical display RGB positive-only brightness about 3.1T at 0.1 level above physical zero brightness.

After hard-limiting under16 samples to 16:
https://i3.imageban.ru/out/2021/02/16/db265b898c622c9409f9e4da2c3acbf6.png
It have increased 0.1-level T-size to 3.2T (less sharp) and some far Gibbs ringing brought in (if using signal restoration DAC with large enough kernel taps value) near black level having positive (visible) values.

Emulgator
18th February 2021, 02:32
Applause, DTL.

DTL
19th February 2021, 05:02
http://downloads.bbc.co.uk/rd/pubs/reports/1987-22.pdf - the publication of Devereux, 1987 mentioned at ITU-Rep BT.629-4-1990 page 7 about possible implementation of YUV limiter keeping most of hue and luminance unchanged. I think in 2021 it may be easy enough designed as good speed Avisynth plugin but as a script it is hard and slow.

Also I see it (may not) do not try to keep the spatial spectrum of non-linearly limited YUV to be Nyquist-limited and anti-Gibbs conditioned. So the new implementation in 2021 and later may be even a bit better.

FranceBB
23rd February 2021, 16:02
So Rec.601 recommends to check YUV (actually Y Cr Cb) if additional limits required to keep RGB-restored 'gamut in range'. And to distort image data as low as possible if actual limiting will be applied it recommends to distort saturation in the first place.

So limiting may be applied after analysing of YUV triad data (being checked in RGB-space for gamut limits) - not by simple checking every luma and chroma data channel separately. And clipping to nominal YUV levels may be even not guaranteed results to be actually RGB-gamut limited.

So the actual limiter may be best to work internally in HSB color system to have ability for Saturation degrading in the first.


You're actually right, in fact although clipping the out of range values makes luma legal, it's not the same for chroma.
For instance, it's entirely possible to have 16-240 chroma, which is made of legal values, but it's represented as out of range in the scope.
The reason for this is relative to the intensity and not the code values in which the signal spans, in fact if you take this 12bit input: https://i.imgur.com/lhdv3Ag.png we can see that luma is slightly lower than 256, sitting at around 210, so, it's slightly out of range, and chroma slightly above 3935, so it's out of range as it's supposed to be 3840, however, if I limit the values to Limiter(min_luma=256, max_luma=3760, min_chroma=256, max_chroma=3840) the luma is gonna be in range but the chroma is still gonna be out of range, especially in the green component and it takes a tweak(sat=0.90) to bring it in range. https://i.imgur.com/pc3Nu0G.png The fact is that, technically speaking, there's nothing wrong with the current Avisynth implementation of clipping, I mean, Limiter does what is supposed to do, namely limit the range to the correct values (in this case Limited TV Range), however, that is not enough for chroma as it not only has to be in that range in terms of values in which the signal is spanning, but it also has to be inside the 75% relative intensity as per standard, so it's still out of range despite being limited to span the correct values. I agree with you that a much better implementation is needed for chroma which should also be able to de-saturate the input signal by a certain percentage according to the specs instead of just getting rid of the illegal values and hope for the best.


Also all these additional limits requirements may be just 'shadows of the past' where real data receivers where very cheap and poor 8bit integer processors and can not handle 'out of 601 gamut' RGB properly.


Sadly no, they're not from the past as they affect very much what we perceive today. Although it's true that the effect of airing out of range stuff is way less catastrophic today than how it was years ago with CRT TV, it's also true that the TV is supposed to convert the input signal to RGB and most of them blindly trust the flag, which means that if it's flagged as Limited, it will convert to RGB (which is always full, as feisty said before and we agreed to) assuming that the black is 16 and the peak white is 235. What this means is that nothing below 16 or above 235 is displayed. What I've seen most of the times, is cameras being out of range, not in the sense of being Full Range, no no, their black was starting correctly, at 16, but their peak white exceeds 235. This is bad as anything above 235 will NOT be displayed by the TV which performs the conversion and a soft highlights rollback is therefore needed. Besides, some watchdogs are more permissive, some other are less permissive and may be prone to make a complaint to broadcasters airing out of range stuff, depending on the nation you're airing in. As to chroma, the same thing applies, however from my experience watchdogs tend to be far more permissive on chroma than on luma (don't ask me why), but it's very much an issue today as it was in the past and it's something that we can't ignore and that we MUST get right.


Physical display RGB is the end of system and for data_to_brightness operation conversion negative under_the_black levels are not valid and consumes some useful data range of low-bit encodings. So display YUV to RGB conversion is usually done to 'full' range with zero black.


Precisely, from Limited TV Range YUV the TV converts to Full Range RGB, but if there's something below 16 and above 235 for luma and 240 for chroma, the TV will almost certainly not display it as it would return a math error. As you said, if 16 is mapped to 0, 15 can't be mapped to -1 which is not valid.


And system RGB data is just one form of describing data of limited spectrum and may be any times later scaled and other processed so it must be in math safe bipolar range against 'black' for keeping undershoots under black and also must have some headroom above nominal and better even above highest objects levels for keeping overshoots.


Correct.


For 'broadcast safe' levels transition operation the Avisynth's filter AddBorders() need to be fixed too. For example based on ITU-R-BT.1212 idea of using Blackman impulse response for simple conditioning for channel or any other conditioning for channel with Gibbs-distortion depressed. But still no hero to do this and core developers are busy with other things. I read some user-defined scripts exist for workaround.


I didn't know about AddBorders(), but I too believe that we should have those broadcast safe values respected right in the core, probably with a better implementation of Limiter, but for now I'm just thinking about a way to implement it as a plugin. It shouldn't be too hard to do, after all we "only" need to de-saturate accordingly, but I have no idea of how much I have to desaturate according to the detected value, nor how I should detect that value. I'm pretty sure that there are some ways to detect it, just like what Histogram("color2") uses to display these things, but I have to think about it and write some logic around it.


Applause, DTL.

Yep. I always said that Russian guys are good at this and he's no exception! Well done for pointing it out, DTL ;)

DTL
23rd February 2021, 18:38
this means is that nothing below 16 or above 235 is displayed.

I do not know where do you take about limiting max brightness display value to 235 Y code value. My poor-people 4k TV set from about 2015 branded 'philips' do display Y code levels up to 254. Do not as good as I think math with gamma 2.4 says like 20% brighter in compare with 235 code level, but about 16% brighter. May be because of poor driving of LCD panel at extreme code values.
https://i3.imageban.ru/out/2021/02/23/c47332398ab976d13c938345b1af85d0.jpg


I understand there may be at the consumer's side badly designed displays clipping brightness values to 235 or even upscaling 234+ code values to 236+ and with truncating high bits without saturation to 8bit ends up with 0..1+ code values and display black dots instead of 'superwhite'. But it is still badly designed examples of digital display devices. For CRT with no error any bit data processing inside tube it is also no problem do display some over-normal brightness values. As I remember at time of analog TV the 'superbright' still non-clipped value was about 130%, not 109% as currently with digital coding.

FranceBB
23rd February 2021, 18:50
I mean they physically represent the whole range, even if they're TVs, if the stream is flagged as full but they won't if it's flagged as limited and since everything is flagged as limited in broadcast, you see my point... :(
As to full range streams properly flagged as full range, it's not mandatory for manufacturers to be able to display those values so it's honestly a lottery as the TV may or may not support it. In your case, your TV correctly decodes Full Range YUV to Full Range RGB, so you're lucky, but that doesn't solve the problem with streams flagged as limited but with luma out of range I'm afraid... :(

Sharc
24th February 2021, 10:34
You may find this interesting. They introduce "preferred min./max. values".
https://tech.ebu.ch/docs/r/r103.pdf

vcmohan
1st March 2021, 12:51
I am looking for a color conversion code using template for all uint and float formats. Something like
template <typename T>
void RGB_YUV( T*YUV, T* RGB)
and
template <typename T>
void YUV_RGB(T* RGB, T* YUV)

can you guide me? I tried to code but became messy and needed more inputs like nbits, min, max, int/float

pinterf
2nd March 2021, 11:31
I am looking for a color conversion code using template for all uint and float formats. Something like
template <typename T>
void RGB_YUV( T*YUV, T* RGB)
and
template <typename T>
void YUV_RGB(T* RGB, T* YUV)

can you guide me? I tried to code but became messy and needed more inputs like nbits, min, max, int/float
It will be complex, plus you'll need the YUV-RGB conversion matrix as well (e.g. bt.601, bt.709 etc..)
edit: one can dig into avsresize which is not only a resizer but a most powerful format and color space converter as well.
It's parameter set is quite complex. http://avisynth.nl/index.php/Avsresize

vcmohan
2nd March 2021, 12:14
It will be complex, plus you'll need the YUV-RGB conversion matrix as well (e.g. bt.601, bt.709 etc..)
edit: one can dig into avsresize which is not only a resizer but a most powerful format and color space converter as well.
It's parameter set is quite complex. http://avisynth.nl/index.php/Avsresize
Very nice of you. Many thanks. But for me it looks formidable. I will go by the old formula and make some functions for my work, as they are not required to be so accurate. My requirement is to depict seeing through a colored filter(glass). While RGB is understandable, YUV I am not able to figure out excepting by converting to RGB, filter, convert back to YUV. There must be a better method.

pinterf
3rd March 2021, 09:43
I can only help with source code links

What you need is to convert from YUV to RGB, make your RGB-based overlay, then back to YUV.

In each case you have to generate two matrices, one for each conversion. On matrix creation you have to specify the used color matrix type. E.g. passing Rec.709 is good for HD/limited range conversions.

Then I link you examples on the conversion itself which is using the pre-generated matrix to do the calculation.
Unfortunately at least 8 bit, 10-16 bits and 32 bit float has to be coded differently.

As for integer scaled arithmetic: 13 or 15 bit internal precision is used for quick integer multiplication conversion. For 8 bits it's more than enough, in some cases over 10 bits it is better to use 32 bit float internally.

And now the sample link-cunami:

RGB to YUV

This one is using 15 bit precision integer arithmetic.
Matrix creation (depending on bit depth and matrix definition (e.g. limited range Rec601, full range PC.601)
https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L616

The conversion itself (their parameter is the above mentioned precalculated matrix)

Exactly 8 bits (RGB24): https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L1432
Exacly 16 bits (RGB48): https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L1459
All bit depths: https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L1459

8-16 bits (C version): https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L1318

Note that depending on the bit depth I am using int64_t for the internal calculation to avoid overflow at 16 bit videos.

Since some years - because of precision - only the 8 bit conversion is using integer arithmetic in SSE2/AVX2. More than 10 bit integer formats are internally use 32 bit float calculation.

Comment here: https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L1490

32 bit float: https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L1344
calling this: https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L1364

YUV to RGB

This one is using 13 bit scaled integer arithmetics, the matrix is pre-calculated here:
https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L1593

Exact 8 bit:
https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L2498
Exact 16 bit:
https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L2539
10-16 bits
https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/convert/intel/convert_planar_sse.cpp#L2676

I hope this helps a bit. Ask if you need further clarification.

vcmohan
4th March 2021, 13:55
Thanks again. As I mentioned, I am trying to show some parts of frame as if one looks through a colored glass. For YUV formats knowing filter yuv, is there a better way than what I am doing viz: convert to RGB, filter in RGB, convert back to YUV. My only concern is when I switch input from RGB to YUV the outputs should look reasonably similar.

DTL
5th March 2021, 18:21
Also about 'super-white' level 109% - EBU tech 3325 2.1.2 describes testing of (good enough) displays ensuring that super white can be correctly displayed (producing about 120% of brightness above 100% level as gamma-tracking obliges).

Balling
25th August 2021, 07:57
Okay, I just read the thread. Oogh. So much confusion. First of all this limiter is not needed at all. Not just because it will not fix a lot of YCbCr values (for example YCbCr BT.709 values 139, 151, 24 will be R'G'B' -21, 182, 181, thus out-of-gamut) but it is not needed, because LG C9 (reference TV) supports Superwhite (>235 Y' even if it is not white Cb, Cr 128, 128) even in internal player, not talking about YCbCr Blu-ray streams. And that is actually the case for most TVs, Superwhite is supported. As for limited range RGB and YCbCr the only real limitation is THAT IN ALL components 0 and 255 (for 10 bit 0, 1, 2, 3, 1020, 1021, 1022, 1023, for 12 even more) values are reserved and should be absent. That is coming from HDMI spec as it is used for synchronisation. For full range there is no such limitation.

Also, I will point out that BT.709 triplet I showed above is actually what is used in xvYCC (it is always limited range). Negative R'G'B' means more saturated colors when converted to XYZ. See this calculator. https://res18h39.netlify.app/color

As for limited range RGB, not only it is used in nvidia control panel but it is how SMPTE RP 219 pattern is defined.

Oh, and BTW, 1+2+3+4+... is not -1/12, series diverges by definition.

FranceBB
25th August 2021, 13:58
First of all this limiter is not needed at all.


That's debatable.


Not just because it will not fix a lot of YCbCr values (for example YCbCr BT.709 values 139, 151, 24 will be R'G'B' -21, 182, 181, thus out-of-gamut)


Out of gamut chroma won't be fixed, but luma will.



but it is not needed, because LG C9 (reference TV) supports Superwhite (>235 Y' even if it is not white Cb, Cr 128, 128) even in internal player, not talking about YCbCr Blu-ray streams. And that is actually the case for most TVs, Superwhite is supported.


Well, it depends from what you mean by "Super White".
All displays are RGB and by standard RGB is always full (Studio RGB is a particular case, we'll talk about this later). So, if the stream is tagged as Limited TV Range, the TV expects 16-235, namely a signal raging from 0.0V, 0.7V, therefore it expands 16 to 0 and 235 to 255. What happens if something is above 235? Math error as it won't fit in 255, therefore it will be clipped out.
If a stream however is flagged as full range and the TV supports full range, 0 will be mapped to 0 and 255 will be mapped to 255.
That being said, values above 235 in a Limited TV Range stream should not be part of the video and only short time overshooting are permitted by the ITU standard.
Same goes for 10bit, which should be within 64-940.
Try to send an out of range content to any serious broadcasting company with a serious QC Department and it will be refused.
And I can tell you that if I send a content with luma and chroma out of range (particularly luma) here at Sky to our QC Department, I can be 100% sure that it will be reported not just by operators but also by automatic checks like Tektronix Cerify and Tektronix Aurora and the content will be refused as they'll send it back to me so that I can re-encode it with the right levels.



As for limited range RGB, not only it is used in nvidia control panel but it is how SMPTE RP 219 pattern is defined.

Studio RGB is a particular thing and although it's used, open source software don't have a way to flag it, in fact it's mainly used between broadcasters and studios for masterfiles.
For instance, I've received plenty of Motion JPEG2000 Studio RGB 12bit (i.e Narrow Range / Limited TV Range, call it what you want) files in which I had to apply LUTs working in Limited TV Range as well and I had to use zlib in Avisynth.

That being said, those are never files that reach the end users and are used in a particular scenario in which both parties (whoever sends the file from the studio and whoever receives the file as broadcasting company) agreed to receive a Narrow Range RGB (aka Studio RGB) and they both know what they're dealing with.

cretindesalpes
25th August 2021, 14:50
That being said, values above 235 in a Limited TV Range stream should not be part of the video and only short time overshooting are permitted by the ITU standard.
BT.709-6 (p. 5), BT.2020-2 (p. 6) and BT.2100-2 (p. 2) don’t define it this way. They define black level and nominal peak at 16*2^N and 235*2^N (where N depends on the coding resolution: 0 for 8 bits, 2 for 10 bits, etc. Math formulation is mine, recs give the real values for each coding), and define a “video data range” from 1*2^N to (255*2^N)-1 inclusive as well as a two “timing reference” ranges (0 to (1*2^N)-1 and 255*2^N to 256*2^N-1). I cannot find any indication that signals under black level or over nominal peak should be temporary (and how would you check that?) or anything. Other ITU recs (like BT.2087 or BT.2390-9) also mention that the signal may exceed the black and peak values.

Maybe broadcasting stations have their own, more restrictive standards and this is perfectly fine. But for the ITU, the full [1, 255) range is legit.

DTL
25th August 2021, 22:11
It looks here is attempt to make cheap quality control for broadcasters.

If source provide 1..254 y-range it may be error/distortion or it may be correct. But to determine it broadcaster need to pay to high-priced worker like color-correction master or at least high graded professional. And if source provide 16..235 range it may be less in quality but the probability of significant errors like direct mapping of PC 0..255 levels to tv-limited is lower. And broadcaster can pay to cheap worker or buy cheap auto-QC software to check simply is levels are in 16..235 range or out. And ask sources to provide content only in hard-limited to 16..235 range. In the quickly degrading world suffering from a series of crisises it may be typical solution. Different providers of software QC tools tried to simulate pro human work of determine if 1..254 content is allowed or make by error by calculating of weights of out of 16..235 range samples and many other ideas. Like check if there large areas hard clipped to 254 level, if it appear rarely in really hard lighting to real camera or it is really error of computer-graphics software operator etc. The QC jury for real high quality content with real range 1..254 need to be highly competent and so highly priced. To make decision if it was unavoidable error in real world of content production or just gross mistake of content producer (and content need to be returned for repair).
But the price of advanced software tools may be also higher.

FranceBB
26th August 2021, 01:43
I wouldn't really call software like Baton, Cerify and Aurora "cheap" as they come with a relatively high price.
That being said, if a content is hard clipped is almost always the case it was shot in broad daylight, with no control whatsoever on it and in BT709 SDR 100 nits straight from the camera, therefore there's little to do honestly.
I've seen plenty of clipped out, completely white skies, but there's no problem with that, you can't always shoot log with a camera that has enough stops and apply a knee to knee down everything to 100 nits and make it also sit within the 16-235 / 0.0 - 0.7V range, especially if it's about news that have to go out live.

Taking this into account, anything else that is not live and that is shot nowadays for documentaries etc it's always shot log and then brought to BT709 and you can be absolutely sure that it perfectly sits within the available limited TV range values without anything clipped out unless the camera didn't have enough stops to record it (which, let's be honest, it can happen).

Still, if I have to choose I would rather get an hard clipped video than an out of range one 'cause if you send it on air and it's flagged as limited people won't be able to see it anyway. Most cameras on live shows have their black sitting at 16 correctly, however luma can go above 235 unless it's clipped. When we get ready for the shots, of course we tell the camera operator when to "close" so that the picture gets a bit darker but the highlights are within the limited TV range, however I personally also put a hard clipping on 'cause if the picture changes out of the blue and another subject is quickly now in focus it might go out of range 'cause perhaps there was a lamp out there that we didn't take into account, so I always always always put hard clipping on during live events just to be safe.

For instance, sports events.
I would rather have the players perfectly visible on the pitch and the lights clipped out in BT709 than having a completely dark picture.

FranceBB
26th August 2021, 01:59
B
Maybe broadcasting stations have their own, more restrictive standards and this is perfectly fine. But for the ITU, the full [1, 255) range is legit.

Well if it was a full range video recorded and flagged as such it would be fine (even though you couldn't air it for standard reason) but if you were to play it on a TV that supports full range stuff it will play fine.
The thing is though that when you have a camera connected via SDI or IP or whatever set to limited TV range by standard it will not set the peak white to 235.
It will make the black sit at 16 but it will leave the white unclipped, therefore, according to what you have in the shot, like a chair with a person and a lamp in the background, the values around the lamp might go above 235.
What happens then?
Well all this is happening in YUV, but our TV work in RGB and we know that RGB is always full range, so if we were to feed a full range video with the full range flag, the TV would just map each point correctly. In case the flag is limited TV range and the content is limited TV range but out of range, 16 will be mapped to 0 correctly, but 235 will be mapped to 255, so what happens to those values above it (that shouldn't be there)? Well they're just not displayed...
This is why nothing should be out of range.
About the short spikes I don't remember where I read it, but it was actually to take into account compression overshootings rather than other things, but maybe it wasn't an ITU standard but rather an EBU recommendation and I'm just confusing the two...