Log in

View Full Version : CropResize - Cropping & resizing function (Avisynth & VapourSynth versions)


Pages : 1 [2] 3

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.

rgr
3rd April 2024, 09:38
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.

rgr
9th April 2024, 18:10
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().