Scaling of EWA Lanczos function with non-standard window
Posted: 2015-02-23T13:34:59-07:00
EDIT: Never mind, I figured it out. Annotations in bold.
Hey,
I'm trying to implement EWA Lanczos rescaling in my application, and I'm trying to figure out what the best way to do this is. For starters, the underlying problem is that the true radius of the function (at 3 taps) is something like 3.238 instead of 3.0, so we need to consider all source values up to and including those at that distance from the pixel.
Since we use a rectangular pixel array, this means that I will potentially have to include all of the pixel values of radius 4 in my search space, since the weight might be non-zero for anything between radius 3 and radius 4 - that is, the algorithm iterates over all 8x8 = 64 values, instead of only needing to consult 3x3 = 36 values. This is quite a bad performance hit, so I'm thinking about ways to avoid it. I can avoid it almost entirely by adding a simple check to see if the distance is greater than the position. That check is surprisingly efficient on the GPU, even though it's a conditional branch. So this problem is already sort of solved.
One of the things I tried in my search is to simply window the function differently - that is, use jinc(x) * jinc(x * jinc_zeros[0] / taps) instead of the traditional jinc(x) * jinc(x * jinc_zeros[0] / jinc_zeros[taps-1]).
This crude hack makes the function reach 0 at 3.0 instead of 3.22, because the window is smaller. However, this changes the function's properties - it loses some of its visual quality (not sure how to describe it), and it also no longer blurs hash patterns as strongly.
I then wondered if I could simply change the scaling of the first term as well, to make them line up again. In essence, this is what your LanczosRadius does. The natural conclusion would be to scale it so that it reaches 0 at 3.0 as well, that is: jinc(x * jinc_zeros[taps-1] / taps) * jinc(x * jinc_zeros[0] / taps). However, this particular scaling works less well than intended - it also doesn't blur hash patterns, for example. I have found an alternative scaling value, that is a value of c such that jinc(x / c) / jinc(x * jinc_zeros[0] / taps) produces a similar result (blurred hash pattern, visual quality) to the true Lanczos function, but I can't figure out where it comes from: I'm using approximately 1.05, which I've arrived at by trial and error (picking values until the hash pattern disappears almost completely). I was actually scaling *both* jinc functions, so it was really jinc(x / c) / jinc(x * jinc_zeros[0] / taps / c) I was testing
Note that for other taps, this value changes. For 4 taps, I arrived at something like 1.20. I don't know where either of these two figures come from.
Can somebody help me figure this out? Is there perhaps another way to compute EWA Lanczos3 more efficiently than by consulting a 8x8 matrix of pixels? Is it possible to use something like a bilinear lookup to reduce this to 4x4? (I know the technique works when the weight matrix is strictly positive, but I'm not sure if it does for weight functions that reach negative values)
Hey,
I'm trying to implement EWA Lanczos rescaling in my application, and I'm trying to figure out what the best way to do this is. For starters, the underlying problem is that the true radius of the function (at 3 taps) is something like 3.238 instead of 3.0, so we need to consider all source values up to and including those at that distance from the pixel.
Since we use a rectangular pixel array, this means that I will potentially have to include all of the pixel values of radius 4 in my search space, since the weight might be non-zero for anything between radius 3 and radius 4 - that is, the algorithm iterates over all 8x8 = 64 values, instead of only needing to consult 3x3 = 36 values. This is quite a bad performance hit, so I'm thinking about ways to avoid it. I can avoid it almost entirely by adding a simple check to see if the distance is greater than the position. That check is surprisingly efficient on the GPU, even though it's a conditional branch. So this problem is already sort of solved.
One of the things I tried in my search is to simply window the function differently - that is, use jinc(x) * jinc(x * jinc_zeros[0] / taps) instead of the traditional jinc(x) * jinc(x * jinc_zeros[0] / jinc_zeros[taps-1]).
This crude hack makes the function reach 0 at 3.0 instead of 3.22, because the window is smaller. However, this changes the function's properties - it loses some of its visual quality (not sure how to describe it), and it also no longer blurs hash patterns as strongly.
I then wondered if I could simply change the scaling of the first term as well, to make them line up again. In essence, this is what your LanczosRadius does. The natural conclusion would be to scale it so that it reaches 0 at 3.0 as well, that is: jinc(x * jinc_zeros[taps-1] / taps) * jinc(x * jinc_zeros[0] / taps). However, this particular scaling works less well than intended - it also doesn't blur hash patterns, for example. I have found an alternative scaling value, that is a value of c such that jinc(x / c) / jinc(x * jinc_zeros[0] / taps) produces a similar result (blurred hash pattern, visual quality) to the true Lanczos function, but I can't figure out where it comes from: I'm using approximately 1.05, which I've arrived at by trial and error (picking values until the hash pattern disappears almost completely). I was actually scaling *both* jinc functions, so it was really jinc(x / c) / jinc(x * jinc_zeros[0] / taps / c) I was testing
Note that for other taps, this value changes. For 4 taps, I arrived at something like 1.20. I don't know where either of these two figures come from.
Can somebody help me figure this out? Is there perhaps another way to compute EWA Lanczos3 more efficiently than by consulting a 8x8 matrix of pixels? Is it possible to use something like a bilinear lookup to reduce this to 4x4? (I know the technique works when the weight matrix is strictly positive, but I'm not sure if it does for weight functions that reach negative values)