回答您的问题。
先说简单的AAA的问题。AAA是从一个叫做AA的Script(毕竟是用AVS脚本写的,还算不上Plugin^^)演化而来的,所以如果您知道AA的全称,就知道怎么回事了。AA的全称是Anti Aliasing,即抗锯齿。而AAA则是Animation Anti Aliasing,用于动画的抗锯齿。就像名字说的一样,这个Script的作用是去除画面中的锯齿,不过代价就是画面大幅度模糊。当然,其对Deinterlace所产生的锯齿也有一定的修复作用,不过个人感觉效果不是那么明显罢了(Deinterlace所产生的锯齿通常比那种“天然锯齿”更为严重一些)。不过想想也是,边缘锯齿和边缘模糊本来就是一对矛盾,取哪边好,看您欣赏习惯了。
之后是LanczosResize的问题。AVS中与Resize有关的部分,都在resample.cpp和resample_functions.cpp里面。
我们首先看resample.cpp中CreateResizeH()这个函数(负责水平方向处理)。- PClip CreateResizeH(PClip clip, double subrange_left, double subrange_width, int target_width, ResamplingFunction* func, IScriptEnvironment* env)
- {
- const VideoInfo& vi = clip->GetVideoInfo();
- //...略
- if (subrange_left == int(subrange_left) && subrange_width == target_width && subrange_left >= 0 && subrange_left + subrange_width <= vi.width) {
- if (vi.IsRGB() || ((int(subrange_left) | int(subrange_width)) & 1) == 0) {
- return new Crop(int(subrange_left), 0, int(subrange_width), vi.height, 0, clip, env);
- }
- }
- return new FilteredResizeH(clip, subrange_left, subrange_width, target_width, func, env);
- }
复制代码 最外面一层if说的是,当subrange_left(左边切的像素数,在你的例子里是5)为整数且subrange_width(切到右边为止的像素,这里是711)与target_width(resize的目标宽度,这里是864)相等且subrange_left不为负数且subrange_left与subrange_width相加小于vi.width(片源的宽度,这里是720),这么多条件同时满足的时候才会继续下面一个if的判断。
下一个if,当片源是RGB或subrange_left、subrange_width为奇数的时候,会继续向下走。
下面新建了一个crop类的实体,把subrange_left和subrange_width输入进去,切边。
其实我们只要看第一个if就知道,这个crop在我们的例子中压根没用到。首先就是第一个if里面的第二个且条件subrange_width == target_width(我们这里是711 vs 864,不相等)没有满足,不会执行这个crop。
那么既然没有进crop,程序直接转入下一步,FilteredResizeH()。- FilteredResizeH::FilteredResizeH( PClip _child, double subrange_left, double subrange_width, int target_width, ResamplingFunction* func, IScriptEnvironment* env ) : GenericVideoFilter(_child), tempY(0), tempUV(0),pattern_luma(0),pattern_chroma(0)
- {
- pattern_luma = pattern_chroma = (int *)0;
- tempUV = tempY = 0;
- original_width = _child->GetVideoInfo().width;
- //...略
- if (vi.IsYUV())
- {
- //...略
- if (vi.IsYV12()) {
- pattern_chroma = GetResamplingPatternYUV( vi.width>>1, subrange_left/2.0, subrange_width/2.0, target_width>>1, func, true, tempY, env );
- } else {
- //...略
- }
- pattern_luma = GetResamplingPatternYUV(vi.width, subrange_left, subrange_width, target_width, func, true, tempY, env);
- }
- else
- //...略
- }
复制代码 在这里,已经把chroma和luma分开进行处理。我只留下了与YV12颜色空间下相关的代码。因为YV12的色度信号横向采样只有亮度信号的一半,所以就将vi.width、subrange_left、subrange_width、target_width全部除以2(xx>>1是除以2的一种更加高效的写法,因为subrange_left和subrange_width都是double类型的变量要除以2.0而不是2,所以不能像vi.width和target_width一样使用二进制方法来计算)。
接下来,它又将这些东西交给了一个叫做GetResamplingPatternYUV()的函数(源代码在resample_functions.cpp)。我看了一眼这个函数,似乎也没什么跟切边有关系的内容。
所以基本上可以推测:
- 在resize内部没有经过任何颜色空间转换。
- 当切边像素是奇数的时候,这些像素并非被切掉了,而是在resize的时候被无视了。因为Y和C被分开处理,所以并不受奇数偶数的限制。
我不是AVS作者,C也不是很好,以上纯推断。
在阅读代码过程中,得到了joshyu的帮助,大感谢!
(本来不想写代码分析的,还是写了 囧) |