将位图绘制到另一个位图上会产生扭曲的图像

Drawing a Bitmap onto another produces a distorted image

我正在使用自定义 class 将一个图像写到另一个更大尺寸的图像上。这是 DotNetFiddle 中的完整 source code

我的自定义 GetPixel() 工作正常。但是下面的 SetPixel() 无法产生正确的输出。可能地址的计算出现了一些问题。但是,我无法检测到它。

    public void SetPixel(int x, int y, Color color)
    {
        // Get color components count
        int cCount = ColorDepth / 8;
        // Get start index of the specified pixel
        int i = ((y * Width) + x) * cCount;
        //int i = ((x * Width) + y) * cCount;
        if (ColorDepth == 32) // For 32 bpp set Red, Green, Blue and Alpha
        {
            _imageData[i] = color.B;
            _imageData[i + 1] = color.G;
            _imageData[i + 2] = color.R;
            _imageData[i + 3] = color.A;
        }

        if (ColorDepth == 24) // For 24 bpp set Red, Green and Blue
        {
            _imageData[i] = color.B;
            _imageData[i + 1] = color.G;
            _imageData[i + 2] = color.R;
        }
        if (ColorDepth == 8)
        {
            // For 8 bpp set color value (Red, Green and Blue values are the same)
            _imageData[i] = color.B;

            string str = string.Empty;
        }
    }

这是在生成扭曲的图像:

.

P.S. 这是输入图像:

.

.

    // Get start index of the specified pixel
    int i = ((y * Width) + x) * cCount;

这是不正确的,无论是在 GetPixel 还是在 SetPixel 中。您会出现偏差,因为您忽略了 Stride。这是图像单个扫描线中的字节数。它是4的倍数对齐内存中的像素数据,有助于处理器更快地读取数据。修复:

    int i = y * Stride + x * cCount;

您的代码中还隐藏着另一个错误,扫描线颠倒存储。换句话说,最后一个扫描线的数据首先被存储。但前提是 BitmapData.Height 不是负数。由于该错误同时出现在您的 GetPixel 和 SetPixel 方法中,因此它们相互抵消了。正确的代码是 (Height - y - 1) * Stride + x * cCount.

此代码并不比 Graphics.DrawImage() 快,您应该始终喜欢这种方法。