Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 11th March 2025, 09:12   #3241  |  Link
pinterf
Registered User
 
Join Date: Jan 2014
Posts: 2,465
Meanwhile, a nice "Animate" addition works on my test bench. This work is perhaps the last one before a feature freeze (Now the "Resize" force parameter, Gauss new parameters, and Animate is in the queue).

Animate can take an external function if you'd like more than a linear interpolation.

Even if you don't use an external function, a finer, more precise interpolation of integer values was implemented, and now 64-bit values are handled just fine. Internally, a 96.32-bit integer arithmetic is used for calculation. The calculated values are properly rounded.

Still undecided whether the custom function should return 0.0 at the beginning and 1.0 at the end of the range.

Now this is possible:

Code:
version.crop(8,32,16,16)
w=Width()
h=height()
force=3 # both H and V

Function Diff(clip src1, clip src2)
{
  return Subtract(src1.ConvertBits(8),src2.ConvertBits(8)).Levels(120, 1, 255-120, 0, 255, coring=false)
}

# rules for animate callback: float param named "stage"
# stage is called for values (0.0 , 1.0)
# For proper start-end conditions 
# f(0.0) = 0.0 and f(1.0) = 1.0 is a nice to have

function animhelper_lin(float "stage")
{
    return stage # full linear
}

function animhelper_exp(float "stage")
{
    return (stage*stage*stage)
}

fn_lin = Func(animhelper_lin)
fn_exp = Func(animhelper_exp)

#function
a=animate(0,100,"bicubicresize", fn_exp, \
16,16,1.0/3.0,1.0/3.0,-1.0,-1.0,w,h,force,\
16,16,1.0/3.0,1.0/3.0, 1.0, 1.0,w,h,force)

#function implemented as linear 
b=animate(0,100,"bicubicresize", fn_lin, \
16,16,1.0/3.0,1.0/3.0,-1.0,-1.0,w,h,force,\
16,16,1.0/3.0,1.0/3.0, 1.0, 1.0,w,h,force)

# classic, always linear
c=animate(0,100,"bicubicresize", \
16,16,1.0/3.0,1.0/3.0,-1.0,-1.0,w,h,force,\
16,16,1.0/3.0,1.0/3.0, 1.0, 1.0,w,h,force)

#check
d=Diff(b,c) # they are the same

StackHorizontal(a,b,c,d)

Last edited by pinterf; 11th March 2025 at 18:15. Reason: param value change
pinterf is offline   Reply With Quote
Old 11th March 2025, 13:54   #3242  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,298
Quote:
Originally Posted by pinterf View Post
Sound reasonable, for me it's zero effort to implement 0..3 allowing different H and V settings instead of a simple boolean.
Yes - integer control with 0 to 3 cases is enough.

About better versions of ConvertToXXX for conversions between full-band and sub-sampled chroma:

1. Downconversions (from 4:4:4 to 4:2:x) should work as today with single resize filter params.
The pre-filtering and resizing can be done in single call to resampler with user-provided kernel params.

2. Upconversions (from 4:2:x to 4:4:4) need addition of special 'pre-filter' params set (same as current resize filter). And optional 1 more stage for UV passing to resampler in no-resize mode.

If user make 'standard intermediate' upconversion to 4:4:4 (YUV or dematrix to RGB) - the 'pre-filter' params is not set and this stage is skipped. Short kernel resizer used to save from ringing at 2x upsampling of unconditioned UVs - like Bicubic or short Spline (16?) or even Point. Today we have default Bicubic and it work about good.

If user make 'final end_of_chain' upconversion to 4:4:4 - the 'pre-filter' params set to anti-gibbs low pass filtering (like Gauss or SinPow or UD2) and resize filter can be long kernel sinc with many taps (like Sinc or SincLin2 or Lanczos or Blackman).

Default 'pre-filter' params set is 'not set' and pre-filtering stage is disabled/skipped.

The minimum required is new version of

ConvertToYUV444(clip, [ string matrix, bool interlaced,
string ChromaInPlacement,
string chromaresample,
float param1, float param2, float param3] )

With added UV prefiltering stage it expected:

ConvertToYUV444(clip, [ string matrix, bool interlaced,
string ChromaInPlacement,
string chromaprefilter,
float pre_param1, float pre_param2, float pre_param3,
string chromaresample,
float param1, float param2, float param3] )

