Log in

View Full Version : z.lib resizers for AviSynth+


Pages : 1 2 3 4 5 6 [7] 8

StvG
7th July 2023, 16:52
avsresize_r22 (https://ppp.woelkli.com/s/jYrxm4eLWAgRCjW) (pass: m6UEtJm68sPV):
- interlaced now works with use_props=1 too.
If interlaced is not specified, frame property "_FieldBased" is read to enable/disable the interlaced mode.
If interlaced is specified, "_FieldBased" doesn't have effect.
- zimg v3.0.5.

real.finder
7th July 2023, 19:11
avsresize_r22 (https://ppp.woelkli.com/s/jYrxm4eLWAgRCjW) (pass: m6UEtJm68sPV):
- interlaced now works with use_props=1 too.
If interlaced is not specified, frame property "_FieldBased" is read to enable/disable the interlaced mode.
If interlaced is specified, "_FieldBased" doesn't have effect.
- zimg v3.0.5.

thank you, I will test it as soon as possible

edit: everything seems ok, what about chroma subsampling parameter? https://forum.doom9.org/showthread.php?p=1989150#post1989150

StvG
8th July 2023, 09:59
thank you, I will test it as soon as possible

edit: everything seems ok, what about chroma subsampling parameter? https://forum.doom9.org/showthread.php?p=1989150#post1989150

What's the difference between z_ConvertFormat(pixel_type="yuv444p16") and z_ConvertFormat(chroma_subsampling="444") (assuming YUV420P16 input)?

real.finder
8th July 2023, 13:12
What's the difference between z_ConvertFormat(pixel_type="yuv444p16") and z_ConvertFormat(chroma_subsampling="444") (assuming YUV420P16 input)?

with YUV420P16 case both are same but with yv12 (8bit YUV420) z_ConvertFormat(pixel_type="yuv444p16") will convert it from 8 bit to 16 bit and 4:4:4 while z_ConvertFormat(chroma_subsampling="444") will only convert it to 4:4:4 (it will be yv24)

edit: maybe it also worth adding bit_bepth parameter too

and both chroma_subsampling and bit_bepth will be ignored when pixel_type is used

StvG
9th July 2023, 06:18
with YUV420P16 case both are same but with yv12 (8bit YUV420) z_ConvertFormat(pixel_type="yuv444p16") will convert it from 8 bit to 16 bit and 4:4:4 while z_ConvertFormat(chroma_subsampling="444") will only convert it to 4:4:4 (it will be yv24)

edit: maybe it also worth adding bit_bepth parameter too

and both chroma_subsampling and bit_bepth will be ignored when pixel_type is used

z_ConvertFormat(pixel_type="yuv444p" + (ComponentSize() == 4 ? "s" : String(BitsPerComponent())))

Is the above code too complicated?

Don't get me wrong. There are already a lot of parameters that making the usage a bit complicated at first look. Adding more parameters with actions that are already covered is unnecessary further complication imo.

real.finder
9th July 2023, 10:41
if the problem that it got lot of parameters, then can we got pixel_type to accept things like "444" (or "yuv444*") or "Y" (without any number or "Y*") and same with bitbepth (like *P16)

StvG
9th July 2023, 14:41
avsresize_r23 (https://ppp.woelkli.com/s/jYrxm4eLWAgRCjW) (pass: m6UEtJm68sPV):
- Added parameter bit_depth: output bit depth. It doesn't have effect if pixel_type is defined;
- Added parameter chroma_subsampling: output chroma subsampling. It doesn't have effect if pixel_type is defined;
- zimg v3.0.5.

real.finder
9th July 2023, 18:05
avsresize_r23 (https://ppp.woelkli.com/s/jYrxm4eLWAgRCjW) (pass: m6UEtJm68sPV):
- Added parameter bit_depth: output bit depth. It doesn't effect if pixel_type is defined;
- Added parameter chroma_subsampling: output chroma subsampling. It doesn't effect if pixel_type is defined;
- zimg v3.0.5.

thanks! both work fine

FranceBB
9th July 2023, 19:43
- Added parameter bit_depth: output bit depth. It doesn't effect if pixel_type is defined;
- Added parameter chroma_subsampling: output chroma subsampling. It doesn't effect if pixel_type is defined;
- zimg v3.0.5.

So, as long as I specify the pixel_type, everything stays the same as in the last version if I don't specify the two new parameters, right?

StvG
10th July 2023, 02:31
So, as long as I specify the pixel_type, everything stays the same as in the last version if I don't specify the two new parameters, right?

Yes, if you specify pixel_type the two new parameters are ignored even if they are specified too.

FranceBB
10th July 2023, 05:25
Perfect, so it won't break any of my supply chains. :)

Well, I'm suffering from insomnia due to the heatwave (I'm currently in Milan, Italy and not in the UK unfortunately) and the fan is just blowing hot air on me, which is useless...
So... I might just get up, take a shower, have breakfast, go to the office (where I actually have AC) and update all my servers xD

joearmstrong
30th July 2023, 07:50
I'm not sure if I'm using chromaloc_op correctly. I haven't used it so far.

I want to convert HDR PQ to SDR:
Example 1:
z_ConvertFormat(pixel_type="RGBP16", colorspace_op="2020ncl:st2084:2020:limited=>rgb:st2084:2020:full", chromaloc_op="top_left=>top_left", dither_type="none")
Cube("D:\5-NBCU_PQ2SDR_DL_Adobe_v1.cube", interp=1, fullrange=1)
z_ConvertFormat(pixel_type="YV12", colorspace_op="rgb:709:709:full=>709:709:709:limited", chromaloc_op="top_left=>left", dither_type="ordered")

Example 2:
z_ConvertFormat(pixel_type="YUV444P16",colorspace_op="2020ncl:st2084:2020:l=>2020ncl:st2084:2020:l",chromaloc_op="top_left=>top_left",dither_type="none")
ConvertYUVtoXYZ(Color=0,HDRMode=0,OOTF=false,OutputMode=2)
ConverXYZ_BT2446_C_HDRtoSDR(PQMode=true,Lhdr=50000.0,Lsdr=100.0,pColor=0,pct_ref=0.6,pct_ip=0.6,pct_wp=1.0,pct_sdr_skin=1.0,pct_hdr_skin=0.44)
ConvertXYZtoYUV(Color=2,pColor=0,OOTF=false)
z_ConvertFormat(pixel_type="YV12",colorspace_op="709:709:709:l=>709:709:709:l",chromaloc_op="top_left=>left",dither_type="ordered")

I think the change to "left" (mpeg2), which is the standard for Rec709, should be placed at the end of the scripts ?

FranceBB
30th July 2023, 11:04
It should, in theory, be fine.
When you upscale the chroma to RGB, you're essentially going to the same resolution for both luma and chroma and, just like with 4:4:4, the chroma location loses its meaning.
When you're downscaling the chroma to go back to 4:2:0, however, it actually matters, but given that by default it assumes that you want the classic 4:2:0 (i.e left) and not type 2 (i.e top left), it will automatically get it right even if you don't specify it ;)

joearmstrong
30th July 2023, 11:46
Thanks for your answer and explanation, FranceBB.

StvG
1st October 2023, 20:11
The source code is uploaded here (https://codeberg.org/StvG/avsresize).
Builds are here (https://codeberg.org/StvG/avsresize/releases).

tormento
2nd October 2023, 11:12
Builds are here.
Thank you :)

hello_hello
26th February 2024, 17:22
I'm think I'm starting to seriously dislike frame properties. Nothing specific to AVSResize. Just generally.

AVSResize appears to have the same problem VapourSynth's resizers did previously (https://forum.doom9.org/showthread.php?t=185080), in that it doesn't take it's own cropping into account when calculating a new sample aspect ratio. I'm using AVSResize r23.
Thanks.

ColorBars.KillAudio().ConvertToYV12() # 640x480 (4:3)
propSet("_SARNum", 1).propSet("_SARDen", 1)
z_ConvertFormat(720,576)
# propGetAny("_SARNum") = 16
# propGetAny("_SARDen") = 15

ColorBars.KillAudio().ConvertToYV12() # 640x480 (4:3)
propSet("_SARNum", 1).propSet("_SARDen", 1)
z_ConvertFormat(720,576, src_left=240, src_top=0, src_width=400, src_height=480)
# propGetAny("_SARNum") = 16
# propGetAny("_SARDen") = 15

FranceBB
26th February 2024, 18:56
I'm think I'm starting to seriously dislike frame properties.

Amen.
I've been saying this for months, Tormento knows that 'cause I've been complaining to him for months when I had to implement them in all my workflows!

Life was easier when we only had clip properties.
Eventually, what I ended up doing in all my Avisynth workflow is:

1) propclearall() to nuke everything
2) do the stuff as I always did
3) propset() to re-populate everything correctly at the end

