View Full Version : CropResize - Cropping & resizing function (Avisynth & VapourSynth versions)
hello_hello
15th July 2019, 18:43
From the version dated 2023-09-28 there's a native VapourSynth flavour of CropResize.
Quite a few changes have been introduced in the version dated 2025-06-16, so if you've used the function in the past the Changes text file would be worth reading. The main change to note for the Avisynth version of CropResize is Avisynth+ 3.7.1 is now a minimum requirement.
The main change for the version dated 2025-12-20 is the inclusion of a new function, CombineClips, that uses CropResize to automatically append videos. See post #97 (https://forum.doom9.org/showthread.php?p=2026204#post2026204) for usage examples.
CropResize 2025-12-20.zip (https://files.videohelp.com/u/210984/CropResize%202025-12-20.zip)
The purpose of the script
The main goal of CropResize is to crop and resize without having to worry about calculating aspect error or distorting the picture. Rather than distort the picture as traditional resizing does when the input and output aspect ratios don't match, the script crops or adds borders instead. It can apply sub-pixel cropping when required.
Despite the numerous options, basic usage is fairly straightforward.
The pictures in post #2 illustrate CropResize usage.
hello_hello
15th July 2019, 18:44
The easiest way to demonstrate CropResize is with some pictures
Some of these examples also demonstrate using the wrapper functions supplied with CropResize to easily
enable the default cropping preview or set Info=true, and some also use the abbreviated function name of CR().
The (home made) PAL 16:9 source used for the following examples
https://i.postimg.cc/Zns9Tsb9/Crop-Resize-01-PAL-16-9.jpg
Basic usage
Simply specify a width (or height) and the desired cropping (or enable auto-cropping), along with the input display
aspect ratio if the source is anamorphic, and let CropResize take care of the rest, here resizing to "square pixel" dimensions.
The abbreviated function name CR() can be used instead of CropResize() if the wrapper functions script is loaded.
CropResize(832,0, 4,32,-6,-32, InDAR=16.0/9.0, Info=true)
or
CR(832,0, 4,32,-6,-32, InDAR=16.0/9.0, Info=true)
https://i.postimg.cc/zfYyXgrk/Crop-Resize-02-Specify-Width.jpg
Cropping according to the output dimensions
When specifying both an output width and height, and borders aren't enabled, the script crops accordingly to prevent
aspect error (although specifying an OutDAR takes precedence over the cropping and output display aspect ratio).
Simply to demonstrate, here 16:9 output dimensions are specified.
CropResize(832,468, 4,32,-6,-32, InDAR=16.0/9.0, Info=true)
https://i.postimg.cc/W4mhD1pc/Crop-Resize-03-Specify-Width-Height-16-9.jpg
Adding borders according to the output dimensions
When specifying both an output width and height, and borders are enabled, the script adds pillarbox or letterbox
borders as required instead of cropping picture (a small amount of extra cropping may still be applied to prevent
aspect error). As for the previous example, 16:9 output dimensions are specified.
CropResize(832,468, 4,32,-6,-32, InDAR=16.0/9.0, Borders=true, Info=true)
https://i.postimg.cc/nzHMqfMj/Crop-Resize-04-Specify-Width-Height-Borders.jpg
MeGUI support
MeGUI was used to crop the source, adding it's global DAR variables and cropping to the script.
CropResize then takes care of the resizing and any extra cropping required to prevent aspect error.
global MeGUI_darx = 71
global MeGUI_dary = 36
Crop(4,32,-6,-32)
CropResize(832,0, Info=true)
https://i.postimg.cc/mkkD63YT/Crop-Resize-05-Me-GUI.jpg
Specifying an output display aspect ratio and adding borders
Cropping and resizing to NTSC dimensions with an mpeg4 display aspect ratio of 20:11 (including the added borders).
CropResize(720,480, 4,32,-6,-32, InDAR=16.0/9.0, OutDAR=20.0/11.0, Borders=true, Info=true)
https://i.postimg.cc/SsDRr1zZ/Crop-Resize-06-NTSC-20-11.jpg
Cropping according to the output display aspect ratio
When an output display aspect ratio is specified and borders aren't enabled, the script adjusts the
cropping to crop to that display aspect ratio and resizes to the specified width and height.
Here the picture is cropped to 16:9 and resized to NTSC 720x480 dimensions.
Exactly the same result can be achieved with the appropriate output sample (pixel) aspect ratio instead of
a display aspect ratio. In this case it'd be 32:37.
CropResize(720,480, 4,32,-6,-32, InDAR=16.0/9.0, OutDAR=16.0/9.0, Info=true)
or
CropResize(720,480, 4,32,-6,-32, InDAR=16.0/9.0, OutSAR=32.0/27.0, Info=true)
https://i.postimg.cc/J0FnwyxZ/Crop-Resize-07-NTSC-16-9.jpg
Resize Width Only
For the purists, there's a "Resize Width Only" mode, preventing height resizing.
It's mainly intended for anamorphic sources and supports anamorphic input/output,
but here there's no output display aspect ratio specified, so the script is automatically
cropping and resizing the width to "square pixel" dimensions.
The function name is preceded with "i" to set Info=true
iCR(0,0, 4,32,-6,-32, InDAR=16.0/9.0, ResizeWO=true)
https://i.postimg.cc/jq3Cn9T2/Crop-Resize-08-Resize-Width-Only.jpg
No Resizing
Resizing can also be disabled completely so the function only crops (it can still add borders though).
CropResize(0,0, 4,32,-6,-32, InDAR=16.0/9.0, NoResize=true, Info=true)
https://i.postimg.cc/CLZ5GNMN/Crop-Resize-09-No-Resizing.jpg
Color conversion
Probably a bit hard to see the difference here, but in addition to automatic color correction,
the ColorMode argument permits specifying a color conversion.
CropResize(832,0, 4,32,-6,-32, InDAR=16.0/9.0, ColorConvert="HDRMatrix", ColorMode="709-601", Info=true)
https://i.postimg.cc/BbjSCS36/Crop-Resize-10-Color-Conversion.jpg
Cropping previews
Output dimensions of 16:9 are specified without borders enabled (832x468) but the specified cropping
is not enough to crop the picture to 16:9, so the script must crop extra from the sides.
The yellow lines show the cropping specified by the user.
The blue lines show any additional cropping applied by the script to prevent aspect error.
The default cropping preview can be enabled by preceding the function name with "p".
pCropResize(832,468, 4,32,-6,-32, InDAR=16.0/9.0)
or
pCR(832,468, 4,32,-6,-32, InDAR=16.0/9.0)
or
CropResize(832,468, 4,32,-6,-32, InDAR=16.0/9.0, CPreview=1)
Also note: Preceding the function name with "pi" enables both the default cropping preview and sets Info=true,
assuming the wrapper functions script is loaded.
https://i.postimg.cc/pdvdtMfG/Crop-Resize-11-CPreview-1.jpg
CropResize(832,468, 4,32,-6,-32, InDAR=16.0/9.0, CPreview=2)
https://i.postimg.cc/4dL4tKrq/Crop-Resize-12-CPreview-2.jpg
CropResize(832,468, 4,32,-6,-32, InDAR=16.0/9.0, CPreview=3)
An AvsPmod style preview.
https://i.postimg.cc/9fBQmg1W/Crop-Resize-13-CPreview-3.jpg
FrostyBorders
CropDAR used to force a cropping of 4:3, with 16:9 output dimensions to demonstrate adding FrostyBorders.
CR(832,468, 4,32,-6,-32, CropDAR=4.0/3.0, InDAR=16.0/9.0, Frosty=true)
https://i.postimg.cc/vTpsLCGw/Crop-Resize-14-Frosty-Borders.jpg
hello_hello
16th July 2019, 00:49
As is always the case, I found a minor gremlin not long after creating this thread. Sometimes Info=true wasn't displaying the output sample aspect ratio when resizing was disabled. The link in the opening post has been updated. The fixed version is dated 2019-07-17.
hello_hello
7th August 2019, 20:57
There's a new version of CropResize (2019-08-08). The link in the opening post has been updated.
The changes are aimed at making the script's behaviour more predictable, although there's not a lot of them. The cropping and resizing functionality remains the same. There's a list of changes in the zip file.
FranceBB
7th August 2019, 22:14
Thank you!! :D
Just one thing:
ColorCorrection (removed)
CropResize no longer converts the colors when upscaling or downscaling.
It previously only converted between rec.601 and rec.709, and color conversion isn't technically the job of a cropping/resizing script, so color correction has been removed entirely.
Instead of removing it entirely, why don't you add it as a bool option which is "false" (disabled) by default? I think that it can be useful in automatized workflows used by some people, so if they want to, they should be able to turn it on.
That's just what I had in mind, anyway, nice resizing script, thank you! :D
hello_hello
7th August 2019, 23:13
Thank you!! :D
Just one thing:
Instead of removing it entirely, why don't you add it as a bool option which is "false" (disabled) by default? I think that it can be useful in automatized workflows used by some people, so if they want to, they should be able to turn it on.
That's just what I had in mind, anyway, nice resizing script, thank you! :D
I actually prefer to include it myself, but there's more colorspaces now, and UHD, which I never work with, so I thought maybe it was best if the script just stuck to cropping and resizing. Plus when I added it originally I had it enabled by default due to my color conversion OCD, but not everyone was crazy about that.
As I prefer it though, I added it back to a version of the script for myself. It still only converts between HD and SD with ColorMatrix.dll, but unlike the previous version it doesn't convert when the source or destination resolution exceed 1080p.
Because it was for me I didn't add an argument for it, but I included a way to disable it by changing a line about 12 lines from the bottom of the script, along with some of the other defaults. It looks like this:
function CR_ColorCorrect() { return true }
If you want a version with a function argument, it shouldn't be too hard to add it back. Anyway, here's a link for my ColorMatrix version.
Edit. Link removed. See post #8.
Aside from the color conversion, everything else is the same, including the function name.
So you know what the rules are, it automatically color converts when downscaling if the source "display" width is > 1056 or the source height is >= 600 and the destination "display" width is <= 1056 and the destination height is < 600.
Upscaling the rules are the same for source and destination width and height.
Info=true will still tell you when color conversion is taking place.
FranceBB
8th August 2019, 13:36
Got it.
Thank you for clarifying and sharing your modified personal version as well! :)
hello_hello
9th August 2019, 00:12
FranceBB,
as it turns out, you talked me into it. Color conversion has been added back to the "official" version. It's now dated 2019-08-09. I'll update the link in the opening post shortly.
I've added back the ColorCorrect argument, but rather than true or false, 0 is disabled, 1 converts with ColorMatrix.dll, and 2 converts with DitherTools. Conversion between SD, HD and UHD colorimetry is now supported.
I don't think there's a 64 bit version of ColorMatrix with Rec.2020 support, but the included 32 bit version has it. It supports YV12 & YUY2.
DitherTools supports Rec.2020 and YV12, YV16, YV24, YV411, and Y8.
The function for setting the default can still be found near the end of the script, and now looks like this.
function CR_ColorCorrect() { return 0 }
So you can enable either conversion method as the default and use ColorCorrect=0 to disable it, or leave it disabled by default and use ColorCorrect=1 (or 2) as required. I've updated the help file
Feel free to check my work. I'm new to converting with DitherTools. The color conversion section is about halfway down the script.
hello_hello
9th August 2019, 09:03
Damn!
Sorry folks, I just noticed a silly in the definition of SD, HD and UHD resolutions for color conversion. I used "or" when I should have used "and" and "and" when I should have used "or". I'll fix it shorty and update link in the opening post and change the version date to 2019-08-10.
wonkey_monkey
9th August 2019, 11:08
"and" and "and"
Buffalo buffalo buffalo Buffalo buffalo Buffalo buffalo buffalo.
hello_hello
9th August 2019, 11:27
The opening post is updated again now. I didn't change the version date again as the link was only active for a few minutes before I pulled it to upload a version that also checks for bitdepth when using Avisynth+, as currently only 8 bit video is supported for automatic color correction. Now I remember why I removed it originally. :)
I don't actually know how to color convert video with bitdepths greater than 8 bit, but I've come this far....
What's used for color conversion these days (I won't bother with stacked 16 bit, but for native Avisynth+ bitdepths > 8)?
Maybe I should also add an argument for specifying an output bitdepth?
Cheers.
hello_hello
9th August 2019, 12:44
Buffalo buffalo buffalo Buffalo buffalo Buffalo buffalo buffalo.
I had to google that one. I hadn't come across it before. Interesting.... :)
FranceBB
9th August 2019, 15:42
FranceBB,
as it turns out, you talked me into it. Color conversion has been added back to the "official" version. It's now dated 2019-08-09. I'll update the link in the opening post shortly.
I've added back the ColorCorrect argument, but rather than true or false, 0 is disabled, 1 converts with ColorMatrix.dll, and 2 converts with DitherTools. Conversion between SD, HD and UHD colorimetry is now supported.
I don't think there's a 64 bit version of ColorMatrix with Rec.2020 support, but the included 32 bit version has it. It supports YV12 & YUY2.
DitherTools supports Rec.2020 and YV12, YV16, YV24, YV411, and Y8.
The function for setting the default can still be found near the end of the script, and now looks like this.
function CR_ColorCorrect() { return 0 }
So you can enable either conversion method as the default and use ColorCorrect=0 to disable it, or leave it disabled by default and use ColorCorrect=1 (or 2) as required. I've updated the help file
Feel free to check my work. I'm new to converting with DitherTools. The color conversion section is about halfway down the script.
Wow, that's great!
I don't actually know how to color convert video with bitdepths greater than 8 bit, but I've come this far....
What's used for color conversion these days (I won't bother with stacked 16 bit, but for native Avisynth+ bitdepths > 8)?
Maybe I should also add an argument for specifying an output bitdepth?
Cheers.
In the normal Avisynth, 16bit stacked and interleaved are used; since you are using Dither Tools, you may wanna use 16bit stacked as it's easier to implement giving the way you are doing it for 8bit already. Anyway, if you wanna check for Avisynth+ high bit depth, in order to go from BT2020 SDR to BT709 SDR and vice versa I personally use HDRTools by JPSDR, which supports native high bit depth (10/12/14/16 bit planar). Anyway, that's not gonna work for folks who use regular Avisynth.
hello_hello
9th August 2019, 17:23
In the normal Avisynth, 16bit stacked and interleaved are used; since you are using Dither Tools, you may wanna use 16bit stacked as it's easier to implement giving the way you are doing it for 8bit already. Anyway, if you wanna check for Avisynth+ high bit depth, in order to go from BT2020 SDR to BT709 SDR and vice versa I personally use HDRTools by JPSDR, which supports native high bit depth (10/12/14/16 bit planar). Anyway, that's not gonna work for folks who use regular Avisynth.
The problem with a stacked 16 bit input is it doubles the height of the video, which means I'd probably need to rework a lot of the script so an LSB input can be specified and it can still calculate the correct cropping and resizing and pass the info to DitherTools.
There's an included resizing wrapper function (CR_Resize16X) that uses the ResizeX script and DitherTools to resize in 16 bit, and it can be configured to output a stacked 16 bit clip, but even that would throw a spanner in the works as the script decides whether to add borders and color correct after resizing, and it'd probably calculate the wrong DAR for MeGUI even though it'd still crop and resize correctly. Given stacked 16 bit is a legacy format, I'm not sure it's worth accommodating.
I looked at avsresize, but the order in which the script does things would probably require a bit of adjusting because it'd be silly to not have it do both the resizing and color conversion. Plus it appears not to run on XP (I assume that's the problem).
I'll check out HDR Tools at some stage though, when I'm not bored with looking at the script. If it'll simply color convert any native Avisynth+ bitdepth as ColorMatrix does for 8 bit, then I can probably add the color conversion without having to worry about the input/output bitdepth as such.
Assuming it runs on XP? If not, I'll have to modify the script and ask you to test it for me. ;)
PS And what about HDR video? Should I think about that or is it impossible to have the script handle it automatically (in respect to color correction)?
FranceBB
10th August 2019, 15:04
Right, 16bit stacked or interleaved output MSB and LSB stacked or interleaved one with the other, so it would screw up the calculation made by the script as the resolution would be wrong. As to HDRTools by JPSDR, I can tell you that it works absolutely fine on Windows XP, however it might require a lot of RAM for UHD sources and BT2020 to be processed with 16bit precision and that's an issue for 32bit systems 'cause it would have to be split using MPPipeline in order to avoid to hit the maximum memory available per single process. Anyway, as to HDR, that's not an easy task, as you are no longer dealing with resolutions and color matrices, but with color curves. Hence, there isn't a perfect mathematical formula to go from a curve to another and the way you would be bringing something to something else would be according to what looks best for you and once you have done it, there's no way to go back. What I mean by this is that you should think about PQ, HLG and BT709 linear as curves and in order to go from a curve to another you need a function that takes some values in input and outputs some other values... however, from our Calculus class we know that functions can be 1 to 1 or onto and if they are both 1 to 1 and onto then they are bijective. Viewing this in a linear algebra setting means that the matrix of linear transformation associated with our function is an isomorphism which basically means that we can go back and forth between the input and the output losslessly 'cause we can invert them, but when you are dealing with PQ, HLG and BT709 linear, there's no way to have an isomorphism and to go back to where you started losslessly.
I've been talking about this more in depth in my "FranceBB LUT Collection" as I thought that it was an interesting topic for linear algebra lovers and because companies were selling matrices of linear transformation for 200 bucks each while I really wanted to make mine open source and offer them for free.
Anyway, back to our original topic, I think that using HDRTools to deal with UHD would require a not so hard modification to the code as you can see the command for the conversion between BT2020 SDR and BT709 SDR in the very first page of Jean Philippe's topic. As to HDR, I would be very reluctant about including it 'cause:
- There's no way to know whether an HDR source is HDR except for the metadata that you would have to check from the indexer if the indexer does pass them, as Avisynth doesn't know anything about color curves.
- even if you manage to get the information from the indexer 'cause it passes it, there's no way to be 100% sure that whoever encoded the file actually included the right metadata. I've seen far too many files wrongly flagged by either Studios or NLE, or cameras.
- it's not just PQ and HLG, there are many other color curves like C-log, log-C, Slog1, Slog2, Slog3, F-log, D-log...
- There isn't a clear mathematical connection between curves and the function that it's used to go from one to another and you will always have to make sure that the conversion is both mathematically correct and it looks good according to your taste which the user might not like (linear transformation, tonemapping algorithms like Hable, Möbius and Reinhard etc).
For all these reasons, I would not include HDR conversion in the script. Trust me, it's a far too big subject that still makes us (broadcast encoder) think...
hello_hello
11th August 2019, 19:26
FranceBB,
Thanks for all the info! There's a couple of things that I don't quite understand though. The HDR Tools docs say:
"If you want a true correct precise/perfect conversion, I would advise you to use a resampler and feed directly to YV24."
Does "resampler" mean something other that the built in Avisynth Convert function?
Also, there's two types of Rec.601. Color=3 (BT601_525) and Color=4 (BT601_625). My understanding is the PAL and NTSC colorimetry is the same in digital-land, so I don't understand the distinction here when everyone else only refers to a single flavour of Rec.601.
I experimented a little and it's doing my head in.
My Source is rec.709 and I'm downscaling it. Converting between rec.709 and rec.601 seems consistent for each method, aside from HDR Tools causing some banding above the guy's head on the right. You might have to run it full screen to see it.
A ConvertYUVtoXYZ(Color=2).ConvertXYZtoYUV(Color=3, pColor=2, OutputMode=2)
https://i.postimg.cc/Cd81fMWP/A.png (https://postimg.cc/Cd81fMWP)
B Dither_convert_yuv_to_rgb(matrix="709", slice=false).Dither_convert_rgb_to_yuv(matrix="601", output="YV12")
https://i.postimg.cc/GBNLH6zn/B.png (https://postimg.cc/GBNLH6zn)
C ColorMatrix(mode="Rec.709->Rec.601", clamp=0)
https://i.postimg.cc/N5w08qtg/C.png (https://postimg.cc/N5w08qtg)
Keep in mind these are all being converted to RGB using rec.601 on playback, but I don't think that should prevent the result being the same each time.
DitherTools and ColorMatrix agree on rec.709 <-> rec.2020 conversions but HDR Toiols doesn't. I copied the syntax from the help file.
D ConvertYUVtoXYZ().ConvertXYZtoYUV(Color=1, pColor=2, OutputMode=2)
https://i.postimg.cc/2bZzvTXb/D.png (https://postimg.cc/2bZzvTXb)
E Dither_convert_yuv_to_rgb(matrix="709", slice=false).Dither_convert_rgb_to_yuv(matrix="2020", output="YV12")
https://i.postimg.cc/qg2Jvb3W/E.png (https://postimg.cc/qg2Jvb3W)
F ColorMatrix(mode="Rec.709->Rec.2020", clamp=0)
https://i.postimg.cc/K10vy1Mz/F.png (https://postimg.cc/K10vy1Mz)
DitherTools and ColorMatrix don't agree on rec.601 <-> rec.2020 conversions, and I still couldn't get anything sensible out of HDR Tools.
G ConvertYUVtoXYZ(Color=1).ConvertXYZtoYUV(Color=3, pColor=1, OutputMode=2)
https://i.postimg.cc/jn6t32TR/G.png (https://postimg.cc/jn6t32TR)
H Dither_convert_yuv_to_rgb(matrix="2020", slice=false).Dither_convert_rgb_to_yuv(matrix="601", output="YV12")
https://i.postimg.cc/sB1ff3YJ/H.png (https://postimg.cc/sB1ff3YJ)
I ColorMatrix(mode="Rec.2020->Rec.601", clamp=0)
https://i.postimg.cc/bD7wF429/I.png (https://postimg.cc/bD7wF429)
All the above was done with classic Avisynth on XP, but a quick look indicated it's the same for Avisynth+.
By the way, I may have missed it, but what does the XYZ in ConvertXYZtoYUV etc actually stand for?
Cheers.
hello_hello
12th August 2019, 16:10
I was hoping I'd uploaded the last version, aside from sorting out the color correction, but a bug managed to slip past the keeper.
Fixed an incorrect output display aspect ratio calculation when NoResize=true and an input sample aspect ratio was specified. The script was still cropping correctly, but the output display aspect ratio calculation was wrong.
New version in the opening post dated 2019-08-12.
FranceBB
13th August 2019, 17:49
what does the XYZ in ConvertXYZtoYUV etc actually stand for?
The XYZ colorspace rather than YUV.
This is because HDRTools allows you to do the conversion in either RGB or XYZ and then it allows you to convert back to YUV.
In the screenshot you posted about BT2020 SDR, I would trust HDRTools as it's normal that colors look off if you view it with a player and a display that don't know anything about BT2020.
For instance, this is sample in BT709 yv12 8bit planar:
https://i.imgur.com/ZdTGLHQ.png
This is the conversion to BT2020 XYZ:
https://i.imgur.com/G8lSDoC.png
And this is the final output of the BT2020 yv24:
https://i.imgur.com/pgiJOJ9.png
This is another example:
BT709 yv12:
https://i.imgur.com/XCJMYCf.png
BT2020 XYZ:
https://i.imgur.com/qXqX19Y.png
BT2020 YUV:
https://i.imgur.com/m27dlef.png
Of course if you playback the file on a good player, let's say MPV, and on a screen that's capable of representing the BT2020 SDR colorspace, then you're gonna see colors in the right way.
Even if you use MPV on a BT709 only capable display, you're very likely gonna see the right colors as MPV is gonna convert it back to BT709 SDR by inverting the process and re-mapping the BT2020 into BT709.
This is the ATP Masters 1000 Montreal, Canada, which is currently on air on Sky Sports:
BT709 yv12:
https://i.imgur.com/zcvNlPp.png
BT2020 XYZ:
https://i.imgur.com/8y0qUI5.png
BT2020 yv24:
https://i.imgur.com/rESwLRk.png
This is simply done by using:
ConvertYUVtoXYZ()
ConvertXYZtoYUV(Color=1,pColor=2)
Does "resampler" mean something other that the built in Avisynth Convert function?
I think so, 'cause the more precision you have, the better. Anyway, since you said that this is all done in normal Avisynth, I think that HDRTools is using 8bit precision and that's why you're seeing banding.
I gotta be fair, though, I've never used HDRTools for BT601 to BT2020 conversion, but only for BT709 SDR to BT2020 SDR and vice-versa and I gotta say that I'm pretty sure that it's doing a good job in that, but I have no idea about how it's handling BT601. I've also been using it to apply tone-mapping to my source to go from HDR PQ and HLG to BT709 and I tried the three tone-mapping algorithms and I found out that Reinhard was the best one (I made a long post about the comparison), anyway, once again, I've never used it for BT601 to BT2020 conversion, however these differences are unexpected. I mean, I expected similar results when going from a color matrix to another... There must be something wrong, but I don't know what.
hello_hello
14th August 2019, 17:49
Thanks for the info again FranceBB!
So XYZ is an actual colorspace? I'll have to research it.
I'll probably take some more screenshots and start a new thread rather than bog this one down with the color conversion stuff. I still think the result should be the same each time, even if the Avisynth output is always being converted to RGB by MPC-HC with rec.601 when viewing it. Even if it looks completely wrong, I'd have assumed the wrongness should be the same no matter which program is doing the conversion.
Thanks again.
FranceBB
14th August 2019, 18:44
So XYZ is an actual colorspace? I'll have to research it.
Sure! :) Link (https://en.wikipedia.org/wiki/CIE_1931_color_space)
Too bad that it isn't actually officially supported by Avisynth+ 'cause it's used in Digital Cinema; for instance, I was trying to convert things to it a few days ago when I was trying to encode a DCP (https://forum.doom9.org/showthread.php?t=176702) (Digital Cinema Package) encoded in Motion JPEG 2000 XYZ.
Even if it looks completely wrong, I'd have assumed the wrongness should be the same no matter which program is doing the conversion.
Well, yes, that's what I expected as well, which is why I don't understand what's going on and why we're getting those very different results.
ChaosKing
14th August 2019, 19:30
Sure! :) Link (https://en.wikipedia.org/wiki/CIE_1931_color_space)
Too bad that it isn't actually officially supported by Avisynth+ 'cause it's used in Digital Cinema; for instance, I was trying to convert things to it a few days ago when I was trying to encode a DCP (https://forum.doom9.org/showthread.php?t=176702) (Digital Cinema Package) encoded in Motion JPEG 2000 XYZ.
I'm not sure if it helps, but I saw that vapoursynth mentions XYZ in "resize" (use strg+f ;-)
http://www.vapoursynth.com/doc/functions/resize.html
p.s you can easily use avisynth stuff in VS with avsproxy
FranceBB
14th August 2019, 19:41
I'm not sure if it helps, but I saw that vapoursynth mentions XYZ in "resize" (use strg+f ;-)
http://www.vapoursynth.com/doc/functions/resize.html
p.s you can easily use avisynth stuff in VS with avsproxy
Wow! Hold on a second, you're telling me that not only VapourSynth supports XYZ, but it also supports a lot of other interesting things like log! I really hope that Ferenc will port them to Avisynth+ when he has time, not that he has much time, giving the million other things he is planning to do for Avisynth+.
hello_hello
14th August 2019, 20:33
I haven't looked hard but I can't see what strg+f refers to yet. :(
I've done some more testing and I'll start a new thread later, but converting in one direction only, here's the highlights. At the moment I'm tempted to say DitherTools would be getting it right, but I don't know for sure.
HDRTools "Linear" refers to this sort of thing: ConvertYUVtoLinearRGB().ConvertLinearRGBtoYUV()
Rec.709 To Rec.601
All conversion methods agree. HDR Linear looks better than HDR XYZ (no banding).
Rec.2020 To Rec.601.
DitherTools and HDR Linear agree.
ColorMatrix different, HDR XYZ seems borked.
Rec.2020 To 709.
I'd only be guessing as nobody agrees.
DitherTools and HDR Linear possibly only disagree for "red".
I think ColorMatrix is wrong.
I think HDR XYX is even wrongerer. :)
I should upload the images shortly and start the new thread before I lose interest again....
Edit: A bit of a delay. I just realised I was using DitherTools 1.27.1. I'll redo the DitherTools conversions with 1.27.2 before starting the new thread in case that changes things. Damn...
Edit: The two versions of DitherTools are identical.
Edit: Here's the new thread. https://forum.doom9.org/showthread.php?p=1881952#post1881952
ChaosKing
14th August 2019, 22:16
I haven't looked hard but I can't see what strg+f refers to yet. :(
I meant use STRG+F (=Browser search function) to search for xyz on the website :D
pinterf
15th August 2019, 08:41
Wow! Hold on a second, you're telling me that not only VapourSynth supports XYZ, but it also supports a lot of other interesting things like log! I really hope that Ferenc will port them to Avisynth+ when he has time, not that he has much time, giving the million other things he is planning to do for Avisynth+.
z_ConvertFormat
https://forum.doom9.org/showthread.php?t=173986
"See VapourSynth documentation for valid string constants."
hello_hello
15th August 2019, 10:56
I meant use STRG+F (=Browser search function) to search for xyz on the website :D
Ahhhh.... You mean Ctrl+F? :)
That only opens a page search for my browser.
ChaosKing
15th August 2019, 11:13
Ahhhh.... You mean Ctrl+F? :)
That only opens a page search for my browser.
omg german (keyboard) brain xD
strg = ctrl
hello_hello
15th August 2019, 13:35
omg german (keyboard) brain xD
strg = ctrl
Yeah, I did a google search for that one. :)
hello_hello
16th August 2019, 18:38
There's an updated version of CropResize in the opening post, blocking colorMatrix from being involved in Rec.2020 conversions. DitherTools can be used instead. I still have plans to add high bitdepth color correction at some stage, but in the mean time.....
The new version is dated 2019-08-17.
hello_hello
3rd September 2019, 04:34
There's an updated version of CropResize in the opening post, dated 2019-09-02. With any luck that'll be it for quite a while, as the script's color correction (converting the colorimetry when upscaling/downscaling) was the only thing left to sort.
Under "ColorCorrect" in the help file, there's a mini essay on my current understanding of color conversion, when to convert and how to do it.
There's now four conversion choices.
1. ColorMatrix
2. DitherTools
3. HDRTools (170m for SD)
4. HDRTools (470bg for SD)
DitherTools can no longer be used for Rec.2020 conversions, but if it's converting the colors, DitherTools will do the resizing too (when a compatible resizer is specified). Only standard dynamic range is supported. I don't think HDR to SDR conversions can be done automatically, I've almost no experience with HDR, and I've no interest in HDR anyway.
Some other changes -
- Avisynth 2.5.8 is no longer supported. As it turns out, the script was already using a couple of functions not available in Avisynth 2.5.8.
- Added a PicDim argument for adjusting how much the picture is dimmed when Info=true. The default is -75. The range is -255 to 0.
- Tweaked Info=true. The displayed info scales a little better with resolution. The source color format and bitdepth are now displayed.
I also noticed an Avisynth+ oddity that causes negative zero (such as a right or bottom cropping of zero) to be displayed with the negative sign under some circumstances. I added a workaround to prevent zero from displaying as a negative, because it was annoying me.
For anyone interested, Avisynth+ displays this as 0
zz = float(-0)
subtitle(string(zz))
but displays this as -0
zz = float(0)
subtitle(string(-zz))
Avisynth 2.6 doesn't display the negative sign either way.
In case I did a stupid, there's still a link for the 2019-08-17 version in the opening post, but the new version should be fine.
hello_hello
10th September 2019, 12:46
This isn't an update to the script itself, as it's exactly the same as the version dated 2019-09-02, but I've update the help file a little. There's no longer any optional plugins included with the script, but there's still links for them at the top of the help file. Including plugins in the zip file was only supposed to be a temporary thing as they'll become outdated.
Even though the script itself is unchanged, I've updated the version to 2019-09-10. There's a new link in the opening post.
hello_hello
20th September 2019, 04:28
I assume nobody is using the global GCropResize function, given nobody's complained about it not working and the last version broke it.
Changes 2019-09-20:
- Fiddled with Info=true again. The Avisynth and CropResize versions are now displayed.
For an anamorphic source and/or output, the source and/or output "display dimensions" are included (right column). The height is the source/output height. The width is the source/output width, as it would be when resized to "square pixel" dimensions on playback. If necessary, "display width" is rounded to an integer (a whole pixel).
- Avisynth Neo probably didn't work correctly with CropResize. Added a check for Neo, although the script doesn't do anything "Neo specific". It now assumes Avisynth+ is being used when Neo is detected.
- The GCropResize function was completely broken after the last update. If GCropResize was used an error message displayed (due to a typo).
hello_hello
20th September 2019, 10:12
If anyone has downloaded the 2019-09-20 version before reading this, or before the 21st, please download it again. I haven't change the version date but I somehow broke Info=true, despite being positive I checked it before uploading the script. Sigh....
hello_hello
7th January 2020, 15:56
I've uploaded a new version of CropResize dated 2020-01-07. There's a link in the opening post along with a summary of changes since the previous version.
I've also updated the pictures illustrating CropResize usage in the second post.
redbtn
7th January 2020, 19:06
Do you have any plans to release Vapoursynth version?
hello_hello
7th January 2020, 20:41
redbtn,
I know nothing about Vapoursynth. I have an old machine running Win7 now (previously only XP), so I have plans to install Vapoursynth and learn to use it, but knowing enough to create a native Vapoursynth version is a "maybe sometime later this year" thing at best.
I do recall bumping into a post a while back where someone had an old version of CropResize working in Vapoursynth...
Here it is.... https://forum.doom9.org/showthread.php?p=1830238#post1830238
Is the avsproxy (https://forum.doom9.org/showthread.php?t=175141) plugin a way to use CropResize? Or vsavsreader (https://forum.doom9.org/showthread.php?t=165957)?
I ask, as I have no idea.
redbtn
8th January 2020, 00:34
@hello_hello thank you for reply! I have no experience to run AVS Plugins in VS, but I'll try.
hello_hello
25th January 2020, 14:15
Another update for CropResize, simply to add a "Position" argument for displaying the current frame number and position in time over the video. Sometimes it's handy and it saves having to use a separate function.
Enabling it requires GRunT. http://avisynth.nl/index.php/GRunT
The new version is dated 2020-01-25, and as usual, there's a link in the opening post.
hello_hello
30th January 2020, 03:20
Sorry folks, but another update. I discovered I'd added a line to the script for testing the color conversion and forgot to remove it, causing the script to throw an error for sources with a bitdepth greater than 8 when color converting with HDRTools. The new version is dated 2020-01-30 and the link is in the opening post.
hello_hello
26th March 2020, 07:41
There's a link for an updated version of CropResize in the opening post, containing some minor fixes. The new version is dated 2020-03-26. There's a text file included describing the changes.
hello_hello
22nd June 2020, 20:16
There's a link for an updated version of CropResize in the opening post, containing fixes for a couple of obscure aspect ratio bugs when specifying an Output DAR. The new version is dated 2020-06-23.
Another link:
CropResize 2020-06-23.zip (https://files.videohelp.com/u/210984/CropResize%202020-06-23.zip)
hello_hello
12th September 2020, 05:43
There's a link for an updated CropResize in the opening post dated 2020-09-11. There's a summary of changes above the link.
hello_hello
28th October 2020, 17:07
There's a link for an updated CropResize in the opening post dated 2020-10-28. It fixes a minor color conversion gremlin. Details in the "Changes" text file.
hello_hello
30th October 2020, 04:52
Sorry about an update so soon. It was just to fix some obsolete information in the help file, but I changed the version date to 2020-10-30.
There be a link in the opening post.
hello_hello
5th November 2020, 11:28
Mainly a little more fiddling with the color correction. New version dated 2020-11-05.
Danette
24th December 2020, 00:49
Edit: Sorry about the essay, but hopefully this will help makes things clearer. :)
The script simply uses the supplied InDAR to base the calculations on. If no InDAR/InSAR is specified, it assumes the source is non anamorphic (square pixels). If you were to do the following, it wouldn't crop at all as the InDAR and output DAR (resolution) are the same. Info=true will show you what it's doing.
CropResize(640,480, 0,0,0,0, InDAR=4.0/3.0, Info=true)
For the following it barely crops as the output dimensions almost match the InDAR.
CropResize(652,480, 0,0,0,0, InDAR=15.0/11.0, Info=true)
For the next example, the shape of objects in the picture will be exactly the same after resizing as for the previous one, but because the output width is narrower this time, it has to crop the sides.
CropResize(640,480, 0,0,0,0, InDAR=15.0/11.0, Info=true)
So it's not agreeing about the AR, or auto-cropping in the traditional sense, it's just preventing an aspect error based on the InDAR and output dimensions. It just happens that InDAR=15.0/11.0 requires 16 pixels to be cropped from the width if you want a 4:3 output. If you want to use that InDAR (which I think we decided is correct), but don't want to crop, you can increase the output width a bit.
Think of any specified cropping as the minimum cropping, but the script will increase it as required to prevent aspect error. To see what's being cropped, enable a cropping preview. The yellow lines are the specified cropping and any blue lines are the additional script cropping. The video isn't resized while the cropping preview is enabled.
CropResize(640,480, 10,4,-6,-4, InDAR=15.0/11.0, CPreview=1, Info=true)
For a 16:9 DVD the equivalent InDARs are (and specifying 16:9 output dimensions for resizing).
CropResize(768,432, 0,0,0,0, InDAR=16.0/9.0) - generic DAR
CropResize(768,432, 0,0,0,0, InDAR=20.0/11.0) - mpeg4 DAR
The main idea of CropResize is to crop and resize without having to calculate aspect error and adjust the cropping or resizing manually to prevent it. An example might be cropping a 1080p source and resizing to 720p. If you don't specify a height (use zero instead), the script will apply your cropping and then pick the appropriate height for you. Because it's free to pick the height, any additional cropping to prevent aspect error will be fairly minimal. You can do exactly the same thing with a DVD source as long as you use the correct InDAR
(cropping a 1080p source like this would mean you have a video with a 2.40:1 aspect ratio after cropping the black).
CropResize(1280,0, 4,140,-2,-142)
If you were to specify the same cropping as above with 4:3 output dimensions (still a 1080p source), it'd apply the specified cropping, then crop a huge amount from each side to give you a 4:3 output without distorting the picture.
CropResize(720,540, 4,140,-2,-142)
I find it very handy when working with video where the amount of black varies quite a bit (usually old DVDs), but I'm OCD about cropping it all. So I can do something like the following, specifying enough cropping to remove the black, without having to worry about distorting the picture, because CropResize won't let me.
Trim(0,1596).CropResize(640,480, 8,0,-8,0, InDAR=15.0/11.0) ++ \
Trim(1597,1884).CropResize(640,480, 16,2,-8,-4, InDAR=15.0/11.0) ++ \
Trim(1885,2597).CropResize(640,480, 24,4,-12,-2, InDAR=15.0/11.0) ++ \
Trim(2598,0).CropResize(640,480, 8,0,-8,0, InDAR=15.0/11.0)
But anyway... what I was trying to explain in my previous post, is if you were to decide the source is 4:3 after you only crop 14 pixels from the sides, you can do it by specifying the appropriate InDAR, and that's the DAR the script will base it's calculations on. Use Info=true and you'll see it's only cropping 7 pixels each side here instead of 8.
CropResize(640,480, InDAR=1.35977, Info=true)
CropResize does have a "traditional" auto-cropping option. It requires the AutoCrop plugin (autocrop.dll). When it's enabled, the source is auto-cropped with autocrop.dll, any specified cropping is applied to the auto-cropped video, if necessary the script applies additional cropping to prevent aspect error, then it resizes. Try the following. Assuming auto-crop crops some or all of the black from the sides, the script will then crop 8 more pixels each side, and to prevent aspect error it'll crop a few pixels top and bottom before resizing to 4:3 dimensions.
CropResize(640,480, 8,0,-8,0, AutoC=true, InDAR=15.0/11.0, Info=true)
If you don't specify a height, you probably won't end up with a 4:3 output, but at the same time the script probably won't have to crop much extra picture to prevent aspect error.
CropResize(640,0, 8,0,-8,0, AutoC=true, InDAR=15.0/11.0, Info=true)
Thought it best to move this discussion here, since we are now focusing on this interesting ”CropResize” creation.
I’m trying to digest all of this and, after reading the above from the “Moire Effect & TFM(pp=0) Solution” thread and your initial post in this thread, I may be getting closer to understanding what this does and how I might prefer to use it.
As you may recall, I would accept borders, and even some edge video degradation, in order to retain as much content as possible. I think I’m becoming more interested in using the AutoCrop function in combination with cropping width only, as shown in one of your examples. So, trying to put it all together, I’ve come up with this as a way to meet my goals:
iCropResize(640,480,AutoC=true,InDAR=15.0/11.0,ResizeWO=true,Info=true)
Does it make sense? Would using CleanBorders=true, instead of ResizeWO=true, also crop width only? Is there any advantage to using one vs. the other?
After setting this for a an entire TV series, I suppose that I’ll have to try to find those one or two known circles/spheres and./or squares to verify correct AR as well as keeping an eye on those left and right crops to make sure I’m ok with what is going on there.
hello_hello
24th December 2020, 14:28
Here's another essay for you. :)
For anyone else reading this post, we're talking about how to crop and resize a 4:3 NTSC DVD here, but specifying an mpeg4 DAR of 15:11 (1.36364) for the DVD instead of 4:3 (1.33333).
For the explanation of the different modes, I'll ignore auto-cropping for the moment. You're probably aware how anamorphic encoding works, so sorry if the "NoResize mode" explanation is stating the obvious.
When resizing is disabled completely (NoResize=true), the script only crops. So for an anamorphic source you need to set the correct sample aspect ratio when encoding, which would be -sar 10:11 in the encoder command line in this case. The sample aspect ratio isn't changed by cropping (only by resizing), so you can crop, set the SAR for the encoder, and the player will resize the encoded video to the correct aspect ratio on playback, just as it does for the DVD. The CropResize output dimensions are completely ignored when resizing is disabled (unless adding borders is enabled), so they might as well be zero.
CropResize(0,0, 8,0,-8,0, InDAR=15.0/11.0, NoResize=true) # Set -sar 10:11 for the encoder. The output will be 704x480.
The above is exactly the same as simply cropping, but for CropResize, Info=true will tell you the correct SAR to use for encoding, based on the specified DAR.
Crop(8,0,-8,0)
Reduce the cropping each side if 8 pixels crops picture, or don't crop at all, set -sar 10:11 for the encoder, and let the player resize the encoded video (if you specify InDAR=4.0/3.0, Info=true will tell you 8:9 is the SAR, and if don't crop, it would show the video would be resized to exactly 4:3 on playback).
CleanBorders also disables resizing, as it's purpose is only to replace the existing borders with clean ones. If the amount of cropping is uneven, CleanBorders centres the picture. The output dimensions are always the same as the source dimensions, so they might as well be zero. Whatever you crop/auto-crop is replaced with black borders.
CropResize(0,0, 8,2,-8,-2, InDAR=15.0/11.0, CleanBorders=true) # Set -sar 10:11 for the encoder and the output will be always be 720x480 with a 15:11 DAR.
Resize Width Only mode defaults to resizing to square pixel dimensions, and both the output width and height are ignored (unless you set an OutDAR or enable adding borders), so once again they might as well be zero.
CropResize(0,0, 8,0,-8,0, InDAR=15.0/11.0, ResizeWO=true) # Based on the specified cropping and InDAR, the output will be 640x480.
The following would output 640x476.
CropResize(0,0, 8,2,-8,2, InDAR=15.0/11.0, ResizeWO=true)
If you cropped a little more from the sides, you'd end up with 636x476.
CropResize(0,0, 10,2,-10,2, InDAR=15.0/11.0, ResizeWO=true)
As far as auto-cropping goes, you don't know how much it'll crop from the sides if the amount of black varies, or if there's sometimes black top or bottom, so as per the above examples, there's no guarantee the output dimensions will be the same every time for either ResizeWO or NoResize, whereas full resizing mode can do whatever it likes to always output the specified dimensions.
Although keep in mind ResizeWO might still have to crop an extra pixel or three after auto-cropping so it can resize the width without distorting the picture. That's partly because by default, both ResizeWO and NoResize output mod4 dimensions (width and height both evenly divisible by 4). I don't necessarily recommend it, but you can change that to mod2 so ResizeWO has a little more freedom when resizing the width, and therefore any extra cropping would be quite minimal. For NoResize mode, mod2 means it'll never crop more than was cropped by auto-crop, unless you specify manual cropping too.
CropResize(0,0, AutoC=true, InDAR=15.0/11.0, Mod=2, ResizeWO=true)
So there's no perfect answer if you auto-crop. It depends if you want the same output dimensions each time. As you'd rather not crop picture, if you're happy to keep a little of the black, I'd consider forgetting about auto-cropping and resize to square pixel dimensions this way:
CropResize(0,0, 3,0,-3,0, InDAR=15.0/11.0, ResizeWO=true)
Or in this case, the following does exactly the same thing:
CropResize(648,480, 3,0,-3,0, InDAR=15.0/11.0)
The total cropping each side will always be 3.6 pixels, it'll probably never be enough to crop picture (even if it doesn't crop all the black), the height will never be cropped or resized, and the output will always be 648x480.
Hopefully that made things a little easier to understand rather than more confusing. :)
bruno321
29th December 2020, 07:15
Thanks for this, I've been using it really often, only for resizing according to SAR or DAR though, no cropping.
Something I noticed is: if I use CropResize(InSAR=8.0/9.0) to emulate a generic NTSC "4:3" situation, it resizes from 720x480 to 640x480. I'd prefer it resized it to 720x540 -- upsizing, not downsizing, as happens when playing back a DVD encode with 8:9 SAR. Why does CropResize downsize in this case, and can I make it always upsize instead?
hello_hello
29th December 2020, 23:47
It only does that for 4:3 NTSC DVDs, as the default output dimensions are the source height (after any cropping), and the width resized to square pixel dimensions (after any cropping). Without increasing the height, 4:3 NTSC DVDs are the only DVDs that require the width to be resized down.
You can specify any 4:3 output dimensions you like though.
CropResize(720,540, InSAR=8.0/9.0)
CropResize(624,468, InSAR=8.0/9.0)
Keep in mind if the output dimensions (for square pixel resizing) don't match the source display aspect ratio, the script will crop whatever is required to prevent aspect error, so if in doubt only specify a width, or only the height, and the script will choose the appropriate height or width for you.
CropResize(720,0, InSAR=8.0/9.0)
CropResize(0,540, InSAR=8.0/9.0)
It's a good idea to resize that way if there's a fair bit of black to be cropped and you don't know what the output dimensions should be. For example, if you cropped a 16:9 NTSC DVD like this, you could pick the width (I chose 868 for no particular reason) and the script would take care of the height based on the InSAR or InDAR.
CropResize(868,0, 2,42,-2,-42, InSAR=32.0/27.0) # the output would be 868x404
One other thing to keep in mind, if you were to crop before resizing with CropResize, you'd have to specify the sample/pixel aspect ratio, not the original display aspect ratio, as cropping changes the display aspect ratio. For an NTSC 16:9 DVD, this would produce exactly the same result as above.
Crop(2,42,-2,-42)
CropResize(868, InSAR=32.0/27.0)
Whereas this would resize incorrectly.
Crop(2,42,-2,-42)
CropResize(868, InDAR=16.0/9.0)
For non-anamorphic sources it doesn't matter, because there's no InSAR/InDAR required.
bruno321
30th December 2020, 07:16
Hmm, I guess the advantage of CropResize for me is precisely that I can quickly preview how the final encode is going to look, without having to do the math manually each time. But I'm not seeing how to do that here, given that I typically like to CropResize after manually cropping the black bars out. If I cropped on both height and width, then how can I input to CropResize a SAR of 8/9 and have it give me an upsized result, without manually specifying to it what width or height I wish it to have (like you did with the 868 above)?
If that doesn't exist, perhaps an extra option "Upsize=true" that would always prevent downsizing would be called for? I'd be grateful for it :)
hello_hello
30th December 2020, 13:45
An option to upsize isn't out the question. You can't specify output dimensions manually? If not, this does it easily enough.
# ========== UpSizeMe ===========================================================
#
# For automatically resizing NTSC 4:3 DVDs based on
# the cropped width, rather than the cropped height.
#
# Crop(10,4,-6,-6)
# CropResize(UpSizeMe(), InSAR=8.0/9.0)
#
# "Mod" adjusts the width to be used for resizing to a particular mod.
# The default is mod 4.
#
# When "Up" is true, if the cropped width isn't a "Mod" width,
# it's increased to the next mod width up, otherwise it's
# reduced to the next mod width down.
# The default is true.
#
# ===============================================================================
function UpSizeMe(clip Source, int "Mod", bool "Up") {
Mod = default(Mod, 4)
Up = default(Up, true)
CroppedWidth = width(Source)
OutWidth = Up ? ceil(float(CroppedWidth) / float(Mod)) * Mod : \
floor(float(CroppedWidth) / float(Mod)) * Mod
return OutWidth }
# ===============================================================================
Crop(10,4,-6,-6)
CropResize(UpSizeMe(), InSAR=8.0/9.0)
CropResize will resize using the cropped width as the OutWidth. It's output will be 704x528 for the example above, rather than 624x468.
If you want the output to be 4:3 each time (even if it requires cropping a little extra picture), use the CropDAR argument.
CropResize(UpSizeMe(), CropDAR=4.0/3.0, InSAR=8.0/9.0)
The output dimensions will be as close to 4:3 as the mod option allows, which for CropResize defaults to mod4 for the width and height. It's only used when CropResize has to choose one or both of them. When you specify output dimensions, you get what you asked for.
CropResize(UpSizeMe(), CropDAR=4.0/3.0, InSAR=8.0/9.0, Mod=4)
hello_hello
31st December 2020, 13:53
bruno321,
I had another idea, so here's a couple of functions. The one you'll want for your 4:3 NTSC DVDs is NCrop().
Simply add your cropping to a script, then add "N" to the beginning of "Crop".
Add the cropping to a script.
Crop(10,4,-6,-6)
Change the function name to NCrop.
NCrop(10,4,-6,-6)
NCrop hands the cropping to CropResize. The cropped video width becomes the output width, 8:9 is used for the sample aspect ratio, and the output is 4:3.
# ===============================================================================
# ========== NCrop ==============================================================
# ===============================================================================
#
# NCrop is a CropResize wrapper function for automatically resizing NTSC 4:3 DVDs based on
# the cropped width, rather than the cropped height.
# All CropResize arguments can be used with NCrop, except OutWidth and OutHeight.
#
# NCrop defaults to using InSAR=8.0/9.0 for CropResize. To disable 8:9 as the default input sample
# aspect ratio, change the InSAR line in the NCrop function to the following:
# InSAR = defined(InDAR) ? 0 : default(InSAR, 0)
#
# NCrop also defaults to using CropDAR=4.0/3.0 for CropResize, to ensure the output has a 4:3 display
# aspect ratio. To disable the forcing of 4:3 cropping and resizing by default, change the CropDAR line
# in the NCrop function to the following:
# CropDAR = default(CropDAR, 0)
#
# The resized height will be mod4.
#
# -------------------------------------------------------------------------------
#
# Useage:
#
# Add cropping to a script.
# Crop(10,4,-6,-6)
#
# Add an "N" to the Crop function's name and the NCrop wrapper function takes over.
# NCrop(10,4,-6,-6)
#
# After changing the function's name to NCrop, CropResize arguments can also be added.
#
# Disable the default input SAR.
# NCrop(10,4,-6,-6, InSAR=0)
#
# Change the default input SAR and display CropResize info.
# NCrop(10,4,-6,-6, InSAR=10.0/11.0, Info=true)
#
# Disable the default input SAR with InDAR.
# NCrop(10,4,-6,-6, InDAR=0)
#
# Override the default input SAR with InDAR, set a new input DAR, and enable borders.
# NCrop(10,4,-6,-6, InDAR=15.0/11.0, Borders=true)
#
# ===============================================================================
function NCrop(clip Source, int "CL", int "CT", int "CR", int "CB", \
val "CropDAR", int "CSplit", bool "CAlign", bool "AutoC", int "CThresh", int "CStart", int "CSample", \
int "CPreview", int "CLine", val "InDAR", val "InSAR", val "OutDAR", val "OutSAR", bool "AutoAspect", \
int "Mod", int "HMod", bool "NoResize", bool "ResizeWO", bool "Borders", bool "CleanBorders", \
val "BColor", bool "Frosty", int "ColorCorrect", string "ColorMode", string "Resizer", int "GMode", \
bool "RMode", int "PicDim", bool "Position", bool "Info") {
Try{ IsG1Function = G1_GFunction }catch(err){ IsG1Function = false }
Try{ IsG2Function = G2_GFunction }catch(err){ IsG2Function = false }
# Disable the use of GCropResize global variables, just in case....
IsG2Function ? Eval(" global G2_GFunction = false ") : nop()
IsG1Function ? Eval(" global G1_GFunction = false ") : nop()
CropDAR = default(CropDAR, 4.0/3.0)
InSAR = defined(InDAR) ? 0 : default(InSAR, 8.0/9.0)
InDAR = default(InDAR, 0)
Mod = default(Mod, 4)
CroppedWidth = width(Crop(Source, CL, CT, CR, CB))
OutWidth = ceil(float(CroppedWidth) / float(Mod)) * Mod
Output = CropResize(Source, OutWidth, 0, CL, CT, CR, CB, CropDAR, CSplit, CAlign, AutoC, \
CThresh, CStart, CSample, CPreview, CLine, InDAR, InSAR, OutDAR, OutSAR, AutoAspect, \
Mod, HMod, NoResize, ResizeWO, Borders, CleanBorders, BColor, Frosty, ColorCorrect, ColorMode, \
Resizer, GMode, RMode, PicDim, Position, Info)
IsG1Function ? Eval(" global G1_GFunction = true ") : nop()
IsG2Function ? Eval(" global G2_GFunction = true ") : nop()
return Output }
# ===============================================================================
# ===============================================================================
hello_hello
31st December 2020, 14:00
GCrop is more generic than NCrop and requires the GCropResize function for specifying CropResize settings, but it's purpose is much the same.
# ===============================================================================
# ========== GCrop ==============================================================
# ===============================================================================
#
# GCrop is a CropResize wrapper function, intended for use with the GCropResize function,
# included with CropResize. "G" for "global", as GCropResize creates global Avisynth variables
# for CropResize. It passes the video through untouched (unless it's auto-cropping).
# The purpose of GCrop is to make it easier to apply standard cropping in a script, while still using
# CropResize for the resizing.
#
# All CropResize arguments can be used with GCropResize, while GCrop itself can only be used to
# specify the cropping.
# If you also specify cropping with GCropResize, it'll be added to GCrop's cropping and the total
# will be applied by CropResize.
#
# -------------------------------------------------------------------------------
#
# Useage:
#
# Add GCropResize to a script to configure any CropResize options.
# Follow GCropResize with the cropping.
#
# GCropResize(1280,720, Borders=true, Info=true)
# Crop(10,44,-6,-42)
#
# Add a "G" to the Crop function's name and the GCrop wrapper function takes over.
#
# GCropResize(1280,720, Borders=true, Info=true)
# GCrop(10,44,-6,-42)
#
# ===============================================================================
function GCrop(clip Source, int "CL", int "CT", int "CR", int "CB") {
Try{ IsG1Function = G1_GFunction }catch(err){ IsG1Function = false }
Try{ IsG2Function = G2_GFunction }catch(err){ IsG2Function = false }
SourceWidth = width(Source)
IsGMode = IsG1Function || IsG2Function
L1 = default(CL, 0)
T1 = default(CT, 0)
R1 = default(CR, 0)
B1 = default(CB, 0)
R1 = (R1 == 0) ? 0 : (R1 < 0) ? R1 : R1 - Source_Width + L1
B1 = (B1 == 0) ? 0 : (B1 < 0) ? B1 : B1 - Source_Height + T1
L2 = IsGMode ? (IsG1Function ? G1_CL : G2_CL) : 0
T2 = IsGMode ? (IsG1Function ? G1_CT : G2_CT) : 0
R2 = IsGMode ? (IsG1Function ? G1_CR : G2_CR) : 0
B2 = IsGMode ? (IsG1Function ? G1_CB : G2_CB) : 0
R2 = (R2 == 0) ? 0 : (R2 < 0) ? R2 : R2 - Source_Width + L2
B2 = (B2 == 0) ? 0 : (B2 < 0) ? B2 : B2 - Source_Height + T2
return CropResize(Source, CL=L1+L2, CT=T1+T2, CR=R1+R2, CB=B1+B2) }
# ===============================================================================
# ===============================================================================
Danette
5th January 2021, 14:50
I’ve spent the last several weeks trying to find AR problems with CropResize on 12 different TV series (all NTSC) …and I can’t find any! So, at this point, I’m going to have to make it my default resizing approach.
I think that what I will do is to use one of your suggestions:
CropResize(0,0, 0,0,-0,0, InDAR=15.0/11.0, ResizeWO=true, Resizer=”Lanczos4Resize”) and add in the cropping (left and right borders only) following use of the auto-crop in AvsPMod’s crop editor. This way, I can quickly determine if the cropping is good. I have a macro that can perform all of this in seconds. Are there any potential pitfalls to which you think I should be alert?
Am I right that the InDAR function is actually changing the pixel size to “x” size, i.e.; the pixel is not square, in order to provide the AR adjustment?
hello_hello
5th January 2021, 20:55
I’ve spent the last several weeks trying to find AR problems with CropResize on 12 different TV series (all NTSC) …and I can’t find any! So, at this point, I’m going to have to make it my default resizing approach.
I think that what I will do is to use one of your suggestions:
CropResize(0,0, 0,0,-0,0, InDAR=15.0/11.0, ResizeWO=true, Resizer=”Lanczos4Resize”) and add in the cropping (left and right borders only) following use of the auto-crop in AvsPMod’s crop editor. This way, I can quickly determine if the cropping is good. I have a macro that can perform all of this in seconds. Are there any potential pitfalls to which you think I should be alert?
Am I right that the InDAR function is actually changing the pixel size to “x” size, i.e.; the pixel is not square, in order to provide the AR adjustment?
Yes, the InDAR effectively tells the script the shape of the pixels for the source video, so InDAR=15.0/11.0 and InSAR=10.0/11.0 achieve the same thing for a 4:3 NTSC DVD (InSAR meaning input sample or pixel aspect ratio). If you don't specify either it uses an InSAR and assumes InSAR=1.0.
ResizeWO mode first determines the resized video width after any cropping (otherwise the original width is resized).
For an InSAR (input sample/pixel aspect ratio) it's simply:
Cropped Width x InSAR
InDAR is converted to InSAR with:
(Original Height x InDAR / Original Width)
So for an InDAR the resized width after cropping is:
Cropped Width x (Original Height x InDAR / Original Width)
If there's no cropping the resized width is effectively:
Original Height x InDAR
From there the script works out how much the width needs to be reduced (if at all) to make it mod4, and then calculates how much extra needs to be cropped from the source width so there won't be any aspect error. The source sample aspect ratio is taken into account when calculating any extra cropping.
In ResizeWO mode, if the height after cropping isn't mod4, the script simply crops an extra couple of pixels from either the top or bottom to make it mod4.
Using my earlier example of cropping 3 pixels from each side:
CropResize(0,0, 3,0,-3,0, InDAR=15.0/11.0, ResizeWO=true, Resizer="Lanczos4Resize")
The mod4 width is calculated to be 648 as the exact width would be 649.09.
714 x 480 x (15/11) / 720 = 649.09
or
714 x (10/11) (SAR) = 649.09
And it works out that a total of 3.6 pixels needs to be cropped from each side in order to resize to 648 with zero aspect error, so the end result is the script does this (Info=true will show you what's happening):
Crop(2,0,-2,0)
Lanczos4Resize(648,480, 1.6,0,-1.6,0)
720 - 3.6 - 3.6 = 712.8
712.8 x (10/11) = 648
If there's no cropping:
CropResize(InDAR=15.0/11.0, ResizeWO=true, Resizer="Lanczos4Resize")
The end result is:
Lanczos4Resize(652,480, 1.4,0,-1.4,0)
720 - 1.4 - 1.4 = 717.2
717.2 x (10/11) = 652
So yeah.... a different InDAR would change the result as the script is simply basing it's calculations on the InDAR (or InSAR) you tell it use.
The only difference I can see to cropping with AvsPmod after resizing, if that's what you mean, is resizing in this case reduces the width of the black, because you're resizing down, so if there were 8 pixels of black each side, they're cropped to 6.6 pixels (because CropResize cropped 1.4 pixels each side before resizing to 652x480) and after resizing...
6.6 x (10/11) = 6.
After resizing with CropResize, 8 pixels borders are now 6 pixel borders.
10 pixel borders would end up 7.82 pixels wide.
10 - 1.4 = 8.6
8.6 x (10/11) = 7.82
So you could do this and end up with 640x480
CropResize(0,0, 8,0,-8,0, InDAR=15.0/11.0, ResizeWO=true, Resizer="Lanczos4Resize")
Or you could end up with 640x480 this way.
CropResize(InDAR=15.0/11.0, ResizeWO=true, Resizer="Lanczos4Resize")
Crop(6,0,-6,0)
Whether cropping before or after CropResize crops less black, or more picture, would depend on the width of the black borders to begin with, and if they have mod2 dimensions. It's swings and roundabouts...
If you auto-crop with AvsPmod, it might be better to crop first, then let CropResize do it's thing, but if you do that you must specify the appropriate InSAR rather than a DAR, as cropping changes the DAR, and keep in mind CropResize might still crop a fraction more from the width to prevent any aspect error when resizing.
AutoCrop()
CropResize(InSAR=10.0/11.0, ResizeWO=true, Resizer="Lanczos4Resize")
Did any of that help? :)
Danette
5th January 2021, 21:37
Yes, it helps confirm my understanding.
I am analyzing (with AvsPmod's cropping editor) the width-cropping necessary BEFORE applying CropResize. I then place those AvsPmod cropping values into CropResize for processing.
I don't much care what the final picture width (640x480,652x480,etc.) is, so long as the AR is accurate.
hello_hello
6th January 2021, 07:18
If you're doing that, here's a wrapper function for you. Similar to the one I posted earlier for bruno321.
This one's called DCrop (for Danette crop). :)
Edit: Also added Resizer="Lanczos4Resize" as the default resizing method.
The defaults are InDAR=15.0/11.0, ResizeWO=true, and Resizer="Lanczos4Resize".
Apply your cropping with AvsPmod.
Crop(6,0,-8,0)
Then switch to DCrop.
DCrop(6,0,-8,0)
And that's it. DCrop and CropResize take over from there.
The result would be the same as
CropResize(0,0, 6,0,-8,0, InDAR=15.0/11.0, ResizeWO=true, Resizer="Lanczos4Resize")
# ===============================================================================
# ========== DCrop ==============================================================
# ===============================================================================
#
# DCrop is a CropResize wrapper function for automatically resizing (4:3 DVDs by default).
# All CropResize arguments can be used with DCrop.
#
# DCrop defaults to using InDAR=15.0/11.0 for CropResize. To disable 15:11 as the default
# input display aspect ratio, change the InDAR line in the DCrop function to the following:
# InDAR = defined(InSAR) ? 0 : default(InDAR, 0)
#
# DCrop also defaults to ResizeWO=true. To disable ResizeWO=true as the default,
# change the ResizeWO line in the DCrop function to the following:
# ResizeWO = default(ResizeWO, false)
#
# The default resizing of "Lanczos4Resize" can also be reverted to Spline36Resize by
# changing the Resizer line in the function to this:
# Resizer = default(Resizer, "")
#
# -------------------------------------------------------------------------------
#
# Useage:
#
# Add cropping to a script.
# Crop(6,0,-8,0)
#
# Add "D" to the Crop function's name and the DCrop wrapper function takes over.
# DCrop(6,0,-8,0)
#
# After changing the function's name to DCrop, CropResize arguments can also be added.
# Specifying a new InDAR or InSAR over-rides the default of InDAR=15.0/11.0.
# DCrop(6,0,-8,0, InSAR=8.0/9.0, Info=true)
#
# In order to use the function as intended, if you wish to add resizing to DCrop,
# the OutWidth & OutHeight must be specified after the cropping, not before.
# DCrop(6,0,-8,0, 640,480, InSAR=8.0/9.0, ResizeWO=false)
#
# ===============================================================================
function DCrop(clip Source, int "CL", int "CT", int "CR", int "CB", int "OutWidth", int "OutHeight", \
val "CropDAR", int "CSplit", bool "CAlign", bool "AutoC", int "CThresh", int "CStart", int "CSample", \
int "CPreview", int "CLine", val "InDAR", val "InSAR", val "OutDAR", val "OutSAR", bool "AutoAspect", \
int "Mod", int "HMod", bool "NoResize", bool "ResizeWO", bool "Borders", bool "CleanBorders", \
val "BColor", bool "Frosty", int "ColorCorrect", string "ColorMode", string "Resizer", int "GMode", \
bool "RMode", int "PicDim", bool "Position", bool "Info") {
Try{ IsG1Function = G1_GFunction }catch(err){ IsG1Function = false }
Try{ IsG2Function = G2_GFunction }catch(err){ IsG2Function = false }
# Disable the use of GCropResize global variables, just in case....
IsG2Function ? Eval(" global G2_GFunction = false ") : nop()
IsG1Function ? Eval(" global G1_GFunction = false ") : nop()
InDAR = defined(InSAR) ? 0 : default(InDAR, 15.0/11.0)
InSAR = default(InSAR, 0)
ResizeWO = default(ResizeWO, true)
Resizer = default(Resizer, "Lanczos4Resize")
Output = CropResize(Source, OutWidth, OutHeight, CL, CT, CR, CB, CropDAR, CSplit, CAlign, AutoC, \
CThresh, CStart, CSample, CPreview, CLine, InDAR, InSAR, OutDAR, OutSAR, AutoAspect, \
Mod, HMod, NoResize, ResizeWO, Borders, CleanBorders, BColor, Frosty, ColorCorrect, ColorMode, \
Resizer, GMode, RMode, PicDim, Position, Info)
IsG1Function ? Eval(" global G1_GFunction = true ") : nop()
IsG2Function ? Eval(" global G2_GFunction = true ") : nop()
return Output }
# ===============================================================================
# ===============================================================================
Danette
8th January 2021, 21:24
Well, thank you. You just made my life a little easier ...imagine that.
bruno321
11th January 2021, 07:45
Just got around to testing these. I've an NTSC (720x480 SAR) source, if I do
Crop(10, 2, -8, -0) I get 702x478.
If I do NCrop(10, 2, -8, -0) I get 704x528. There's this difference in width due to the script forcing mod4. Could you make a mod2 script?
Same with UpsizeMe() (which I personally prefer).
Thanks!
hello_hello
11th January 2021, 08:15
Personally I'd avoid a mod2 width. These days it'd probably be okay, but you never know.. there might still be the odd player/device that won't be happy about it. You're resizing the height anyway, so resizing the width by a couple of pixels at the same time isn't likely to make a difference. Anyway.... I included the Mod argument so you can change the mod to whatever you want.
UpSizeMe(Mod=2)
The default for CropResize is still mod4 for the height though. The width will be whatever UpSizeMe tells CropResize to make it, but if you want to set mod2 for the height as well, you'll need to do this:
Crop(10,4,-6,-6)
CropResize(UpSizeMe(Mod=2), HMod=2, InSAR=8.0/9.0)
To make the default mod2 for UpSizeMe, just change the following line in the function I posted earlier.
Change:
Mod = default(Mod, 4)
to:
Mod = default(Mod, 2)
You'll still have to use Mod=2 or Hmod=2 for CropResize though. For CropResize, Hmod uses the same value as Mod unless you specify a value for HMod, so normally this would change both the width and height mod.
CropResize(640,480, Mod=2, InSAR=8.0/9.0)
You can modify the NCrop function the same way. Changing the Mod default will change the height mod for CropResize too.
To not have the script crop to 4:3 dimensions, as well as changing the Mod line, delete the CropDAR line or change it to the following.
CropDAR = default(CropDAR, 0.0)
hello_hello
11th January 2021, 12:00
bruno321,
Thinking about it, another reason for not fussing over a couple of pixels resizing for the width, is the way CropResize works in full resizing mode, it can sometimes crop in a non-intuative way, which is why ResizeWO mode exists.
It's been a while since I've played with the guts of this part of the script, so I'd have to look through it to give myself a refresher course but...
Even after setting everything to mod2 I only had to adjust the cropping you mentioned previously by a couple of pixels to show you an example.
Crop(10, 2, -8, -2)
iCropResize(UpSizeMe(Mod=2), Mod=2, InSAR=8.0/9.0)
The input width is 702, but as you can see from the screenshot, even though the output width is 702, the script cropped just a little from the width and resized it back up again.
https://i.postimg.cc/SNfrPJnJ/1.jpg
The alternative would be to manually reduce the output height so the script has to crop the picture height instead of the width, but even though it's a very small difference here due to the mod2 dimensions, there's now more cropped from the height than there was from the width, because left to it's own devices, the script chose the path of "least extra picture cropping".
Crop(10, 2, -8, -2)
iCropResize(UpSizeMe(Mod=2),534, InSAR=8.0/9.0)
https://i.postimg.cc/pXHCkDXw/2.jpg
So.... you might be resizing the width a bit anyway....
Maybe I could add some extra checking so if the specified OutWidth is the same as the cropped width and there's no OutHeight specified, the script will choose a height that won't require the width to be cropped any further. I think there was a reason I had start to from scratch to get ResizeWO mode to work rather than use the same resizing as for normal resizing mode though, but I'll give it some thought.
hello_hello
17th January 2021, 11:17
bruno321,
I'd almost finished typing this post and I thought the new CropResize, with some changes for you, was ready to go, but I discovered a resizing problem during the final testing. I'll come back to it tomorrow when my brain's fresh, because the cause is alluding me right now, but rather than have to start this post from scratch again then....
I've added the ability to resize NTSC 4:3 DVDs "up", and as a side effect, also to automatically resize other DVD types "down". There's info in the new changelog explaining how it works, but for the new CropResize, there's a special value of -1 for OutWidth and OutHeight.
When OutWidth=-1 and OutHeight=0, the script automatically takes care of the resizing as before when both were zero, however OutWidth=-1 forces CropResize to use the width of the cropped video as the OutWidth, and it won't be cropped any further to prevent aspect error, and therefore won't be resized
The magic value of -1 can also be used for OutHeight, although not at the same time. It forces CropResize to use the height of the source after cropping for the output, once again without cropping or resizing it further.
There's limitations to when specifying -1 can make a difference. Those details are in the new changelog (or will be).
Here's the results from an earlier test, before I broke something in the script, to show you what -1 does.
16:9 PAL initially cropped to 700x572 Output dimensions & extra cropping
Crop(10, 2, -10, -2)
CropResize(0, 0, InSAR=64.0/65.0) 996x572 (0.00, 0.13, 0.00, -0.13)
CropResize(0, -1, InSAR=64.0/65.0) 992x572 (1.25, 0.00, -1.25, 0.00)
CropResize(-1, 0, InSAR=64.0/65.0) 700x400 (0.00, 0.96, 0.00, -0.96)
4:3 NTSC initially cropped to 700x476 Output dimensions & extra cropping
Crop(10, 2, -10, -2)
CropResize(0, 0, InSAR=8.0/9.0) 624x476 (0.00, 0.68, 0.00, -0.68)
CropResize(0, -1, InSAR=8.0/9.0) 620x476 (1.25, 0.00, -1.25, 0.00)
CropResize(-1, 0, InSAR=8.0/9.0) 700x532 (0.00, 1.56, 0.00, -1.56)
So.... OutWidth=-1 will make the UpSizeMe function obsolete. Once I find the bug (hopefully tomorrow), you'll be able to crop and resize your 4:3 NTSC DVDs the following way. Mod4 is still the default so if you want mod2 you have to tell CropResize about it.
Crop(10,4,-6,-6)
CropResize(-1, Mod=2, InSAR=8.0/9.0)
bruno321
20th January 2021, 18:35
Thanks, hello_hello. But FWIW I have no problem with using CropResize for, e.g, mpeg4 "4:3" NTSC DVDs as CropResize(UpsizeMe(),Mod=2,InSAR=10.0/11.0). I have that in a macro in avspmod so I don't have to think about it.
hello_hello
21st January 2021, 01:38
I had a new version on the way anyway, mainly to fix a couple of very minor bugs (nothing effecting the cropping/resizing calculations) and to make some changes to the included "frosty borders" function, and I figured the new options could also be used to prevent the width/height resizing I mentioned a few posts back, so while I was at it....
I've just been lazy about looking for the silly I did in the process. Soon...
Cheers.
hello_hello
30th January 2021, 22:30
There's a new version of CropResize in the opening post dated 2021-01-31. Compared to the previous version there's just a few minor improvements and bug fixes, along with the addition of an ability to specify negative values for OutWidth and OutHeight, to prevent resizing of the width or height when possible. Details in the help file.
There's also new wrapper functions labelled "CRCrop Functions". Usage details can be found at the top of that script.
There's still a link for CropResize 2020-06-23 in the opening post. It's now labelled version 2 as it contains all the changes applied to the function up to 2021-01-31, with the exception of the old color conversion methods. I thought I'd update the old version to keep it alive for anyone who might still be using it.
hello_hello
31st January 2021, 13:59
Sorry folks, but I discovered a mistake that was causing an error when the Frosty argument was enabled. I fixed it and updated the version numbers in the opening post to 2021-02-01 for the current CropResize and 2020-06-23 v3 for the older version.
hello_hello
1st February 2021, 00:06
I'm surprised nobody has mentioned it, but I just realised that for a while at least, I haven't been including the full wrapper functions script in the zip file, so even though the second post in this thread advertises the use of CR() rather than having to type CropResize(), with the wrong wrapper functions script the abbreviated function names couldn't have worked.
I haven't changed the version dates, but for anyone who's downloaded CropResize 2021-02-01 or 2020-06-23 v3 from the opening post prior to my submitting this one (those versions were only uploaded about 8 hours ago), if you download the zip file again you'll find the full wrapper functions script is now included, and the help file has been updated under the "Wrapper Functions" sections near the end. The CropResize function itself is exactly the same.
Sorry about that.
hello_hello
14th October 2021, 18:30
I've updated the link for CropResize in the opening post. The new version is dated 2021-10-15.
There's a few improvements, amongst them the ability to specify float values for cropping. I hadn't seen the need for it until now, as the script does it's own sub-pixel cropping to prevent aspect error, but after playing around a bit with Avisynth (https://www.videohelp.com/software/Avisynth)'s Animate function (due to a discussion on panning and scanning recently) it seemed like a good idea.
The CropResize cropping previews animate nicely, and if nothing else it makes simulating the "Ken Burns Effect" less of a chore, as there's no need to worry about distorting the picture. Here's a couple of quick samples, if anyone's interested.
CropResize(1280,720)
v = Last.Trim(18900,18900).Loop(190)
Animate(v, 10, 179, "pCropResize",
\ 960,720, 0.0, 40.0, -400.0, -40.0,
\ 960,720, 745.0, 120.0, -250.0, -310.0)
Animated Cropping Preview.mkv (https://files.videohelp.com/u/210984/Animated%20Cropping%20Preview.mkv) (996 kB)
Animate - The Ken Burns Effect.mkv (https://files.videohelp.com/u/210984/Animate%20-%20The%20Ken%20Burns%20Effect.mkv) (2.9 MB)
hello_hello
20th October 2021, 02:15
Fixed an unnecessary error message when using the Blend or TSoft arguments with FCropResize (adding frosty borders).
There's a link for CropResize 2021-10-20 in the opening post.
hello_hello
22nd October 2021, 07:12
Fixed another unnecessary error message when using Clone=3 with FCropResize (adding frosty borders) and the ResampleMT plugin wasn't loaded.
Made Clone=3 play nice with YV411.
There's a link for CropResize 2021-10-22 in the opening post.
hello_hello
28th January 2022, 18:37
I've updated both versions of CropResize in the opening post. There's no functional change aside from fixing an error the script produced when Borders=true and the border dimensions weren't identical.
New versions CropResize 2022-01-28 and CropResize 2020-06-23 v7
Hopefully the next update will eliminate the need for two versions as I intend to add the old color conversion methods back so there's only one script to update.
Danette
28th April 2022, 01:59
I’m trying to decide whether or not to abandon dithertools and colormatrix, assuming that these aren’t dependencies for something unforeseen. I’m willing to try to do so, if CropResize 2022-01-28 is truly superior to 2020-06-23 v7 ...or is it better to wait for your newer version designed to eliminate the two separate versions? Do you believe that the 2022 version is worth the effort?
Also, are you still adding GradFun3 to the end of your scripts? I’ve been finding others that seem to prefer GradFun2b and/or flash3kyuu_deband to GradFun3, especially given their inclusions of these in their “Universal” plugins offerings, which don’t include GradFun3. What is your opinion on this?
hello_hello
29th April 2022, 10:02
CropResize 2022-01-28 and CropResize 2020-06-23 v7 should be exactly the same, with the exception of the color conversion plugins they support.
I'm only just getting back to working on the new version. The real world got in the way and I haven't been on the computer much during the last few months.
The new version won't be much different to the current ones in respect to functionality. There's a couple of obscure bug fixes (obscure because they don't involve typical usage), but the main change is native support for the FMTConv plugin for resizing and color conversion, and breaking backwards compatibility with previous versions in respect to color conversion.
After adding FMTConv and combining the color conversion methods from the two scripts, specifying a plugin with an number, ie ColorCorrect=2 was starting to become confusing (at least for me), so the argument name has changed and it's also a string. It'll be ColorConvert="ColorMatrix" etc instead.
I can't say I've come across any "universal" plugins, but yes I still use GradFun3 because it still does what it's supposed to do, or sometimes I use f3kdb/flash3kyuu_deband instead to also add grain for stronger banding prevention. There's also a neo version (http://avisynth.nl/index.php/Neo_f3kdb) with HBD support.
Edit: Just be aware that by default f3kdb/Neo_f3kdb adds grain too (much like following GradFun3 with AddGrainC would do) so if you don't want grain added you need to disable it with Neo_f3kdb(grainY=0, grainC=0).
I can't comment on GradFun2db as I really only have it in the plugins folder for a function or two that requires it. There's also scripts such as GradFun2DBmod and F3KDB_3, but I don't know much about them either.
Edit: CropResize always outputs the source bitdepth, so if you convert an 8 bit source to a higher bitdepth before resizing, ie
ConvertBits(16)
CropResize(1280,720)
And follow it with something like Neo_f3kdb that supports HBD and can deband and dither to 8 bit, it means you'll be resizing in 16 bit and still outputting 8 bit instead of resizing in 8 bit and then debanding. I assume Neo_f3kdb converts an 8 bit source to 16 bit for debanding, only in native Avisynth+ 16 bit rather than the stacked 16 bit format DitherTools uses. You can't do a similar thing with GradFun3 as CropResize doesn't support resizing a stacked 16 bit input.
If you're color converting too, you'll have to use the 2022-01-28 version of the script as it uses color conversion plugins supporting native Avisynth+ 16 bit.
hello_hello
25th September 2022, 08:51
There's a new version of CropResize dated 2022-09-22 in the opening post.
The main change is to the way a plugin is specified for color correction to hopefully make it easier to use (only standard dynamic range color conversions). There's details of the changes in the zip file, but the highlights are:
------------------------------------------------
A new "ColorConvert" argument has replaced "ColorCorrect" and it's a string.
Color conversion now supports the AVSResize, ColorMatrix, DitherTools, FMTConv, HDRMatrix and HDRTools plugins.
CropResize(1280,720, ColorConvert="FMTConv", ColorMode="601-709")
The default conversions between HD and SD colorimetry are all matrix-only, except for HDRTools. Specifying "NTSC" or "PAL" primaries for SD forces the color primaries to be converted too. Conversions to/from rec.2020 always convert the color primaries.
CropResize(1280,720, ColorConvert="AVSResize", ColorMode="601N-709")
------------------------------------------------
FMTConv added as a "native" resizer, selected by preceding the resize kernel with "F_".
CropResize(1280,720, Resizer="F_Spline36")
------------------------------------------------
CropResize now includes ringing repair (taken from the Resize8 (https://forum.doom9.org/showthread.php?t=183057) script). Unlike Resize8 though, it's disabled by default (partly because I use Resize8 quite a lot and there's no need to enable ringing repair twice).
CropResize(1280,720, RingRepair=true)
or to specify a fixed strength for ringing repair rather than the script calculating it based on the degree of resizing (range zero to one).
CropResize(1280,720, RingRepair=0.75)
------------------------------------------------
New wrapper functions added to the "Resizer Functions" script for linear light resizing.
CR_AVSResizeLinear(), CR_DitherToolsLinear() and CR_FMTConvLinear().
CropResize(960,540, Resizer="CR_DitherToolsLinear")
------------------------------------------------
Plus a couple of obscure bug fixes and some other minor changes.
hello_hello
29th September 2022, 16:10
There's a new version of CropResize dated 2022-09-29 in the opening post.
A minor update. See the Changes text file for details.
hello_hello
3rd October 2022, 15:52
There's a new version of CropResize dated 2022-10-04 in the opening post.
Just a minor regression fix.
hello_hello
30th October 2022, 17:36
There's a new version of CropResize dated 2022-11-01 in the opening post.
Fixed packed RGB cropping (RGB24, RGB32 etc) when the AVSResize and FMTConv plugins are resizing (the video was being resized without any cropping being applied).
Fixed AutoDAR=true ignoring the specified mod width or height (default Mod=4).
hello_hello
19th November 2022, 15:34
There's a link for a new version of CropResize dated 2022-11-19 in the opening post.
The pictures demonstrating CropResize usage in the 2nd post have also been updated.
-------------------------------
Fixed a 2022-09-22 regression when NoResize=true or ResizeWO=true and CSplit=1 (the default).
Specifying non-mod cropping (ie not mod2 for YV12) could result in an error message or the cropping
being adjusted slightly incorrectly.
The display and sample aspect ratios shown when Info=true should still have been correct though.
Changed the displayed info when a cropping preview is enabled, mainly to show the display and
sample aspect ratios as float (ie 1.777778) as well as a fraction (ie 16:9).
hello_hello
2nd June 2023, 04:41
There's a link to a new version of CropResize dated 2023-06-02 in the opening post.
The new version updates the built-in frosty borders function to match the latest update to the standalone FrostyBorders script. There's no other changes.
hello_hello
13th July 2023, 17:28
There's a link for new a version dated 2023-07-14 in the opening post. Just a couple of minor gremlin fixes.
hello_hello
25th September 2023, 16:21
There's a link for new a version dated 2023-09-26 in the opening post.
The major changes are listed above that link.
CropResize now comes in both Avisynth and VapourSynth flavours.
hello_hello
27th September 2023, 17:57
Sorry about the quick update, but there's a link for new a version dated 2023-09-28 in the opening post.
Fixed a couple of regressions in version 2023-09-26.
There was a typo in the VapourSynth version preventing an output sample aspect ratio being used.
The Avisynth version was producing an error message when a copping preview was enabled while Info=true.
While I was updating I tweaked the way Info displays a frame properties sample aspect ratio of 1:1 so at first glance the source video doesn't appear to be anamorphic.
hello_hello
1st October 2023, 18:16
There's a link for a new version dated 2023-10-02 in the opening post.
The "CropResize Changes" text file contains the details.
hello_hello
11th October 2023, 02:11
There's a link for a new version dated 2023-10-11 in the opening post.
Fixed a minor bug in the VapourSynth version. The Avisynth version hasn't changed (only the date to keep the two flavours the same).
hello_hello
12th October 2023, 21:17
Another minor bug fix. The Avisynth version this time. There's a link for the new version dated 2023-10-12 in the opening post.
hello_hello
28th October 2023, 22:14
New version dated 2023-10-28 in the opening post.
The only change is a bug fix for one of the included resizer wrapper functions.
If
cropresize(1920,1080,borders=true)
each source (jpg, mp4) will put in the box 1920x1080 with black frames?
Sources are:
- jpg files with different resolution and DAR, but each with PAR 1:1
- mp4, avi files with different resolutions and with 1:1 PAR (I think)
It seems to work, but I want to make sure :)
hello_hello
6th April 2024, 14:06
If
cropresize(1920,1080,borders=true)
each source (jpg, mp4) will put in the box 1920x1080 with black frames?
Sources are:
- jpg files with different resolution and DAR, but each with PAR 1:1
- mp4, avi files with different resolutions and with 1:1 PAR (I think)
It seems to work, but I want to make sure :)
Yes, it'll work as you expect.
The difference between enabling borders and not enabling them...
When they're not enabled, the output dimensions determine the display aspect ratio (assuming there's no OutDAR or OutSAR specified). So for example, if the picture is 4:3 and you specify 16:9 output dimensions, the script will automatically increase the cropping if necessary to ensure the picture is cropped to 16:9 before it's resized. If you only specify a width or height though (not both), the script calculates the unspecified width or height instead of cropping.
When borders are enabled, the script adds borders instead of increasing the cropping so the DAR of the picture itself won't change.
You have to specify both a width and height to add borders, even when Borders=true.
Full disclosure....
Sometimes the picture has to be cropped a little to prevent aspect error before it's resized, as the resized picture must be at least mod2 for YV12 (the default is mod4), so even when borders are enabled the script might crop an extra pixel or two, but generally it's not any more than that.
Thanks.
I would also have a question about defining the source PAR, but since AviSynth does not support it, the problem does not exist :)
poisondeathray
9th April 2024, 18:23
Thanks.
I would also have a question about defining the source PAR, but since AviSynth does not support it, the problem does not exist :)
SARNum , SARDen exist as a frame properties , so they can be set or overriden
http://avisynth.nl/index.php/Internal_functions#SARNum
Some source filters can read the source SAR and pass this information
automatically, some programs like ffmpeg can read avisynth frame properties and pass them along
Use PropShow to see the frame properties , propSet to set parameters
hello_hello
10th April 2024, 21:04
Thanks.
I would also have a question about defining the source PAR, but since AviSynth does not support it, the problem does not exist :)
The current CropResize supports resizing based on a sample/pixel aspect ratio in frame properties (it uses any SAR in frame properties automatically). Not all source filters add a SAR to frame properties though. If for some reason you don't think that SAR is correct, you can over-ride it using the InDAR or InSAR arguments or use them to specify an input DAR/SAR when there's no SAR in frame properties. CropResize also writes and/or updates the SAR in frame properties after resizing. If you want a specific SAR after resizing, you can use the OutDAR or OutSAR arguments. Info=true will tell you the correct (output) SAR to use for encoding.
Keep in mind there can only be one output SAR per script, so even though you can specify a different OutDAR or OutSAR when there's more than one instance of CropResize in a script (when appending different videos), it doesn't make sense to do so.
If you need to change the way CropResize crops and resizes based on an aspect ratio, change the InDAR or InSAR instead.
Ignore a chroma location being shown in this screenshot. It's something I'm adding for the next version, mainly for color conversion, although it's turned into more of a chore than I expected.
A random anamorphic source, resized to PAL 16:9 dimensions with borders.
CropResize(720,576, OutDAR=16.0/9.0, Borders=true, Info=true)
https://imgur.com/TfOc6w1.png
An example where videos A and B both have a SAR in frame properties but you want to change it for video B. Both are resized to non-anamorphic (square pixel) dimensions.
A = FFVideoSource("VideoA")
B = FFVideoSource("VideoB")
A.Trim(0, 99).CropResize(1280,720, Borders=true) ++ \
B.Trim(60, 154).CropResize(1280,720, InSAR=64.0/45.0, Borders=true) ++ \
A.Trim(100, 0).CropResize(1280,720, Borders=true)
rgr
10th April 2024, 23:03
some programs like ffmpeg can read avisynth frame properties and pass them along
Use PropShow to see the frame properties , propSet to set parameters
I tested ffmpeg and I don't see it reading PAR.
Duration: 03:04:24.12, start: 0.000000, bitrate: N/A
Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p(tv, bt470bg/bt470bg/smpte170m, progressive), 696x560, 50 fps, 50 tbr, 50 tbn
Stream #0:1: Audio: pcm_f32le, 48000 Hz, stereo, flt, 3072 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
Stream #0:1 -> #0:1 (pcm_f32le (native) -> aac (native))
Maybe LWLibavVideoSource doesn't set SAR.
rgr
10th April 2024, 23:06
The current CropResize supports resizing based on a sample/pixel aspect ratio in frame properties (it uses any SAR in frame properties automatically). Not all source filters add a SAR to frame properties though. If for some reason you don't think that SAR is correct, you can over-ride it using the InDAR or InSAR
Good to know, thanks for explaining.
I am combining various video files and if PAR is not recognized automatically, I will not do it manually for now.
poisondeathray
10th April 2024, 23:17
I tested ffmpeg and I don't see it reading PAR.
Duration: 03:04:24.12, start: 0.000000, bitrate: N/A
Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p(tv, bt470bg/bt470bg/smpte170m, progressive), 696x560, 50 fps, 50 tbr, 50 tbn
Stream #0:1: Audio: pcm_f32le, 48000 Hz, stereo, flt, 3072 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
Stream #0:1 -> #0:1 (pcm_f32le (native) -> aac (native))
Maybe LWLibavVideoSource doesn't set SAR.
It might not be automatic in the current avs ffmpeg patch. Youu can add "-avisynth_flags sar " as an ffmpeg input option
See this post
FFmpeg now supports reading two more frame properties - _SARNum and _SARDen, which are then combined into what FFmpeg reads as the full SAR value.
https://forum.doom9.org/showthread.php?p=1974149#post1974149
colorbars(720,480,"YV12")
Trim(0,300)
propSet("_SARNum",10)
propSet("_SARDen",11)
Input #0, avisynth, from 'props.avs':
Duration: 00:00:10.04, start: 0.000000, bitrate: 0 kb/s
Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 720x480, SAR 10:11
DAR 15:11, 29.97 fps, 29.97 tbr, 29.97 tbn
Stream #0:1: Audio: pcm_f32le, 48000 Hz, 2 channels, flt, 3072 kb/s
At least one output file must be specified
hello_hello
11th April 2024, 10:25
Good to know, thanks for explaining.
I am combining various video files and if PAR is not recognized automatically, I will not do it manually for now.
Why not?
When you specify an InDAR or InSAR, CropResize uses it as the basis for it's calculations. You don't need to specify either for a non-anamorphic source, but if the source is anamorphic the correct InDAR or InSAR should be specified if there's no SAR in frame properties.
If you were to specify a 16:9 DAR for an NTSC source (for example), you could resize it to 16:9 dimensions without CropResize applying any extra cropping.
CropResize(960,540, InDAR=16.0/9.0)
Without the InDAR, CropResize would assume 720x480 is both the resolution and the display aspect ratio (1.5:1) and it'll therefore crop unnecessarily to make the video 16:9 before resizing, and the DAR of the picture after resizing will be incorrect.
It's important that the correct InDAR or InSAR is used for an anamorphic source.
hello_hello
16th June 2025, 17:41
There's a link for a new version of CropResize dated 2025-06-16 in the opening post.
The main cropping and resizing functionality remains the same, however quite a few changes have been introduced, so if you've used the function in the past the Changes text file would be worth reading. The main change to note for the Avisynth version of CropResize is Avisynth+ 3.7.1 is now a minimum requirement.
hello_hello
20th December 2025, 12:38
There's a link for a new version of CropResize dated 2025-12-20 in the opening post. There's only a few minor changes to the CropResize function (see the CropResize Changes text file).
Based on an idea from rgr at doom9, a new function, CombineClips has been added (for both Avisynth and VapourSynth).
It's been updated and incompatible with the standalone CombineClips function I previously linked to at doom9.
By default borders are added as required to prevent aspect error, but borders can be disabled and the function will crop to prevent aspect error instead.
There's a separate CombineClips help file included, but below are some examples with screenshots.
Anamorphic clips must have an appropriate sample aspect ratio in frame properties otherwise they won't be resized correctly.
----------------------------------------------------------
The four source clips were taken from the same video (with a 2:1 aspect ratio), but they're resized and/or cropped differently.
832x468 16:9 dimensions and display aspect ratio.
A = CropResize(832,468).Subtitle("A", align=5)
https://i.postimg.cc/MMkQLHzr/A-832x468-16-9.jpg (https://postimg.cc/MMkQLHzr)
720x576 PAL dimensions and a 16:9 display aspect ratio.
B = CropResize(720,576, OutDAR=16.0/9.0).Subtitle("B", align=5)
https://i.postimg.cc/N9hHnFQN/B-PAL-16-9.jpg (https://postimg.cc/N9hHnFQN)
800x400 2:1 dimensions and display aspect ratio.
C = CropResize(800,400).Subtitle("C", align=5)
https://i.postimg.cc/jwV712RF/C-800x400-2-1.jpg (https://postimg.cc/jwV712RF)
720x480 NTSC dimensions and a 4:3 display aspect ratio.
D = CropResize(720,480, OutDAR=4.0/3.0).Subtitle("D", align=5)
https://i.postimg.cc/2bpZtyCg/D-NTSC-4-3.jpg (https://postimg.cc/2bpZtyCg)
----------------------------------------------------------
The output frames are stacked to make the result easier to see.
The help file has info on using the Max argument.
Avisynth syntax is used below, but the VapourSynth syntax is very similar.
Setting the desired output width with Max=True.
CombineClips will calculate the appropriate height based on the clip with the greatest display aspect ratio.
The output is 960x480 (2:1 DAR).
CombineClips([A,B,C,D], 960,0)
https://i.postimg.cc/HJ8M3X1R/1-width-960-max-true.jpg (https://postimg.cc/HJ8M3X1R)
Setting the desired output width with Max=False.
CombineClips will calculate the appropriate height based on the clip with the smallest display aspect ratio.
The output is 960x720 (4:3 DAR).
CombineClips([A,B,C,D], 960,0, Max=False)
https://i.postimg.cc/xkNmgMVB/2-width-960-max-false.jpg (https://postimg.cc/xkNmgMVB)
Specifying the desired output dimensions with borders enabled.
If those dimensions don't match the resizing dimensions of at least one clip, every clip will have borders added.
CombineClips([A,B,C,D], 768,360)
https://i.postimg.cc/Z9vNjpz1/3-768x360.jpg (https://postimg.cc/Z9vNjpz1)
Specifying the desired output dimensions with borders disabled.
CombineClips([A,B,C,D], 768,360, Borders=False)
https://i.postimg.cc/7CJzX0rF/4-768x360-borders-false.jpg (https://postimg.cc/7CJzX0rF)
Resizing to 720x480 NTSC dimensions with a 16:9 display aspect ratio and adding borders as required.
CombineClips([A,B,C,D], 720,480, OutDAR=16.0/9.0)
https://i.postimg.cc/VryChvz4/5-NTSC-16-9.jpg (https://postimg.cc/VryChvz4)
Displaying the cropping and resizing for each video.
CombineClips([A,B,C,D], 960,480, Info=True)
https://i.postimg.cc/VryChvzK/6-960x480-Info-True.jpg (https://postimg.cc/VryChvzK)
----------------------------------------------------------
hello_hello
16th March 2026, 22:13
I don't know how often this'll be of use to anyone, myself included, but I was working with some DVDs that contained a mixture of 16:9 and 4:3 pictures, and the 4:3 sections had horrible ringing at the edges, so I created a function to automatically crop the borders from the 4:3 sections, as well as a couple of pixels of picture each side to remove the ringing, then add new borders after resizing.
When I say "automatically", the cropping must be specified manually, but once it's configured it picks out the 4:3 sections, crops them and resizes as required before added new borders... without me having to split the video into sections manually.
For videos with multiple aspect ratios it won't be suitable, but for a video with two aspect ratios it worked quite well, so in case anyone else may find it useful... Naturally it uses CropResize to crop, resize and add the borders.
A 4:3 section resized to square pixel dimensions:
https://i.imgur.com/5jPSX0c.png
The same 4:3 section after running the video through the CropEdges function.
BClip = Source.Crop(0,0,-632,0)
CropEdges(Source, BClip, 0,0, 8,0,-8,0, 98,0,-98,0, CropDAR=4.0/3.0, InDAR=20.0/11.0, luma=18, CPreview=0)
https://i.imgur.com/YUskO7m.png
# ===============================================================================
# CropEdges
# ===============================================================================
#
# CropEdges will crop the borders from a video containing sections with two different aspect ratios.
# The idea is to crop the sections with a wider aspect ratio and optionally resize, while cropping
# away the borders of the sections with the narrower aspect ratio, along with a few pixels of picture
# if necessary to remove any crud at the edges, and to then resize the picture as required before
# adding new borders.
#
# The desired cropping for the clip with the wider aspect ratio is specified using CL1, CT1, CR1 & CB1.
# The desired cropping for the clip with the narrower aspect ratio is specified using CL2, CT2, CR2 & CB2.
#
# A clip slightly less than the width of one of the larger borders (either left or right) must be supplied.
#
# The Luma argument can be used to adjust the detection of the borders. In theory "black" should have a
# value of 16 for limited range video (8 bit), but it mightn't be consistent so it can be adjusted if
# necessary. The default value is 18, so any value above 18 for the average Luma of the supplied border
# clip would be assumed to contain picture by default. For high bitdepth video the value is automatically
# scaled, so 8 bit values should always be specified for the Luma argument.
#
# The CPreview argument can be used to help adjust the cropping values for each clip, and to adjust the
# Luma value if necessary so the function correctly detects which parts of the video have a narrower aspect
# ratio.
#
# -------------------------------------------------------------------------------
# An example
# -------------------------------------------------------------------------------
#
# For the following example we'll assume the source is a PAL DVD containing a 16:9 picture with 8 pixel
# borders each side, and sections containing a 4:3 picture with 96 pixel borders each side. Therefore
# for the border clip you'd crop the picture to only keep the left 96 pixels.
# BClip = Crop(0,0,96,0)
# However in case the width of the narrow picture changes a bit, it won't hurt to keep a little less than
# the whole border.
# BClip = Crop(0,0,88,0)
#
# The cropped border clip is used as an argument for CropEdges, along with the desired cropping for both
# the 16:9 and 4:3 sections. If you want the sections with the narrower aspect ratio to always be cropped
# to a specific aspect ratio, specify that aspect ratio with the CropDAR argument. It's not applied to the
# wider sections.
#
# Specifying an output width and height is optional, and the NoResize argument can be used to prevent
# automatic resizing of anamorphic video.
#
# Keep in mind that when output dimensions are specified, if the specified dimensions don't match the aspect
# ratio of the wider sections, they'll be cropped to prevent aspect error by default. To prevent this, either
# specify zero for the output width and height, or the Border argument can be used to add borders as required
# instead of cropping. The Border argument has no effect for the sections of video with the narrower aspect
# ratio.
#
# -------------------------------------------------------------------------------
#
# CropEdges(Source, BClip, 0,0, 8,0,-8,0, 98,0,-98,0, CropDAR=4.0/3.0, InDAR=20.0/11.0, luma=18, CPreview=0)
#
# ===============================================================================
function CropEdges(clip, Source, clip BClip, \
int "OutWidth", int "OutHeight", \
float "CL1", float "CT1", float "CR1", float "CB1", \
float "CL2", float "CT2", float "CR2", float "CB2", \
float "CropDAR", int "CPreview", bool "NoResize", \
float "InDAR", float "OutDAR", bool "Borders", bool "BBlur", \
string "Resizer", bool "Info", int "Luma") {
Source_Bits = BitsPerComponent(Source)
Scale = (Source_Bits == 8) ? 1 : (Source_Bits != 32) ? pow(2, Source_Bits - 8) : 1.0 / 256.0
OutWidth = default(OutWidth, 0)
OutHeight = default(OutHeight, 0)
CL1 = default(CL1, 0.0)
CT1 = default(CT1, 0.0)
CR1 = default(CR1, 0.0)
CB1 = default(CB1, 0.0)
CL2 = default(CL2, 0.0)
CT2 = default(CT2, 0.0)
CR2 = default(CR2, 0.0)
CB2 = default(CB2, 0.0)
CropDAR = default(CropDAR, 0.0)
CPreview = default(CPreview, 0)
InDAR = default(InDAR, 0.0)
OutDAR = default(OutDAR, 0.0)
NoResize = default(NoResize, false)
Borders = default(Borders, false)
BBlur = default(BBlur, true)
Resizer = default(Resizer, "")
Info = default(Info, false)
Luma = default(Luma, 18) * Scale
Assert((OutWidth == 0 == OutHeight) || !NoResize, " CropEdges " + chr(10) + \
" OutWidth & OutHeight must both be zero (or unspecified) when NoResize is true " + chr(10))
Clip1 = CropResize(Source, OutWidth, OutHeight, CL1, CT1, CR1, CB1, CPreview=CPreview, \
InDAR=InDAR, OutDAR=OutDAR, NoResize=NoResize, Borders=Borders, BBlur=BBlur, Resizer=Resizer, Info=Info)
Width2 = (OutWidth > 0) ? OutWidth : width(Clip1)
Height2 = (OutHeight > 0) ? OutHeight : height(Clip1)
Clip2 = CropResize(Source, Width2, Height2, CL2, CT2, CR2, CB2, CropDAR=CropDAR, CPreview=CPreview, \
InDAR=InDAR, OutDAR=OutDAR, NoResize=NoResize, Borders=true, BBlur=BBlur, Resizer=Resizer, Info=Info)
return ConditionalFilter(BClip, Clip1, Clip2, function [Luma] () { (AverageLuma() > Luma) }) }
# ===============================================================================
Edit 2026-03-20:
Added a calculation to the function so 8 bit values for the Luma argument (0 to 255) automatically scale for video of any bitdepth.
tormento
17th March 2026, 16:53
the 4:3 sections had horrible ringing at the edges
Often, the "horrible ringing" at the edges comes from bad resizing and/or fractional scaling with luma and/or chroma going to hell.
I suggest you to try some tools such as getnative to find the original resolution and descale to that one before applying any other filter.
hello_hello
18th March 2026, 10:29
The ringing, or what looks like ringing, definitely exists in the source. I'll confess it hadn't occurred to me to consider it mightn't be, but after having another look I'm certain it is, however it's not as bad as I originally thought. Resizing to square pixel dimensions probably made it worse, followed by the player having to upscale to fill the display.
As a test I upscaled the DVD to 1440x1152 with PointResize for a better look (cropping 8 pixels left and right first). The frame I used for my previous screenshot actually looks fairly good (nothing I'd normally be OCD about fixing), but there's still some frames with "ringing or "halos" at the borders.
Even if it's not ringing, border edges are often far from clean, so the function can be used to make sure they are.
(Width x 2) x (Height x 2)
https://i.postimg.cc/N9413Tmr/point.png (https://postimg.cc/N9413Tmr)
So yes, the player was probably creating much of the ringing as it upscaled the video to 1080p. Cropping the borders away and adding them back after resizing to square pixel dimensions seems to prevent that, although probably because I used the AddBorders "R" argument to blur the edges just a little bit.
Edit: Now that you have me questioning the cause of the ringing, I'll change the function name to something more generic, like CropEdges().
tormento
18th March 2026, 10:41
The ringing, or what looks like ringing, definitely exists in the source.
That is what I meant, probably in not my so clear english.
Can you share a unprocessed clip, preferably a clean and well contrasted one?
hello_hello
18th March 2026, 17:17
Here's 30 seconds containing 4:3 picture.
VTS_01_1.mkv (https://files.videohelp.com/u/210984/VTS_01_1.mkv)
Edit: I don't know where my head was at earlier, but I'm pretty sure I checked the video again after resizing it to 1440x1152 with PointResize, but I'd also cropped 8 pixels from each side. To simply double the width and height I should have resized to 1408x1152. It shouldn't matter though, given I upscaled with PointResize, should it?
I'll look at it again while resizing as I should have later.
DTL
19th March 2026, 07:05
The original analog sources was designed to be displayed at the physical screens with overscan and cropping edges of the physical image by physical frame of the screen/display. So all possible damaged edges of a frame (start/end lines and start/end parts of lines) expected to be cropped out by display and new transients to display's environment created by display (like LCD/CRT/plasma screen frame). If user want to display 4/3 on 16/9 the 'overscan+cropping hardware accelerated' feature of the standard displays need to be completely simulated at the active screen area of the non-standard display. To save from display resizer (or DAC before analog display) overshoot (halo or ringing depend on scaler kernel/filter size) the new transient to 'black' (or any other new border colour) need to be same conditioned as all other 'not-enchanced' transients in the active frame area. This was implemented in new AddBorders (r-param and others). If the overshoot happens this may cause additional distraction of a viewer to the edges of an image from the important center of an image. Other possible 'hardware' option to display 4/3 at 16/9 is to mask sides of the 16/9 screen with a (black) mask with sharp or other shaped edges.
tormento
20th March 2026, 00:08
Here's 30 seconds containing 4:3 picture.
I see that's a broadcasted content. There's little I can do to help you, as, usually, those kind of video are so much processed, by hw and not by sw, that they are beyond any reasonable recovery.
My hint, beside training some AI (it depends how much effort you want to put in the recovery) is to use Bore filter for the borders.
P.S: Pixel ratio isn't 1:1, as with almost every modern DVD. I suggest you to process the video as it is and to force proper SAR in the encoder, not to lose data.
hello_hello
20th March 2026, 01:56
Using the function I posted earlier to crop the old borders and a couple of pixels of picture each side, then adding new borders after resizing to square pixel dimensions seems to work pretty well. Enabling the AddBorders "R" argument when adding back the borders definitely makes a difference when the video is upscaled on playback. Any blurring of the borders is virtually unnoticeable (CropResize only uses R=2 when it's blurring option is enabled) but it's enough to prevent noticeable ringing or over-shoot when the player upscales the encoded video.
I think adding the R argument to AddBorders was DTL's idea. It was certainly a good one.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.