where prefilter is only applied to further upsampled direction (H if input is 4:2:2 or H and V if input is 4:2:0). This expected to have performance and RAM usage benefit over user-script with extracting UV planes for prefiltering (and optional resizing) and combining back to YUV.

Last edited by DTL; 11th March 2025 at 14:12.
DTL is offline   Reply With Quote
Old 11th March 2025, 14:23   #3243  |  Link
pinterf
Registered User
 
Join Date: Jan 2014
Posts: 2,465
Until I understand why on earth a second treat is needed on chroma , a question:
Since those Gauss extra parameters don't do any harm and give some freedom, I adopted them. Since defaults are kept, this is fully compatible.
It's so simple, that I don't think I can expect change of mind on this topic, isn't it?
pinterf is offline   Reply With Quote
Old 11th March 2025, 14:40   #3244  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,298
Quote:
Originally Posted by pinterf View Post
a question:
Since those Gauss extra parameters don't do any harm and give some freedom, I adopted them. Since defaults are kept, this is fully compatible.
It's so simple, that I don't think I can expect change of mind on this topic, isn't it?
Yes - I hope the changes are final. Some post-ideas on sources text:

1. The 'support' limits for SincResize and GaussResize are properties of resampler engine used and not kernels - so we can make
#define MAX_SUPPORT 150

