View Full Version : Evenly padding to mod8/16?
Reel.Deel
8th September 2015, 16:43
Hi, I'm looking for a script that can evenly pad to mod8/16. I came across this function:
function mmod1(clip c, int h, int v) { c.pointresize(c.width+(1-c.width)%h+h-1, c.height+(1-c.height)%v+v-1, 0,0, c.width+(1-c.width)%h+h-1, c.height+(1-c.height)%v+v-1) }
It does what I want but unfortunately it only pads the bottom right borders. There's nothing wrong with this and it's in fact the correct thing to do in certain situations but there are other times were padding the borders evenly is more desirable. I've tried modifying the script to do just that but I was unsuccessful. Any help would be be appreciated.
feisty2
8th September 2015, 17:08
Function P2M8 (clip input)
{
w = input.width ()
h = input.height ()
w8 = int ((w + 4) / 8) * 8
h8 = int ((h + 4)/ 8) * 8
left = int ((w8 - w) / 2)
right = w8 - w - left
top = int ((h8 - h) / 2)
bot = h8 - h - top
return Padding (input, left, top, right, bot)
}
Function Padding (clip input, int "left", int "top", int "right", int "bottom")
{
w = input.width ()
h = input.height ()
output = input.PointResize (w+left+right, h+top+bottom, -left, -top, w+left+right, h+top+bottom)
return output
}
WARNING: ain't tested it... use it at ur own risk
ajp_anton
8th September 2015, 20:28
Pad to any mod, optionally separately for width and height. Also not tested =).
function padtomod(clip input,int hmod,int "vmod")
{
vmod = default(vmod, hmod)
w = input.width
h = input.height
hpad = ceil(w/hmod)*hmod
vpad = ceil(h/vmod)*vmod
left = round((hpad-w)/2)
top = round((vpad-h)/2)
return input.pointresize(hpad, vpad, -left, -top, hpad, vpad)
}
Reel.Deel
20th September 2015, 14:23
@ajp_anton
Finally tried out padtomod but unfortunately it's cropping instead of padding.
raffriff42
20th September 2015, 18:08
EDIT New and improved - supports rounding up or down to the nearest mod-X size. Round down by default.XXSource(...)
UUSize(Width-39, Round(Height+2*PI), mod=8, floor=true)
return Last
##################################
### crop or add borders to ensure clip is a certain size
##
## @ wid, hgt - new desired width & height (no mod requirement)
## @ mod - mod value (default = minimum = 4)
## @ floor - always go to the smaller of the two nearest mod sizes (default true)
##
function UUSize(clip C, int wid, int hgt, int "mod", bool "floor")
{
mod = Max(4, Default(mod, 4))
flor = Default(floor, true)
out_wid = (flor) ? wid-(wid%mod) : wid+(wid%mod)
out_hgt = (flor) ? hgt-(hgt%mod) : hgt+(hgt%mod)
C ## Last==C
bdrX = out_wid - Width
bdrY = out_hgt - Height
bdrLt = Ceil(Float(bdrX) / 2.0)
bdrTp = Ceil(Float(bdrY) / 2.0)
bdrLt = bdrLt - (bdrLt % 2)
bdrTp = bdrTp - (bdrTp % 2)
bdrRt = (bdrX - bdrLt)
bdrBt = (bdrY - bdrTp)
AddBorders(
\ Max(0, bdrLt), Max(0, bdrTp),
\ Max(0, bdrRt), Max(0, bdrBt))
Crop(
\ ((bdrLt < 0) ? -bdrLt : 0),
\ ((bdrTp < 0) ? -bdrTp : 0),
\ ((bdrRt < 0) ? bdrRt : out_wid),
\ ((bdrBt < 0) ? bdrBt : out_hgt))
return Last
}
Reel.Deel
21st September 2015, 03:41
@ raffriff42
Neat script, the only downside is I want to pad (duplicate edge pixels) not add borders. ajp_anton's script does exactly want I but as I mentioned earlier it's cropping instead of padding. I tried tweaking it but only made it worse. :o
Desbreko
21st September 2015, 04:20
Gotta convert ints to floats before dividing or else the result is automatically converted to an int.
function padtomod(clip input, int hmod, int "vmod")
{
vmod = default(vmod, hmod)
w = input.width()
h = input.height()
hpad = ceil(float(w)/float(hmod))*hmod
vpad = ceil(float(h)/float(vmod))*vmod
left = round((hpad-w)/2)
top = round((vpad-h)/2)
return input.pointresize(hpad, vpad, -left, -top, hpad, vpad)
}
raffriff42
21st September 2015, 06:45
Neat script, the only downside is I want to pad (duplicate edge pixels) not add borders.OK, I have one...function Padding(clip c, int left, int top, int right, int bottom)
{
w = c.width()
h = c.height()
c.pointresize( w+left+right, h+top+bottom, -left, -top, w+left+right, h+top+bottom )
}
raffriff42
21st September 2015, 13:21
You might be interested in this, too:## based on GradFunkMirror
# http://forum.doom9.org/showthread.php?t=165658
#
function AddMirrorBorders(clip C, int "bdrx", int "bdry")
{
bdrx = Max(2, Default(bdrx, 16))
bdry = Max(2, Default(bdry, 16))
bdrLt = Max(0, bdrx - (bdrx % 2))
bdrTp = Max(0, bdry - (bdry % 2))
bdrRt = 2 * bdrx - bdrLt
bdrBt = 2 * bdry - bdrTp
CL = C.Crop(0, 0, bdrLt, 0)
CR = C.Crop(C.Width-bdrRt, 0, bdrRt, 0)
C2 = (bdrLt==0)
\ ? (bdrRt==0)
\ ? C
\ : StackHorizontal(C, CR.FlipHorizontal)
\ : (bdrRt==0)
\ ? StackHorizontal(CL.FlipHorizontal, C)
\ : StackHorizontal(CL.FlipHorizontal, C, CR.FlipHorizontal)
CT = C2.Crop(0, 0, 0, bdrTp)
CB = C2.Crop(0, C2.Height-bdrBt, 0, bdrBt)
C3 = (bdrTp==0)
\ ? (bdrBt==0)
\ ? C2
\ : StackVertical(C2, CB.FlipVertical)
\ : (bdrBt==0)
\ ? StackVertical(CT.FlipVertical, C2)
\ : StackVertical(CT.FlipVertical, C2, CB.FlipVertical)
return C3
}
Reel.Deel
21st September 2015, 15:08
Gotta convert ints to floats before dividing or else the result is automatically converted to an int.
function padtomod(clip input, int hmod, int "vmod")
{
vmod = default(vmod, hmod)
w = input.width()
h = input.height()
hpad = ceil(float(w)/float(hmod))*hmod
vpad = ceil(float(h)/float(vmod))*vmod
left = round((hpad-w)/2)
top = round((vpad-h)/2)
return input.pointresize(hpad, vpad, -left, -top, hpad, vpad)
}
Thanks Desbreko, works correctly now.
---
Now I need to figure out how to create another small function that crops based on the padding added by padtomod. Any ideas? Another thing I'm wondering about is how does padtomod treat a clip with odd dimensions? I now that PointResize can only do integers so does it just pad more to one side or am I missing something.
Desbreko
21st September 2015, 17:34
If the resolution is odd, it will put an extra pixel of padding on the bottom and right sides as needed.
Now that I take another look, the Round function in the left and top variable assignments isn't needed since, again, it's dividing two ints and any remainder is automatically truncated. So those lines could be simplified to this:
left = (hpad-w)/2
top = (vpad-h)/2
Or, if you want the extra padding on the top and left sides instead, you could change them to this:
left = ceil((hpad-w)/2.0)
top = ceil((vpad-h)/2.0)
To crop the padding, here's a function that takes a target width and height and crops the sides of the clip evenly to reach that resolution:
function CropEven(clip input, int target_width, int target_height)
{
w = input.Width()
h = input.Height()
hcrop = w-target_width
vcrop = h-target_height
lcrop = Floor(hcrop/2.0)
tcrop = Floor(vcrop/2.0)
rcrop = Ceil(hcrop/2.0)
bcrop = Ceil(vcrop/2.0)
return input.Crop(lcrop, tcrop, -rcrop, -bcrop)
}
Like the padtomod function, it will crop the extra pixels off the bottom and right sides if the target resolution is odd. If you want it to crop them from the top and left instead, you can swap the Floor and Ceil calls.
raffriff42
22nd September 2015, 00:49
This one expands with your choice of borders, duplication, or mirroring. It crops as well. First a test and demo routine...XXXSource(...)
## use a test source with detail near the edges (not colorbars)
## reduce contrast to see subtitles & colored border more clearly (test only)
(IsRGB) ? RGBAdjust(0.5, 0.5, 0.5, 1, 64, 64, 64) : ColorYUV(cont_y=-128, cont_u=-192, cont_v=-192)
## try to force image size to all values from (width-17, height-17) to (width+17, height+17)
## let's see what happens...
return Animate(Last, 0, 36, "CropExtest", -17, +17).Trim(0, 36)
## ...view in step mode, not real time!
##################################
function CropExtest(clip C, int delta)
{
## TEST OPTIONS:
_mod = 4 ## one of (4|8|16|32)
##[[ choose one:
_option = $ffff00 ## set border color
#_option = -1 ## extend
#_option = -2 ## mirror
#]]
_debug = true
## Animate() above requires final clip to be a constant size
awid = 960
ahgt = 540
C ## Last==C
return CropEx(Width+delta, Height+delta, _mod, border=_option, debug=_debug)
\ .Spline64Resize(awid, ahgt)
\ .Subtitle(String(delta, "delta=%0.0f"), align=8, size=Height/16)
}
Now the actual code:# http://forum.doom9.org/showthread.php?p=1739635#post1739635
## fka UUSize4
##################################
### symmetrically crop or expand a clip to ensure it is a certain size,
### with size forced to mod-4, mod-8 etc
##
## @ wid, hgt - new desired width & height (will be rounded to nearest 'mod')
## @ mod - mod value; one of (1|2|4|8|16|32); default 2
## (if negative, round UP, else round down)
## @ border - border color; default 0 (black border)
## (if -1, mode="extend"; if -2, mode="mirror")
## @ mode - expand method: ("extend"|"mirror"|"border") default/fallback="border"
## (overrides "border" argument for those who prefer this syntax)
## @ debug - show internal variables
##
function CropEx(clip C, float wid, float hgt, int "mod",
\ int "border", string "mode", bool "debug")
{
mode = Default(mode, "border")
mdd = Default(mod, 2)
border = Default(border, 0)
dbug = Default(debug, false)
mult = (mdd>0) ? -1 : 1
mdd = Abs(mdd)
Assert((mdd==1||mdd==2||mdd==4||mdd==8||mdd==16||mdd==32),
\ "CropEx: 'mod' argument not one of (1|2|4|8|16|32)")
border = Min(Max(-2, border), $ffffff)
wid = Round(wid)
hgt = Round(hgt)
out_wid = wid + mult * (wid % mdd)
out_hgt = hgt + mult * (hgt % mdd)
C ## Last==C
bdrX = out_wid - Width
bdrY = out_hgt - Height
bdrLt = Ceil(Float(bdrX) / 2.0)
bdrTp = Ceil(Float(bdrY) / 2.0)
bdrLt = bdrLt - (bdrLt % 2)
bdrTp = bdrTp - (bdrTp % 2)
bdrRt = (bdrX - bdrLt)
bdrBt = (bdrY - bdrTp)
mode = (mode=="extend") ? mode
\ : (mode=="mirror") ? mode
\ : (border==-1) ? "extend"
\ : (border==-2) ? "mirror"
\ : "border"
dbg="CropEx:" +String(mdd, " mod= %0.0f")
dbg=dbg+"\n"+String(C.Width, "in_wid= %0.0f") +String(C.Height, " in_hgt= %0.0f")
dbg=dbg+"\n"+String(wid, "arg_wid= %0.0f") +String(hgt, " arg_hgt= %0.0f")
dbg=dbg+"\n"+String(bdrX, "bdrX= %+0.0f") +String(bdrY, " bdrY= %+0.0f")
dbg=dbg+"\n"+String(bdrLt, "bdrLt= %+0.0f") +String(bdrTp, " bdrTp= %+0.0f")
dbg=dbg+"\n"+String(bdrRt, "bdrRt= %+0.0f") +String(bdrBt, " bdrBt= %+0.0f")
dbg=dbg+"\n"+String(out_wid, "out_wid= %0.0f") +String(out_hgt, " out_hgt= %0.0f")
dbg=dbg+"\n mode = '"+mode+"'" +String(border, " border= %0.0f")
(mode=="extend") ? padding(
\ Max(0, bdrLt), Max(0, bdrTp),
\ Max(0, bdrRt), Max(0, bdrBt))
\ : (mode=="mirror") ? MirrorBorders(
\ Max(0, bdrLt), Max(0, bdrTp),
\ Max(0, bdrRt), Max(0, bdrBt))
\ : AddBorders(
\ Max(0, bdrLt), Max(0, bdrTp),
\ Max(0, bdrRt), Max(0, bdrBt), border)
Crop(
\ ((bdrLt < 0) ? -bdrLt : 0),
\ ((bdrTp < 0) ? -bdrTp : 0),
\ ((bdrRt < 0) ? bdrRt : out_wid),
\ ((bdrBt < 0) ? bdrBt : out_hgt))
return (!dbug) ? Last : Subtitle(dbg, align=5, lsp=0)
}
##################################
function MirrorBorders(clip C, int left, int top, int right, int bottom)
{
bdrLt = Max(0, left )
bdrTp = Max(0, top )
bdrRt = Max(0, right )
bdrBt = Max(0, bottom)
C ## Last==c
(bdrLt==0) ? Last : StackHorizontal(
\ stack_to_wid(bdrLt, flip=true)
\ .Crop(0, 0, bdrLt, 0)
\ .FlipHorizontal,
\ Last)
(bdrRt==0) ? Last : StackHorizontal(
\ Last,
\ stack_to_wid(bdrRt, flip=true)
\ .Crop(Width-bdrRt, 0, bdrRt, 0)
\ .FlipHorizontal)
(bdrTp==0) ? Last : StackVertical(
\ stack_to_hgt(bdrTp, flip=true)
\ .Crop(0, 0, 0, bdrTp)
\ .FlipVertical,
\ Last)
(bdrBt==0) ? Last : StackVertical(
\ Last,
\ stack_to_hgt(bdrBt, flip=true)
\ .Crop(0, Height-bdrBt, 0, bdrBt)
\ .FlipVertical)
return Last
}
##############################
## Stack clip 'C' horizontally until it is at least 'wid' wide
function stack_to_wid(clip C, int wid, clip "R", bool "flip") {
R = Default(R, C)
flip = Default(flip, false)
C2 = (flip) ? C.FlipHorizontal : C
return (R.Width >= wid) ? R
\ : stack_to_wid(C, wid, StackHorizontal(R, C2))
}
##############################
## Stack clip 'C' vertically until it is at least 'hgt' high
function stack_to_hgt(clip C, int hgt, clip "R", bool "flip") {
R = Default(R, C)
flip = Default(flip, false)
C2 = (flip) ? C.FlipVertical : C
return (R.Height >= hgt) ? R
\ : stack_to_hgt(C, hgt, StackVertical(R, C2))
}
Reel.Deel
22nd September 2015, 02:15
If the resolution is odd, it will put an extra pixel of padding on the bottom and right sides as needed.
Now that I take another look, the Round function in the left and top variable assignments isn't needed since, again, it's dividing two ints and any remainder is automatically truncated. So those lines could be simplified to this:
left = (hpad-w)/2
top = (vpad-h)/2
Or, if you want the extra padding on the top and left sides instead, you could change them to this:
left = ceil((hpad-w)/2.0)
top = ceil((vpad-h)/2.0)
To crop the padding, here's a function that takes a target width and height and crops the sides of the clip evenly to reach that resolution:
function CropEven(clip input, int target_width, int target_height)
{
w = input.Width()
h = input.Height()
hcrop = w-target_width
vcrop = h-target_height
lcrop = Floor(hcrop/2.0)
tcrop = Floor(vcrop/2.0)
rcrop = Ceil(hcrop/2.0)
bcrop = Ceil(vcrop/2.0)
return input.Crop(lcrop, tcrop, -rcrop, -bcrop)
}
Like the padtomod function, it will crop the extra pixels off the bottom and right sides if the target resolution is odd. If you want it to crop them from the top and left instead, you can swap the Floor and Ceil calls.
CropEven is what I was looking for. Thanks again for the help. The additional info might also come in handy later. :)
padtomod and CropEven made things much easier :)
input = last
padtomod(16)
processing().moreprocessing()
CropEven(last, input.width(), input.height())
@raffriff42
Interesting script, will make note of it. Kinda reminds of PadResize()/PadMirror() (http://forum.videohelp.com/threads/369143-ResizersPack-MasksPack-PlaygroundPack-SmoothContrast-Logo-mod-functions).
Reel.Deel
14th November 2015, 01:19
How can I make padtomod (http://forum.doom9.org/showthread.php?t=172577#post1739499) add additional padding if the source is already the specified mod?
Right now I'm doing something like padtomod(16).Padding(8,8,8,8) / Crop(8,8,-8,-8,true).CropEven(src.width(), src.height()). It works but I was wondering if it can be done a bit better within padtomod.
Desbreko
15th November 2015, 05:14
This will let you specify a minimum amount of padding to be added to the left/right and top/bottom sides. So instead of PadToMod(16).Padding(8,8,8,8) you can just use PadToMod(16,16,8,8).
function PadToMod(clip input, int hmod, int "vmod", int "hmin", int "vmin")
{
vmod = Default(vmod, hmod)
hmin = Default(hmin, 0)
vmin = Default(vmin, hmin)
w = input.Width()
h = input.Height()
hpad = Ceil(Float(w)/Float(hmod))*hmod
vpad = Ceil(Float(h)/Float(vmod))*vmod
left = Floor((hpad-w)/2.0)
top = Floor((vpad-h)/2.0)
hadd = Ceil(Float(hmin*2)/Float(hmod))*hmod
vadd = Ceil(Float(vmin*2)/Float(vmod))*vmod
hpad = left < hmin ? hpad+hadd : hpad
vpad = top < vmin ? vpad+vadd : vpad
left = left < hmin ? left+hadd/2 : left
top = top < vmin ? top+vadd/2 : top
return input.PointResize(hpad, vpad, -left, -top, hpad, vpad)
}
Reel.Deel
24th November 2015, 14:34
Thanks Desbreko, it's working beautifully.
x = Width()%16 == 0 ? 8 : 0
y = Height()%16 == 0 ? 8 : 0
PadToMod(16, 16, x, y)
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.