Irrational-Encoding-Wizardry / descale

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

Feature requests for extended usage #8

Closed YomikoR closed 1 year ago

YomikoR commented 1 year ago

When trying to encode this anime (16-bit PNG) my filtering greatly benefited from applying the descale plugin in some uncommon ways. Since the ideas are theoretically reasonable, I wish they could be implemented from the plugin side in a better form.

Descaling by field

For this anime, a possible choice of parameters for getting rid of cross-conversion is

top_descaled = Delanczos(top_field, 1920, 360, src_top=1/6)
bot_descaled = Delanczos(bot_field, 1920, 360, src_top=1/6)

The result needs a src_top=1/3 shift for correct centering. Another "common" pair of offsets are src_top=1/12 for top field and src_top=-1/12 for bottom (example).

Descaling with border padding

By descaling as mentioned above, you may immediately see the border brightness artifact is much amplified in the output.

I guessed the artifact in the source was caused by upscaling with poor border handling, so I simulated the situation as if the fields were upscaled from 362p content with black top and bottom lines, and did the following instead:

top_descaled = Delanczos(top_field.std.AddBorders(top=1, bottom=1), 1920, 362, src_top=1/2, src_height=360 + 4/3).std.Crop(top=1, bottom=1)

The result was not perfect, but the amplification was successfully suppressed, so that post-processing was made possible with less radius and minimal strength. Similar approaches work for a number of 2010s anime with 720p native resolution with border brightness issues.

It might be possible to implement in the descale plugin by directly adjusting scaling weights, and hopefully the result could be more accurate than the current zero-value padding approach (which naturally incurs underflow).

Your comments are very much appreciated.

Frechdachs commented 1 year ago

Part 1 of this request is out of scope of this project and should be handled by a wrapper. Part 2 has been implemented in #10 by @YomikoR.