(as current SincResize - it really depends on resampler's ability to process with enough performance and require not very small frame size) and make clamping of support (and taps) (0, MAX_SUPPORT) in both SincResize and GaussResize.

2. The highest p for GaussResize is naturally limited to about 50..100 where it becomes equal to PointResize (support falls greatly below 1) and do not decrease 'blur' any more. But lowest of 0.01 may be not enough if user process HD or UHD frame and want more soft blur and have enough compute resources. So the MAX_SUPPORT and min valid p-param for GaussResize may be subject of research and/or user-requests for max softening required. If we allow min p-param to 0.001 (or lower) - the MAX_SUPPORT define also need to be somehow higher (may be 250 or 500 - need to check the s-equation output). Or some research need about how much 'support' size can use current AVS+ resample engine (at how large frame sizes and colour-subsampling formats).

Last edited by DTL; 11th March 2025 at 15:03.
DTL is offline   Reply With Quote
Old 11th March 2025, 14:46   #3245  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,298
"Until I understand why on earth a second treat is needed on chroma "

You need to dig deeply to the beginning of the digital moving pictures on this planet at the current civilization - it is about 1/2 or century in the past. When the very first ITU BT 601 rec/standard on digitizing of analog video was developed. There were (may be still present) some articles about that times at EBU website (or Internet archive). The key words is something about 'we finally agreed on UV low-pass filters defined in BT rec.601 for 4:2:2 subsampled chroma but it cause UV signals ringing as hell'. It was designed to allow many generations YUV4:2:2<->RGB transcodings in the production chain without great chroma sharpness losses. I not remember the exact document link - will try to search one more time some later.

Last edited by DTL; 11th March 2025 at 15:02.
DTL is offline   Reply With Quote
Old 11th March 2025, 15:16   #3246  |  Link
tormento
Acid fr0g
 
tormento's Avatar
 
Join Date: May 2002
Location: Italy
Posts: 2,925
The killer feature to add would be CUDA support, such as NekoPanda started. I just dream of that.

And I think I will keep on dreaming.
__________________
@turment on Telegram
tormento is offline   Reply With Quote
Old 11th March 2025, 15:42   #3247  |  Link
pinterf
Registered User
 
Join Date: Jan 2014
Posts: 2,465
AviSynth is a framework that provides the necessary ecosystem for creating a filter chain that can keep data in GPU memory across filters, eliminating the need to transfer data back and forth between the CPU and GPU. Dreaming about a CUDA-core AviSynth is pointless without plugins, unless one is satisfied with a CUDA-accelerated Version() clip.

There are other ways to achieve this if authors write their own plugins and follow their own rules.

By the way, even Nekopanda didn't rewrite everything. They specifically rewrote filters to support only 8-bit, others only YV12, and MvTools with a block size of 8x8.
pinterf is offline   Reply With Quote
Old 11th March 2025, 16:58   #3248  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,298
I did some simulation with
'standard bicubic subsampled chroma 4:2:2 ColorBars' names _b
and
'max possible bandwidth subsampled chroma 4:2:2 ColorBars" names _s

With different upconversions to 4:4:4 and 4x sinc-based displaying resizing (LanczosResize)



Script:
Code:
Function Convert422To444dp(clip c)
{
  uc=UToY(c)
  vc=VToY(c)
  uc=UserDefined2Resize(uc,src_left=0.001,uc.width, uc.height, b=115, c=9)
  vc=UserDefined2Resize(vc,src_left=0.001,vc.width, vc.height, b=115, c=9)
  uc=SincLin2Resize(uc, src_left=0, uc.width*2, uc.height, taps=16)
  vc=SincLin2Resize(vc, src_left=0, vc.width*2, vc.height, taps=16)
  yuv444=CombinePlanes(c, uc, vc, planes="YUV", source_planes="YYY", pixel_type="YUV444P8")
  return yuv444  
}

Function Convert422To444sp(clip c)
{
  return ConvertToYUV444(c, chromaresample="userdefined2", param1=115, param2=9)
}

ColorBarsHD(2048,150)
UserDefined2Resize(width/8, height, b=120, c=13) # YUV 4:4:4 cond

bt601_chroma_b=ConvertToYUV422(chromaresample="bicubic") # AVS_bicubic 42x chroma - half band uncond
bt601_chroma_s=ConvertToYUV422(chromaresample="sinclin2") # close_bt 601 42x chroma - half band uncond

#single pass 2x upsize no anti-Gibbs
sp_noag_bic_b=ConvertToYUV444(bt601_chroma_b).Subtitle("sp_noag_bic_b")
sp_noag_bic_s=ConvertToYUV444(bt601_chroma_s).SubTitle("sp_noag_bic_s")

#single pass 2x upsize + use anti-Gibbs kernel
sp_ag_b=Convert422To444sp(bt601_chroma_b).Subtitle("sp_ag_b")
sp_ag_s=Convert422To444sp(bt601_chroma_s).Subtitle("sp_ag_s")

#dual pass
dp_ag_b=Convert422To444dp(bt601_chroma_b).Subtitle("dp_ag_b")
dp_ag_s=Convert422To444dp(bt601_chroma_s).Subtitle("dp_ag_s")

#last=StackVertical(sp_noag_bic,sp_noag, sp_ag, dp_ag)
last = StackVertical(sp_noag_bic_b, sp_noag_bic_s, sp_ag_b, sp_ag_s, dp_ag_b, dp_ag_s)

LanczosResize(width*4, height, taps=16)

ConvertToRGB24(matrix="PC.601")
The worst case ringing is when standard bicubic-based upsampler meet highest possible bandwidth subsampled chroma (possible from some sources). But if source produced with AVS-like ConvertTo422 with bicubic downsampled chroma it works good enough (AVS resizers are good complement each other like bicubic for downsize and upsize).

The single pass chroma upconverting with anti-ring kernel do not shows significant difference in ringing over pre-filtered chroma it is original frequency domain + second pass sinc-based flat upsampler (dual-pass chroma processing). Also the dark shadows in colour transients looks a bit smaller in single pass processing. So prefiltered chroma way may be left for special use cases (if it may benefit with some current user's source) and may be done in scripting.

Last edited by DTL; 11th March 2025 at 17:06.
DTL is offline   Reply With Quote
Old 11th March 2025, 18:17   #3249  |  Link
pinterf
Registered User
 
Join Date: Jan 2014
Posts: 2,465
Avisynth+ 3.7.3 r4241
https://github.com/pinterf/AviSynthP...ag/v3.7.3.4241

https://avisynthplus.readthedocs.io/...gelist374.html
https://avisynthplus.readthedocs.io/...rs/resize.html
https://avisynthplus.readthedocs.io/...s/animate.html

Last week changes
Code:
20250311 3.7.3 r4241
--------------------
- Animate: Custom function option
- Animate: more precise granularity for integer interpolation, allow 64 bit input
- Animate: add proper rounding for integer interpolation
- Resizers: add "force" integer parameter to force the resizing process even if Avisynth decided it's not needed
- GaussResize: add "b" and "s" parameters See :doc:`Resize Filters <corefilters/resize>`.

20250309 3.7.3 r4217
--------------------
Expr: implement tanf in JisASM

  Benchmark script
  
    BlankClip(1000,1280,720,pixel_type="Y8")
    # swipes the range between -Pi to +Pi
    s = "sxr 2 * 1 - 3.14159254 * 1 * tan 10 * 128 +"
    # swipes the range between -5Pi to +5Pi
    # s = "sxr 2 * 1 - 3.14159254 * 5 * tan 1 0 * 128 +"
    a= Expr(s,  optSSE2 = false, optAVX2=false, OptVectorC=False)
    b= Expr(s,  optSSE2 = false, optAVX2=false)
    c= Expr(s,  optSSE2 = True, optAVX2=false)
    d= Expr(s,  optSSE2 = True, optAVX2=True)

    a # or b or c or d

  Results:

                       MSVC Intel ICX LLVM
    SinglePixel C    :  48   66 [fps]
    Vector friendly C: 122  175
    JitASM SSE       :    345  (same for both)
    JitASM AVX       :    727  (same for both)


20250306 3.7.3 r4612
--------------------
Expr: Rewrite the C (non-Intel-JIT) path to support vectorization, if the compiler is capable.

    I created this for non-Intel platforms where the (Intel SSE2-AVX2) JIT compiler does not work.

    Even if the compiler is not very advanced (MSVC khhhhmm..) this approach is faster because it 
    has less overhead when interpreting the instruction flow. It processes 16, 8, 4, and 1 floats
    when handling the horizontal line, taking the largest chunks it can then finishing the rest
    with the smaller ones.

    Benchmarks (x64 bit). For comparison, I also provide the JIT results. 

    Script (optSSE2 = false disables JIT):
    
        # Mandelbrot
        ColorBarsHD()
        a="X dup * Y dup * - A + T^ X Y 2 * * B + 2 min Y^ T 2 min X^ "
        b=a+a
        c=b+b
        blankclip(width=960,height=640,length=1600,pixel_type="YUV420P8")
        Expr("sxr 3 * 2 - -1.2947627 - 1.01 frameno ^ / -1.2947627 + A@ X^ syr 2 * 1 - 0.4399695 "
        \ + "- 1.01 frameno ^ / 0.4399695 + B@ Y^ "+c+c+c+c+c+b+a+"X dup * Y dup * + 4 < 0 255 ?",
        \ "128", "128",optSSE2 = false, optAVX2=false) # optVectorC=true default

    MSVC: Microsoft VC, actual VS2022 version.
    Intel: Intel C++ Compiler 2025 - LLVM based, aka ICX.

    "Base" means the instruction set is not specified: SSE2 is the minimum for x64. 

    Compiler/Settings                      VectSize  FPS  
    -------------------------------------- ---------- -----
    MSVC debug                             1         0.27 
    Intel (base + optional AVX2 paths)     1         1.01 (! Mixed instruction set support, slow) 
    MSVC Base                              1         1.71 VectorSize=1, not optimal :)
    MSVC old single variable C:            -         2.82 
    Intel old single variable C:           -         2.90 
    MSVC Base                              16        4.47 (initial Proof of Concept version) 
    MSVC AVX2                              16        4.59 (initial PoC version) 
    MSVC Base                              16        5.94 
    MSVC AVX2                              16        6.04 
    Intel Base                             16        6.29 (initial PoC version) 
    Intel AVX2 optional AVX512 -Qax:AVX512 16        12.60 (! Mixed instruction set support, slow)
    Intel Base                             16        14.70 
    Intel AVX2                             16        19.20 
    Intel AVX512                           16        20.10 
    MSVC JIT SSE2                          2x4       59.00 (dual lanes, XMM regs)
    MSVC JIT AVX2                          2x8       128.00 (dual lanes,YMM regs)

    In this test, where dual processor optimization was enabled, Intel performed poorly (though 
    it still achieved twice the speed of MSVC). It seems that dynamically dispatching code fragments
    to different instruction sets incurs significant overhead.

    Conclusion: 
    
    We should better avoid builds mixed-code sets.
    Since AVX2 has been generally supported for at least ten years, creating a non-mixed 
    AVX2-only compilation is a reasonable enhancement.
    
    Looking at the numbers, achieving one-third the speed of the old SSE2 JIT, which we considered 
    fast, is quite impressive. Even x86/x64 users can benefit from this speedup. If the Expr contains
    specific trigonometric functions (tan, asin, acos, atan) that have no JIT implementation, then 
    Avisynth cannot use JIT and falls back to the C implementation.
    
    Expr has now a new debug parameter: bool optVectorC (default true) which C code to run if non-JIT is used.
pinterf is offline   Reply With Quote
Old 11th March 2025, 19:43   #3250  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,298
Now you can also update Notes to the Blur() - https://avisynthplus.readthedocs.io/...ters/blur.html

"If you need a larger radius Gaussian blur,..."

GaussResize(width, height, force=3, p=0.1, s=0)

It looks github web do not allow to add comments on lines or at least full .rst file. https://github.com/pinterf/AviSynthP...t?plain=1#L438

Current: Force the resizing process even if the dimensions remain unchanged and ``src_width`` or ``src_top``
are zero. Useful to intentionally prevent sudden visual differences that might occur if resizing
is unexpectedly skipped.

* 0 - return unchanged if no resize needed
* 1 - force H - Horizontal resizing phase
* 2 - force V - Vertical resizing phase

Better text: Force the resizing or convolution with resize kernel (filtering) process even if the dimensions remain unchanged and ``src_width`` or ``src_top``
are zero. Useful to intentionally prevent sudden visual differences that might occur if resizing
is unexpectedly skipped or if convolution only (filtering) without resize is required.

* 0 - return unchanged if no resize needed
* 1 - force H - Horizontal resizing or convolution (filtering) phase
* 2 - force V - Vertical resizing or convolution (filtering) phase

For GaussResize p :
"original equation is s = sqrt(-ln(0.01)/(param*ln(b))"

p-param passed to GaussResize is internally scaled by 0.1 (old AVS arguments were integers only ?). So from user's view original equation is s = sqrt(-ln(0.01)/((p-param * 0.1)*ln(b))

Also in "as s = sqrt(4.6 / ((param * 0.1) * log(b)))" - log(b) in C-library is log based e-number (natural). So for less messy description may be better to write as 's = sqrt(4.6 / ((p * 0.1) * ln(b)))' . Where ln(b) is more universal math equation for natural logarithm. And 'p' and 'b' are directly entered by user params values.

For GaussResize b :
b: Controls the blurring. Valid range: 1.5 to 3.5.

Better text:
b: Controls the blurring. Valid range: 1.5 to 3.5. Filter kernel is b^(-p*0.1*(x^2)) . Default b is 2.0 to be compatible with pre-3.7.4 use cases. If high precision Gauss kernel is required (for example for filtering applications) it is recommended to use the base of the natural logarithm 2.71828.

Last edited by DTL; 11th March 2025 at 22:31.
DTL is offline   Reply With Quote
Old 12th March 2025, 10:23   #3251  |  Link
pinterf
Registered User
 
Join Date: Jan 2014
Posts: 2,465
Quote:
Originally Posted by DTL View Post
Now you can also update Notes to the Blur() -
[...]
GaussResize(width, height, force=3, p=0.1, s=0)
[...]
Thanks, for me it's better to see all your proposed changes here rather than at random places as comments. I prefer not having to think over where the modifications are.
pinterf is offline   Reply With Quote
Old 12th March 2025, 14:48   #3252  |  Link
LigH
German doom9/Gleitz SuMo
 
LigH's Avatar
 
Join Date: Oct 2001
Location: Germany, rural Altmark
Posts: 7,199
What error exactly? Please quote.
__________________

New German Gleitz board
MediaFire: x264 | x265 | VPx | AOM | Xvid
LigH is offline   Reply With Quote
Old 12th March 2025, 18:18   #3253  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,298
Now it is script-based simulation of what we have now with AddBorders and what is nice to have in single call to AddBorders with options of filtering new transients:

Code:
Function AddBordersHF(clip c, int left, int right, int flt_rad)
{
  unflt=AddBorders(c, left, 0, right, 0)
  flt=GaussResize(unflt, unflt.width, unflt.height, p=10, b=2.71828, s=0, force=1)
  uf_internal=Crop(c, flt_rad, 0, c.width-flt_rad*2, c.height)
  return Overlay(flt, uf_internal, x=left+flt_rad, y=0)
}

Function AddBordersVF(clip c, int top, int bottom, int flt_rad)
{
  unflt=AddBorders(c, 0, top, 0, bottom)
  flt=GaussResize(unflt, unflt.width, unflt.height, p=10, b=2.71828, s=0, force=2)
  uf_internal=Crop(c, 0, flt_rad, 0, c.height - flt_rad*2)
  return Overlay(flt, uf_internal, x=0, y=top+flt_rad)
}


ColorBarsHD(2000,2000)
UserDefined2Resize(width/10, height/10)

std=AddBorders(10, 10, 10, 10)

AddBordersHF(last, 10, 10, 2)
AddBordersVF(last, 10, 10, 2)

StackVertical(std, last)

LanczosResize(width*4, height*2, taps=16)


It is not very high-performance way because filtering is processed over full frame (the small extras from input frame is enough around transients areas of size about (resizer's 'support' * 2 + 2 * flt_rad)).

The functions of AddBordersHF and AddBordersVF expected to be implemented in compiled form (and called one or both if H_or_V or H_and_V borders added).

Expected new params to AddBorders (and LetterBox):
1. Filtering kernel name and its params (+4 new params). Defaults: Gauss, p=10, b=2.71828, s=0)
2. Radius of filtered transient (integer, typically 1 (already good quality) or 2 or 3 (even better quality) is enough, 0 mean filtering is disabled)

For best performance in compiled form it may be done as 'in-place' transform - read narrow parts of source frame to filtering (convolution) engine and replace flt_rad*2 number of samples around transient with filtered samples. No full-frame RAM read and store.

Last edited by DTL; 12th March 2025 at 18:45.
DTL is offline   Reply With Quote
Old 12th March 2025, 19:23   #3254  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,405
@Jamaika
What exactly is the question ? I have update according DTL pull request, but not builds for now.

Still not add the "force" parameter, and this one will probably not be in the desampling, as it has no effect on the parameters of the resampling filter.
And still not updated the NNEDI internal call parameters...
Please, stop changing the resamplers and giving me more work...
__________________
My github.
jpsdr is offline   Reply With Quote
Old 12th March 2025, 21:11   #3255  |  Link
pinterf
Registered User
 
Join Date: Jan 2014
Posts: 2,465
Quote:
Originally Posted by DTL View Post
Now it is script-based simulation of what we have now with AddBorders and what is nice to have in single call to AddBorders with options of filtering new .
Meanwhile I did my study as well. I did a full AddBorders first, then cropped and blur-resized four smaller areas: a wider rectangle around the left/right/top/bottom margins, N pixels aouround the transient border area. Then with a specially written new filter MultiOverlay (quick one-pass overlay of N clips onto an original, with N pairs of xy coordinates) I copied back these blurred rectangles onto the transient area. In my proof of concept the force-resize was made on +/- 10 pixel wide rectanges from which I copied back only the +/- 1,2 or 3 pixel wide central part. Resizing a broader part is necessary, too small dimension are giving error.
pinterf is offline   Reply With Quote
Old 12th March 2025, 22:02   #3256  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,298
There are many possible solutions for the filtering/blurring of new created transients with different quality/performance balance.

Usage of 'full-blood' specially designed kernels for resizing and wide/long-enough kernels/convolutions/supports allows to create best quality but requires more computing or usage of more complex convolution engines (like core resampler engine of AVS).

But in simple cases in the past we sometime uses much more simple filter Blur() with also H or V only processing depending on the direction of new added transient (setting amountH or amountV params only to non-zero). It is much more simple 3-samples wide kernel convolution-only engine and it gives not very bad result (may be about 70..90+% of possible quality of GaussResize convolution). But its kernel is more simple and more limited in possible max quality (because of too low support/length too).

Some 'task size estimations' :
For p=10 and b=2.72 in current GaussResize the 1% gauss-kernel 'side_size/support' is sqrt(4.6 / ((p * 0.1) * ln(b))) = 2.144 and it sort of 'provides 99% quality of gauss-kernel'. It mean it is enough to process +-3 input samples (total kernel size of 6) in convolution. With new required calculated samples of +-3 max to the sides of new created transient it mean we need to read 3+3=6 samples to the 'sides' of transient max (and total of 12 ?) to send to convolution engine. With 'radius' of 1 it is 1+3=4 and input 8 samples max. If number of new added (or filled in case of LetterBox) samples are not enough for current convolution step - we duplicate last edge sample (it may be already working in Blur() filter design). Sort of 'virtually expanded image of the same colour'.

For colour-subsampled formats the AVS resampler engine (used in 'resizers') may require more size of the buffer to process.

Also the 'no-resize' convolution engine from GeneralConvolution() filter can be used too. But as user need to manually create kernel coefficients it is not very easy to control so rarely used.

Last edited by DTL; 12th March 2025 at 22:36.
DTL is offline   Reply With Quote
Old 12th March 2025, 23:59   #3257  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,298
Some issue with Info() on small frame size ?
Code:
ColorBarsHD(2000,2000)
BilinearResize(width/10, height/10)
info()
Cropped upper part (shifted up ?)


Also a question to make scripting easier - can we skip
int target_width, target_height =
Width and height of the returned clip.
params in Resize() ? If not set - can it assume it is equal to input ? Or at least if force > 0. If resize engine used for no-resize filtering - it is too long and possibly source of an error to search and type input width and height.

Last edited by DTL; 13th March 2025 at 00:59.
DTL is offline   Reply With Quote
Old 14th March 2025, 16:34   #3258  |  Link
pinterf
Registered User
 
Join Date: Jan 2014
Posts: 2,465
AviSynth+ 3.7.3 r4246
https://github.com/pinterf/AviSynthP...ag/v3.7.3.4246

AddBorders and LetterBox: add transient filtering.
new filter: MultiOverlay. Bulk copy-paste from clips.

More info:

Latest changes since 3.7.3: https://avisynthplus.readthedocs.io/...gelist374.html
AddBorders doc: https://avisynthplus.readthedocs.io/...ddborders.html
MultiOverlay doc: https://avisynthplus.readthedocs.io/...tioverlay.html

And at this point I'd like to stop adding more new features to 3.7.3.
pinterf is offline   Reply With Quote
Old 14th March 2025, 18:53   #3259  |  Link
hello_hello
Registered User
 
Join Date: Mar 2011
Posts: 4,999
Is the behavior of the Defined, Default and VarExist functions inconsistent?
I ask, as I've not used VarExist before and I expected it to be the same as Defined, in that the specified variable shouldn't be a string.

Z = VarExist(X)
I don't know what "X" means
(couldn't not knowing what "X" means return false?)

Z = VarExist("X")
Z is false

X = undefined() or any value other than a string
Z = VarExist(X)
Invalid arguments to VarExist

X = undefined()
Z = VarExist("X")
Z is true

X = "Y"
Z = VarExist(X)
Z is false
(should this return "invalid arguments to VarExist" if the variable must be specified as a string?)

X = "Y"
Z = VarExist("X")
Z is true

The Default and Defined functions seem to interpret string literals as variables.
I've never used them that way before, but after experimenting with VarExist, I thought I'd try it.

Z = defined(X)
I don't know what "X" means.

X = undefined()
Z = defined("X")
Z is true

X = undefined()
Z = defined(X)
Z is false

Last edited by hello_hello; 14th March 2025 at 19:25.
hello_hello is offline   Reply With Quote
Old 14th March 2025, 20:06   #3260  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,298
Quote:
Originally Posted by pinterf View Post
AviSynth+ 3.7.3 r4246
https://github.com/pinterf/AviSynthP...ag/v3.7.3.4246

AddBorders and LetterBox: add transient filtering.
Thank you.

The most important Note to the documentation of AddBorders and LetterBox (and possibly any other filters used same method of conditioning of the transients in the future):

The anti-ringing filtering of transients created by currently implemented solutions is mostly valid (have most of the design-quality) for current/working Transfer Domain. Because currently AVS+ core does not support Transfer Domain conversions - it can only apply any filtering in Current Transfer Domain and can not serve as Transfer Domain conversion tool inside its filters.

It means if a user prepares content for being resized (processed with any interpolation) in another Transfer Domain (like in Linear) - the quality of anti-ringing created in another Transfer Domain will be degraded by Transfer Domain conversion. So if a user needs to prepare a content for any Transfer Domain with highest quality of anti-ringing filtered transients - the filters like AddBorders/LetterBox(r>0) must be applied to the clip converted to the required Transfer Domain first.

Typically AVS+ process clips with data in input data System Transfer Domain (we need clip/frameProperty with current Transfer Domain tagging some day) if users do not apply Transfer Domain conversion.

So example for preparing transients for being mostly compatible with Linear Transfer Domain (for example source in bt.601 System Transfer Domain and user prepare content for best quality resize in Linear Transfer Domain):

(in pseudo-filters)

ConvertTransfer(output="linear')
AddBorders(10, r=1)
..apply any other filters in Linear Transfer Domain..
ConvertTransfer(output="some_system')

Currently Transfer Domain conversions are supported by external plugins (avsresize, fmtconv and jpsdr's plugins and may be others).

Last edited by DTL; 15th March 2025 at 14:58.
DTL is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 21:20.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2025, vBulletin Solutions Inc.