Skip to content

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

@yunhao-qian

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);

发现上述问题不再出现。

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