Skip to content

Bitmap::Sample2D方法有一个像素的偏差 #4

Description

@yunhao-qian

复现代码

放大一个checker texture并输出图片:

const int N = 64;
Bitmap texture(N, N);
for (int y = 0; y < N; ++y)
    for (int x = 0; x < N; ++x) {
        uint32_t color = (x + y) & 1 ? 0xff000000 : 0xffffffff;
        texture.SetPixel(x, y, color);
    }

const int W = 3072, H = 2048;
Bitmap output(W, H);
for (int y = 0; y < H; ++y)
    for (int x = 0; x < W; ++x) {
        float u = (x + 0.5f) / W, v = (y + 0.5f) / H;
        output.SetPixel(x, y, texture.Sample2D(u, v));
    }
output.SaveFile("output.bmp");

发现checker texture比预期的位置向左、上平移了一个网格,并在图片的右、下边沿导致拖影。
output

可能的原因和解决办法

  • 现有的代码中,Bitmap::SampleBilinear方法接收的参数值为(x = u * _w + 0.5f, y = v * _h + 0.5f)。
  • 所以,这两个参数的取值范围是0.5 <= x <= _w + 0.5, 0.5 <= y <= _h + 0.5。
  • 获得四个像素坐标的位运算等价于:x1 = floor(x), y1 = floor(y), x2 = ceil(x), y2 = ceil(y)。
  • 可以看出,取样时图像的左、上边永远不会被裁切,而图像右、下边可能被裁切。

如果减去一个像素的偏移,把Bitmap::SampleBilinear开头部分的代码修改为:

int32_t x1 = Between(0, _w - 1, (fx >> 16) - 1);
int32_t y1 = Between(0, _h - 1, (fy >> 16) - 1);
int32_t x2 = Between(0, _w - 1, fx >> 16);
int32_t y2 = Between(0, _h - 1, fy >> 16);

发现上述问题不再出现。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions