Irrational-Encoding-Wizardry / descale

VapourSynth plugin to undo upscaling
MIT License
71 stars 14 forks source link

bug in src_left and src_top #2

Closed kgrabs closed 7 years ago

kgrabs commented 7 years ago

So we've all seen Kyoto Animation's "955.5p" meme by now. I decided to test it out with a src_top workaround and ended up with some wrong results with descale compared to fmtc with invks: https://diff.pics/IzYyWw1owqtv/1

Essentially what this script ahead does is pads the input clip to 1920x1080.565149136578 with debicubic's src_top parameter, and reverses the supposed "1699x955.5" upscale to 1699x956. Then it's upscaled back to 1080p using src_top=0.5 to crop to 955.5p

The problem seems to effect both the src_left and src_top parameters

import vapoursynth as vs
core = vs.get_core()

b = 0.
c = 0.5
w = 1699.
h = 955.5
w_mod1 = 1699
h_mod1 =956
src_left_down = (1920.*w_mod1/w-1920.)*-1.
src_top_down = (1080.*h_mod1/h-1080.)*-1.
src_left_up = w_mod1-w
src_top_up = h_mod1-h
src = core.lsmas.LWLibavSource('F:\\[BDMV] Hibike! Euphonium 2 Vol.1\\BDMV\\STREAM\\00000.m2ts')
src16 = core.resize.Point(src, format=vs.GRAY16)
src32 = core.resize.Point(src, format=vs.GRAYS)
deb = core.descale.Debicubic(src=src32, width=w_mod1, height=h_mod1, b=b, c=c, src_left=src_left_down, src_top=src_top_down)
#deb = core.fmtc.resample(src32, w_mod1, h_mod1, sx=src_left_down, sy=src_top_down, kernel='bicubic', a1=b, a2=c, invks=True, invkstaps=5)
diff = core.resize.Bicubic(deb, 1920, 1080, filter_param_a=b, filter_param_b=c, src_left=src_left_up, src_top=src_top_up, range_s='limited', format=vs.GRAY16, dither_type='none')
diff = core.std.MakeDiff(src16, diff)
diff.set_output()
Frechdachs commented 7 years ago

Contrary to fmtconv and AviSynth's Debilinear/Debicubic src_left and src_top refer to the initial upscale.

For example, if an upscale was done with

src = some_720p_clip
upscaled = core.resize.Bilinear(src, 1920, 1080, src_top=0.5)

then it would be reversible with

core.descale.Debilinear(upscaled 1280, 720, src_top=0.5)

You can convert src_left/top from Descale to fmtconv: src_top * upscaled_height / native_height * (-1) The following two clips should get shifted by the same amount:

a = core.descale.Debilinear(src, 1280, 720, src_top=0.5)
b = core.fmtc.resample(src, 1280, 720, sy=0.5 * src.height / 720 * -1, kernel='bilinear', invks=True)

You can also convert it from fmtconv to Descale: src_top * native_height / upscaled_height * (-1)

In Avisynth

Debilinear(src, 1280, 720, src_top=-0.25, src_height=src.Height() - 0.25)

would be similar to

descale.Debilinear(src, 1280, 720, src_top=0.25 * 720 / src.height)

So in your example src_top_down should be (1080 * 956 / 955.5 - 1080) * 956 / 1080 which is the same as pow(956, 2) / 955.5 - 956.

Also two things regarding your script:

  1. In Python 3 / is always a float division, you dont have to append . or .0 to your numbers. // is an integer division.

  2. You should use the new method of getting the core core = vs.core. It's there since R37 and is much safer to use, especially when used inside imported scripts. Previously you had to call get_core() in every function of the imported script individually.