which is a big pain anyway... :(

hello_hello
26th February 2024, 20:05
FranceBB, "starting to" was probably a bit of an under-statement. :)

It might be handy for resizers that support reading and writing a frame properties SAR to have a specific option for keeping the original SAR or even changing it. Sometimes you want to resize an image and keep the resized aspect ratio on playback instead of the player undoing the resizing, as would happen if the SAR is honored from Avisynth script through to encoder, which I assume is the ultimate goal. It'd probably be easier to do via a resizer argument rather than having to fiddle with frame properties. A DAR argument might even be a better as people tend to think in terms of a DAR rather than a SAR (I definitely do) and it'd be easy for the resizer to convert it to a SAR for frame properties. I can only dream....

StvG
28th February 2024, 04:34
avsresize r24 (https://codeberg.org/StvG/avsresize/releases):
- Added ST.428-1 (gamma 2.6) transfer function.
- Fixed SAR calculation when internal crop is used.
- zimg a0fac0f.

Would it be possible to include the 2.6 gamma to the possible transfer function which is used in st431-2 and st432-1?

Added in r24 as "st428". Related (https://github.com/sekrit-twc/zimg/issues/192).

I'm think I'm starting to seriously dislike frame properties. Nothing specific to AVSResize. Just generally.

AVSResize appears to have the same problem VapourSynth's resizers did previously (https://forum.doom9.org/showthread.php?t=185080), in that it doesn't take it's own cropping into account when calculating a new sample aspect ratio. I'm using AVSResize r23.
Thanks.

ColorBars.KillAudio().ConvertToYV12() # 640x480 (4:3)
propSet("_SARNum", 1).propSet("_SARDen", 1)
z_ConvertFormat(720,576)
# propGetAny("_SARNum") = 16
# propGetAny("_SARDen") = 15

ColorBars.KillAudio().ConvertToYV12() # 640x480 (4:3)
propSet("_SARNum", 1).propSet("_SARDen", 1)
z_ConvertFormat(720,576, src_left=240, src_top=0, src_width=400, src_height=480)
# propGetAny("_SARNum") = 16
# propGetAny("_SARDen") = 15

Fixed in r24.

hello_hello
28th February 2024, 22:02
Fixed in r24.

Thank you.

Another one....
AVSResize is changing the ColorRange frame property from full to limited for 32 bit YUV. Would it be correct to assume it shouldn't?

ColorBars.KillAudio().ConvertToYV24().ConvertBits(32)
propset("_ColorRange", 0)
z_ConvertFormat(960,720)
# propGetAny("_ColorRange") = 1

The same thing happens when you use colorspace_op without specifying a coior range
z_ConvertFormat(colorspace_op="170m:601:170m=>470bg:601:470bg")

And when using two instances of z_ConvertFormat to convert to RGB and back.
z_ConvertFormat(colorspace_op="170m:601:170m=>rgb:linear:170m", pixel_type="RGBPS")
z_ConvertFormat(colorspace_op="rgb:linear:170m=>470bg:601:470bg", pixel_type="YUV420PS")

Cheers.

StvG
29th February 2024, 05:07
avsresize r25 (https://codeberg.org/StvG/avsresize/releases):
- Fixed exported _ColorRange properties.
- zimg a0fac0f.

Thank you.

Another one....
AVSResize is changing the ColorRange frame property from full to limited for 32 bit YUV. Would it be correct to assume it shouldn't?

ColorBars.KillAudio().ConvertToYV24().ConvertBits(32)
propset("_ColorRange", 0)
z_ConvertFormat(960,720)
# propGetAny("_ColorRange") = 1

The same thing happens when you use colorspace_op without specifying a coior range
z_ConvertFormat(colorspace_op="170m:601:170m=>470bg:601:470bg")

And when using two instances of z_ConvertFormat to convert to RGB and back.
z_ConvertFormat(colorspace_op="170m:601:170m=>rgb:linear:170m", pixel_type="RGBPS")
z_ConvertFormat(colorspace_op="rgb:linear:170m=>470bg:601:470bg", pixel_type="YUV420PS")

Cheers.

The first case (z_ConvertFormat(960,720)) is fixed in r25.

The last two cases always should give full color range property. It's fixed in r25.

hello_hello
1st March 2024, 01:23
Thanks again!

ErazorTT
5th March 2024, 01:29
Unrelated to the current new versions, is there something off for 2020->709?

Taking this red ramp as an input:
https://i.postimg.cc/WhY8pzLc/red-ramp-input.png (https://postimg.cc/WhY8pzLc)

And applying:
z_ConvertFormat(colorspace_op="rgb:2020:2020:full=>rgb:709:709:full")

results in:
https://i.postimg.cc/nXskXxpj/red-ramp-2020-to-709.png (https://postimg.cc/nXskXxpj)

Comparing to my expectation and with the calibrated display modes BT.2020 and BT.709 on my display, the position marked (look at the full image) appears too abrupt and too magenta. Could there be something off somewhere in the matrices?

my expectation would have been this:
https://i.postimg.cc/Hrft5NkS/red-ramp-expectation.png (https://postimg.cc/Hrft5NkS)

poisondeathray
5th March 2024, 03:39
Unrelated to the current new versions, is there something off for 2020->709?

Taking this red ramp as an input...

It seems off . There are large jumps at lower values in the green channel .

Compare the result to FMTC, which is smooth and the increments are even


fmtc_transfer(transs="2020", transd="linear")
fmtc_primaries(prims="2020", primd="709")
fmtc_transfer(transs="linear", transd="709")


For avsresize - I tried linearizing first, also maxcpu setting. Also same result in vapoursynth

StvG
5th March 2024, 04:52
Yes, it's zimg bug.
The github (https://github.com/sekrit-twc/zimg) repo is abandoned and the new bitbucket (https://bitbucket.org/the-sekrit-twc/zimg/src/master/) repo doesn't have enabled the "Issues" sections. If someone has contact with the author (irc, discord) can report this. Also it can be reported on the VS repo/forum (I guess the VS people can reach him since zimg is the default VS resize/colorspace function).

Balling
16th March 2024, 21:33
"Comparing to my expectation and with the calibrated display modes BT.2020 and BT.709 on my display, the position marked (look at the full image) appears too abrupt and too magenta. Could there be something off somewhere in the matrices?"

Mmmm... "Note that "z" is not a color management system and should not be used to perform drastic contrast or gamut reduction, such as BT.2020 to BT.709."


Same command ffmpeg -i red-ramp-inputbt2020.png -vf zscale=rin=full:r=full:tin=2020_12:t=2020_12:pin=2020:p=709:d=none dwedstrange1.png

Balling
16th March 2024, 21:42
" Taking this red ramp as an input:"

That ramp is sRGB, rendering intent Perceptual. This is lossless data (-f md5 - prints c9910d9f1c4dcf3698ba025a268facf4), but tagged as 2020 primaries, 2.4 gamma. Here you go (I must say windows is closer to what zimg does in sdr mode, in HDR not even close): https://i.postimg.cc/1zWB2gMn/red-ramp-inputbt2020.png

DTL
16th March 2024, 22:14
Unrelated to the current new versions, is there something off for 2020->709?

Taking this red ramp as an input:
https://i.postimg.cc/WhY8pzLc/red-ramp-input.png (https://postimg.cc/WhY8pzLc)

And applying:
z_ConvertFormat(colorspace_op="rgb:2020:2020:full=>rgb:709:709:full")


Any 'simple' shrink-conversion of wider domain to narrower is unlikely possible with significant clipping or other issues. Maybe original designer of wide->narrow valid convert path assume user prepare valid colour gamut and levels range first (in 2020 primaries and 2020 transfer) and only as next step apply conversion. Maybe avsresize do not doing any 'shrinking' at all at attempt to to 'downconversion'. It looks not covered in the documentation ? HDR to SDR and WCG to SCG conversions may be performed at least in 3 different ways:
1. Range crop (extract SDR and SCG from HDR and WCG). Any out of range values are clipped to max valid values.
2. Full range map (compress full HDR and WCG into SDR and SCG).
3. Some unlimited ways of 'tonemap'.

So it possibly only low-distorted way: rgb:709:709:full=>rgb:2020:2020:full=>rgb:709:709:full (using 32bit float samples to escape of quantization noise as best as possible).

If feed out-of-range 2020 primaries and transfer to conversion to 709 - the result maybe undefined.

Also freeware HDR<->SDR conversion libraries may have some set of 'magic variables' to tweak the conversion like float "nominal_luminance", bool "approximate_gamma", bool "use_props", bool "scene_referred".

ErazorTT
20th March 2024, 02:12
"Note that "z" is not a color management system and should not be used to perform drastic contrast or gamut reduction, such as BT.2020 to BT.709."

Any 'simple' shrink-conversion of wider domain to narrower is unlikely possible with significant clipping or other issues. Maybe original designer of wide->narrow valid convert path assume user prepare valid colour gamut and levels range first (in 2020 primaries and 2020 transfer) and only as next step apply conversion. Maybe avsresize do not doing any 'shrinking' at all at attempt to to 'downconversion'.

I don't know what you guys are talking about. There is a very well defined conversion from any color space to any other, by going through XYZ. This of course involves clipping but if nothing else is specified by the user this should be the default. And no, z_ConvertFormat does not try to do any perceptual conversion, that is clear from the clipping it produces.

For the discussed case, the conversion from (linear) 2020 RGB to XYZ is given by:
X = 0.636958048 * rl + 0.144616904 * gl + 0.168880975 * bl;
Y = 0.262700212 * rl + 0.677998072 * gl + 0.059301716 * bl;
Z = 0.000000000 * rl + 0.028072693 * gl + 1.060985058 * bl;

And the conversion from XYZ to (linear) 709 RGB is given by:
rl = 3.240969944 * X - 1.537383176 * Y - 0.4986107602 * Z;
gl = -0.9692436371 * X + 1.875967501 * Y + 0.04155505794 * Z;
bl = 0.05563007901 * X - 0.2039769588 * Y + 1.056971515 * Z;

The clipping than happens by clamping:
rl = min(max(rl,0),1);
gl = min(max(gl,0),1);
bl = min(max(bl,0),1);

This will produce my "expectation image" from the "input image". z_ConvertFormat reproduces this for all colored ramps apart from the red ramp, thus there is something wrong.

(PS: that is exactly what Rep. ITU-R BT.2407-0 describes in section 2, on pages 1 and 2. And of course what I haven’t shown here is going back and forth from gamma to linear, but thats also streightforward.)

ErazorTT
20th March 2024, 02:52
That ramp is sRGB, rendering intent Perceptual. This is lossless data, but tagged as 2020 primaries, 2.4 gamma.
How do you come to that conclusion? By looking at the tags of the image file? That is completely irrelevant, first of all that is just a screenshot, second the input can be interpreted however necessary.
My actual input was not that image but a script creating the ramp which I then fed to z_ConvertFormat.

ErazorTT
20th March 2024, 10:49
Ok I think found the issue. Actually I looked further into it because of Balling's and DTL's comments.
The point is that the conversion by z_ConvertFormat is done display-referred, while I did it scene-referred. Display-referred is probably the "more correct".
So the conversion by z_ConvertFormat is actually fine!

This obviously means that fmtc_transfer converts scene-referred.

Scene-referred means that the transfer function used is that shown in item 1.2 from the tabel on page 3 of Rec. ITU-R BT.709-6. Display-referred means that the transfer function used is the one from Rec. ITU-R BT.1886 page 3.

DTL
20th March 2024, 14:20
Documentation http://avisynth.nl/index.php/Avsresize says

bool scene_referred = false
Whether to use scene-referred transfer function (default false).

Is setting to true produce expected result ?

"Display-referred is probably the "more correct"."

Linear scene light expected to be close to reality and fixed for source (image data). And displays may be different. If you make a chain of conversions and some uses display linear and some scene linear - the result will be more distorted.

It may be same idea as about spatial spectrum shaping - it is better to do in scene linear light.

ErazorTT
20th March 2024, 16:34
bool scene_referred = false
Whether to use scene-referred transfer function (default false).

Ah, it's good to know that it can do both. Yes, so this reproduces what I initially expected. I am now not sure which conversion to prefere but it seems that display-referred is the one I need.

Balling
4th April 2024, 21:22
Ok I think found the issue. Actually I looked further into it because of Balling's and DTL's comments.
The point is that the conversion by z_ConvertFormat is done display-referred, while I did it scene-referred. Display-referred is probably the "more correct".
So the conversion by z_ConvertFormat is actually fine!

This obviously means that fmtc_transfer converts scene-referred.

Scene-referred means that the transfer function used is that shown in item 1.2 from the tabel on page 3 of Rec. ITU-R BT.709-6. Display-referred means that the transfer function used is the one from Rec. ITU-R BT.1886 page 3.

It is more complex. If we have PQ it is only display referred, as OETF is inverse of EOTF. With BT.709 and BT.2020 — both SDR specs — it is not thay simple. The change of primaries must happen ON LINEAR LIGHT using 2.0 gamma, not 2.2 or 2.4. Then you can apply 2.4.

hello_hello
25th July 2024, 23:55
Another one....
AVSResize is changing the ColorRange frame property from full to limited for 32 bit YUV. Would it be correct to assume it shouldn't?

ColorBars.KillAudio().ConvertToYV24().ConvertBits(32)
propset("_ColorRange", 0)
z_ConvertFormat(960,720)
# propGetAny("_ColorRange") = 1

The same thing happens when you use colorspace_op without specifying a coior range
z_ConvertFormat(colorspace_op="170m:601:170m=>470bg:601:470bg")

And when using two instances of z_ConvertFormat to convert to RGB and back.
z_ConvertFormat(colorspace_op="170m:601:170m=>rgb:linear:170m", pixel_type="RGBPS")
z_ConvertFormat(colorspace_op="rgb:linear:170m=>470bg:601:470bg", pixel_type="YUV420PS")

StvG,
While trying to get my head around the assumptions ConvertBits() makes regarding color range for 32 bit YUV when there's no ColorRange in frame properties (you answered my question in that thread), I started to worry that changing the way AVSResize handles YUV float might have been a mistake.

I'd been under the impression that 32 bit YUV was always full range, and from what I can tell that was true originally but it's no longer the case. Without a frame property to tell it otherwise ConvertBits() assumes all YUV is limited range, including float, so would it be better for consistency if AVSResize did the same?

AVSResize is also currently writing full range to frame properties for any 32 bit color space conversion even when limited is specified. For example:
z_ConvertFormat(colorspace_op="170m:601:170m:l=>470bg:601:470bg:l")

Cheers.

StvG
26th July 2024, 07:43
StvG,
While trying to get my head around the assumptions ConvertBits() makes regarding color range for 32 bit YUV when there's no ColorRange in frame properties (you answered my question in that thread), I started to worry that changing the way AVSResize handles YUV float might have been a mistake.

I'd been under the impression that 32 bit YUV was always full range, and from what I can tell that was true originally but it's no longer the case. Without a frame property to tell it otherwise ConvertBits() assumes all YUV is limited range, including float, so would it be better for consistency if AVSResize did the same?

I don't think so. In this thread there was a discussion (https://forum.doom9.org/showthread.php?p=1926448#post1926448) already about this (read the linked post and the next posts, btw I see you replied too at that time).

AVSResize is also currently writing full range to frame properties for any 32 bit color space conversion even when limited is specified. For example:
z_ConvertFormat(colorspace_op="170m:601:170m:l=>470bg:601:470bg:l")Cheers.

Because zimg always assumes 32-bit float in full range and l=>l doesn't perform range conversion.

hello_hello
9th October 2024, 06:00
I was initially stacking videos to check the frame properties were correct after conversion with a function, but I noticed some color oddities with AVSResize when converting between rec.2020 and rec.709.
Would it be safe to assume from the result that approximate_gamma=true (the default) is a bad idea? The difference seems to be the most noticeable for the primary colors. The source is a rec.709 blank clip converted to rec.2020 with HDRTools (so the primaries are rec.2020) and then converted back to rec.709.

z_ConvertFormat(colorspace_op="2020:2020:2020:limited=>rgb:linear:xyz:full", pixel_type="RGBP16")
z_ConvertFormat(colorspace_op="rgb:linear:xyz:full=>709:709:709:limited", pixel_type="YUV420P8")

https://i.imgur.com/56LbtCC.png

z_ConvertFormat(colorspace_op="2020:2020:2020:limited=>rgb:linear:xyz:full", pixel_type="RGBP16", approximate_gamma=false)
z_ConvertFormat(colorspace_op="rgb:linear:xyz:full=>709:709:709:limited", pixel_type="YUV420P8", approximate_gamma=false)

https://i.imgur.com/1p9Nx2d.png

DTL
9th October 2024, 07:24
It is good to pick RGB levels (or YUV if the conversion in that colour space) and post source code values for Red patch and all output code values of different tools used. Typical sources of errors - levels range treatment (in float more frequently) and scene/display referred linear. So you can try first RGB only colour space and limited (narrow) range only and look for scene/display switches in the tools used and test different options combinations. Also for best possible matching between different tools - may be helpful https://forum.doom9.org/showthread.php?p=1972733#post1972733

StvG
19th October 2024, 06:51
I was initially stacking videos to check the frame properties were correct after conversion with a function, but I noticed some color oddities with AVSResize when converting between rec.2020 and rec.709.
Would it be safe to assume from the result that approximate_gamma=true (the default) is a bad idea? The difference seems to be the most noticeable for the primary colors. The source is a rec.709 blank clip converted to rec.2020 with HDRTools (so the primaries are rec.2020) and then converted back to rec.709.

z_ConvertFormat(colorspace_op="2020:2020:2020:limited=>rgb:linear:xyz:full", pixel_type="RGBP16")
z_ConvertFormat(colorspace_op="rgb:linear:xyz:full=>709:709:709:limited", pixel_type="YUV420P8")

https://imgur.com/56LbtCC.png

z_ConvertFormat(colorspace_op="2020:2020:2020:limited=>rgb:linear:xyz:full", pixel_type="RGBP16", approximate_gamma=false)
z_ConvertFormat(colorspace_op="rgb:linear:xyz:full=>709:709:709:limited", pixel_type="YUV420P8", approximate_gamma=false)

https://imgur.com/1p9Nx2d.png

Can you share a test script and a sample if there is?

tormento
19th October 2024, 16:22
I am scratching my head.

From Avsresize (http://avisynth.nl/index.php/Avsresize#Changing_Colorimetry) page:

SD NTSC Rec. 601 to HD Rec. 709
z_ConvertFormat(colorspace_op="470bg:601:170m:full=>709:709:709:full")

SD PAL Rec. 601 to HD Rec. 709
z_ConvertFormat(colorspace_op="470bg:601:470bg:full=>709:709:709:full")

Rec. 709 SDR to Rec. 2020 SDR
z_ConvertFormat(colorspace_op="709:709:709:full=>2020:2020:2020:full")

And so on.

Why it requires full when it's actually limited?

FranceBB
19th October 2024, 18:42
Probably to preserve overshootings (i.e highlights over 0.7V) which shouldn't be there in the first place.
It won't do anything bad to the input signal anyway other than changing the frame properties in terms of metadata.

Anyway, I tried without specifying anything and it worked just fine and the same goes for limited to limited as long as you don't have anything exceeding 0.7V.


#Matrix Conversion BT601 PAL to BT709
z_ConvertFormat(colorspace_op="470bg:601:470bg=>709:709:709")


#Matrix Conversion BT709 to BT601 PAL
z_ConvertFormat(colorspace_op="709:709:709=>470bg:601:470bg")


#Matrix Conversion BT709 to BT2020
z_ConvertFormat(colorspace_op="709:709:709:limited=>2020:2020:2020:limited")


#Matrix Conversion BT2020 to BT709
z_ConvertFormat(colorspace_op="2020:2020:2020:limited=>709:709:709:limited")


#Matrix Conversion BT2020 to BT601 PAL
z_ConvertFormat(colorspace_op="2020:2020:2020:limited=>470bg:601:470bg:limited")

DTL
20th October 2024, 22:50
I am scratching my head.

Why it requires full when it's actually limited?

full->full may mean 'no change of range mapping'. Though if calculation is somehow depend on range mapping it can cause distortions - so better to test also limited->limited.

hello_hello
21st October 2024, 13:48
Can you share a test script and a sample if there is?

I was just using a blank clip and changing the color (of the blank clip).
It's probably not technically correct as the blank clip wouldn't have 2020 primaries (I assume) but it does illustrate the difference.

clip = BlankClip(color=color_red).ConvertToYUV420(matrix="rec2020").Spline36Resize(240,240)
clip = clip.ConvertBits(10)
SourceBits = BitsPerComponent(clip)
Bits = (SourceBits == 32) ? 32 : 16
RGBType = "RGBP" + ((SourceBits == 32) ? "S" : "16")
YUVType = "YUV420P" + ((SourceBits == 32) ? "S" : "16")

clipA = clip.HistoTop().Subtitle("BlankClip", size=20)

clipB = clip.ConvertBits(Bits)\
.z_ConvertFormat(colorspace_op="2020:2020:2020:limited=>rgb:linear:xyz:full", pixel_type=RGBType)\
.z_ConvertFormat(colorspace_op="rgb:linear:xyz:full=>709:709:709:limited", pixel_type=YUVType)\
.ConvertBits(SourceBits).HistoTop().Subtitle("AVSResize (ag=true)", size=20)

clipC = clip.ConvertBits(Bits)\
.z_ConvertFormat(colorspace_op="2020:2020:2020:limited=>rgb:linear:xyz:full", pixel_type=RGBType, approximate_gamma=false)\
.z_ConvertFormat(colorspace_op="rgb:linear:xyz:full=>709:709:709:limited", pixel_type=YUVType, approximate_gamma=false)\
.ConvertBits(SourceBits).HistoTop().Subtitle("AVSResize (ag=false)", size=20)

clipD = clip\
.fmtc_bitdepth(Bits)\
.fmtc_resample(css="444")\
.fmtc_matrix(mat="2020", fulls=false, fulld=true, bits=Bits)\
.fmtc_transfer(transs="1886", transd="Linear")\
.fmtc_primaries(prims="2020", primd="709")\
.fmtc_transfer(transs="Linear", transd="1886")\
.fmtc_matrix(mat="709", fulls=true, fulld=false, bits=Bits)\
.fmtc_resample(css="420")\
.fmtc_bitdepth(SourceBits)\
.HistoTop().Subtitle("FMTConv", size=20)

clipE = clip\
.ConvertBits(16)\
.ConvertToYUV444()\
.ConvertYUVtoXYZ(Color=1, fullrange=false)\
.ConvertXYZtoYUV(Color=2, PColor=1, fullrange=false)\
.ConvertToYUV420()\
.ConvertBits(SourceBits)\
.HistoTop().Subtitle("HDRTools", size=20)

StackHorizontal(clipA, clipB, clipC, clipD, clipE)

function HistoTop(clip Source) {
Try{ FTurnRight(Source).Histogram().FTurnLeft() }Catch(err){ TurnRight(Source).Histogram().TurnLeft() } }

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

clip = BlankClip(color=color_lime).ConvertToYUV420(matrix="rec2020").Spline36Resize(240,240)

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

DTL
21st October 2024, 16:28
scene_referred=true or false change anything ?

Also look at comment: https://forum.doom9.org/showthread.php?p=1972755#post1972755

About the 'magic' amplitude correction:
- fmtconv - after rgb_lin=fmtc_transfer(rgb_lin,transs="hlg",transd="linear", sceneref=true) the ouput is within range [0,~1]. After applying RGBAdjust values of 0.5, the output becomes within range [0, ~0.5].
- avsresize after rgb_lin=z_convertformat(yuv444,pixel_type="rgbps", colorspace_op="2020ncl:std-b67:2020:l=>rgb:linear:2020:l", scene_referred=true) the output is within range [0, ~3.188]. After applying RGBAdjust values of 0.157, the output becomes within range [0, ~0.5].

Different tools may use different scaling in 'linear'. So may you need to use RGBAdjust() to tweak RGB linear code values somehow. Try to look into code values after each operation.

poisondeathray
21st October 2024, 16:41
What plugins/versions ? I'm getting different results with that script just copy/pasted

avs+ r4066
avsresize r25
fmtconv r30
hdrtools 1.0.5

https://i.postimg.cc/L8xMH2FT/hello-hello.png

hello_hello
21st October 2024, 22:25
DTL & poisondeathray,

thanks for the info. I probably won't get a chance to play around again until late today or tomorrow.

What plugins/versions ? I'm getting different results with that script just copy/pasted

avs+ r4066
avsresize r25
fmtconv r30
hdrtools 1.0.5

https://i.postimg.cc/L8xMH2FT/hello-hello.png

I'm using the same versions of everything except Avisynth+ (r4073 (https://gitlab.com/uvz/AviSynthPlus-Builds))

hello_hello
22nd October 2024, 08:20
I was just using a blank clip and changing the color (of the blank clip).
It's probably not technically correct as the blank clip wouldn't have 2020 primaries (I assume) but it does illustrate the difference.

Well it looks like it was my fault. Kind of.....
I think it's the first time I've come across a plugin behaving differently running in Wine than in Windows, but when I ran the script again in VirtualBox/Windows 11 it was fine.

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

I went back to Avisynth+ 3.7.3 (official release) and nothing changed, so I doubt it's an Avisynth problem.

So it appears approximating gamma in Wine is a bad idea. Anyone know why that'd be? I'm not running the latest version of Wine, so out of curiosity I might install some flavor of Linux in VirtualBox later and install the latest Wine to see if it works properly. I don't want to update Wine on my main OS just yet.

poisondeathray
22nd October 2024, 14:40
So it appears approximating gamma in Wine is a bad idea. Anyone know why that'd be? I'm not running the latest version of Wine, so out of curiosity I might install some flavor of Linux in VirtualBox later and install the latest Wine to see if it works properly. I don't want to update Wine on my main OS just yet.

Maybe some issues with SIMD / AVX2 ? Apparently some Wine releases had some issues . You can try SetMaxCPU and work your way down the list to help debug

hello_hello
22nd October 2024, 15:39
Maybe some issues with SIMD / AVX2 ? Apparently some Wine releases had some issues . You can try SetMaxCPU and work your way down the list to help debug

It's all over with anything less than sse4.1, running in both Windows and Wine. Unfortunately though, limiting the CPU capabilities didn't make any difference to the approximate gamma problem.

SetMaxCPU("ssse3")

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