Skip to content

Commit

Permalink
Revert "lanczos3: Actually sample 7x7 instead of 6x6 (#27)"
Browse files Browse the repository at this point in the history
This reverts commit 22e1bb1.

The kernel size of the `lanczos3` filter is 6x6, and sampling it at
`x=3.5` or `y=3.5` results in a weight of `0`, thus making these pixels
completely irrelevant.  This became more clear in #28 that simplified
the offset passed to `lanczos3_filter()` to always be `0.5`, to read the
weight at the middle of each source pixel.

Note that for an even reduction in image size the center coordinate
of every target pixel (what `uv` denotes) is exactly on the boundary
between two source pixels, meaning the pixel at kernel position
`x=0,y=0` (barring float imprecisions) is at the right/bottom of the
center of the target pixel, hence correctly reading 3 pixels to the
left, top, right and bottom (with indices in the range [-3, 2]).

For uneven reductions (i.e. 3x) this doesn't hold, and that was likely
what the code removed in #28 was incorrectly trying to compensate for?
  • Loading branch information
MarijnS95 committed Oct 23, 2023
1 parent dab89c9 commit 9b795a5
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions src/ispc/kernels/lanczos3.ispc
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,15 @@ static inline uint8<4> resample_internal(uniform Image src_image, float<2> uv, u
// Truncate floating point coordinate to integer:
const int<2> src_coord = uv * src_image.size;

for (uniform int x = -3; x <= 3; x++) {
for (uniform int y = -3; y <= 3; y++) {
const float lanczos3_offset = 0.5;
// Sample the lanczos3 filter from -2.5 to 2.5.
// Pixel 0, 0 in the source will be at the bottom-right of the center of the target pixel,
// hence reading source pixels in the range [-3, 2] will correctly read pixels to the left, top,
// right and bottom of the target pixel.
for (uniform int x = -3; x < 3; x++) {
for (uniform int y = -3; y < 3; y++) {
float wx = lanczos3_filter((uniform float)x + 0.5);
float wy = lanczos3_filter((uniform float)y + 0.5);

float wx = lanczos3_filter((uniform float)x + lanczos3_offset);
float wy = lanczos3_filter((uniform float)y + lanczos3_offset);
float w = wx * wy;
int<2> texel_offset = {x, y};
int<2> src_kernel_coord = src_coord + texel_offset;
Expand Down

0 comments on commit 9b795a5

Please sign in to comment.