WPF - 调整大小时位图图像上的工件

WPF - artifacts on bitmap image on resize

我正在 C# (WPF) 中实现错误扩散算法(颜色还原),并且我正在使用 writeableBitmap。
以下函数使用计算图像打开新的 window:

private void OpenNewWindow()
{
    // TODO: Bug with image resizes
    const int margin = 50;
    currAlgWindow = new Window { Owner = this };
    var w = algorithmBitmap.Width;
    var h = algorithmBitmap.Height;
    var canvas = new Canvas { Width = w + margin * 2, Height = h + margin * 2 };


    var img = new Image { Source = algorithmBitmap };
    Canvas.SetLeft(img, (canvas.Width - w) / 2);
    Canvas.SetTop(img, (canvas.Height - h) / 2);
    canvas.Children.Add(img);

    currAlgWindow.SizeToContent = SizeToContent.WidthAndHeight;
    currAlgWindow.Content = canvas;
    currAlgWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
    currAlgWindow.Show();
}

我遇到了我遇到过的最奇怪的问题,因为在调整新 Window 的大小时,分配的图像 发生了变化 ,即使没有 onSizeChanged随处附加的事件。
示例:
1. currAlgWindow.Show() 之后的图片
2. 调整大小后的图像window。

3. 进一步调整大小后的图像

移动 window 也会稍微改变图像(刷新可见)。
所有问题都不会出现在原始图像上,只会出现在计算出的图像上。

我也提供算法代码:

public abstract class Algorithm
{
    protected WriteableBitmap bitmap;
    protected byte[] originalCopy;
    protected int bytesPerPixel;
    protected int width;
    protected int height;

    protected Algorithm()
    {
    }

    public virtual WriteableBitmap Bitmap
    {
        get => bitmap; 
        set 
        {
            bitmap = value;
            bytesPerPixel = (bitmap.Format.BitsPerPixel + 7) / 8;
            width = bitmap.PixelWidth;
            height = bitmap.PixelHeight;

            originalCopy = new byte[height * bitmap.BackBufferStride];
            bitmap.CopyPixels(originalCopy, bitmap.BackBufferStride, 0);
        }
    }

    public abstract void Apply(int Kr, int Kg, int Kb);

    protected static int RoundToNeareastMultiple(int num, int multiple)
    {
        return (int)(((num + multiple / 2) / multiple) * multiple);
    }
}
public class ErrorDiffusionDithering : Algorithm
{
    public ErrorDiffusionDithering(WriteableBitmap imageBitmap)
    {
        this.Bitmap = imageBitmap;
    }

    public override void Apply(int Kr, int Kg, int Kb)
    {
        int itR = 255 / (Kr - 1);
        int itG = 255 / (Kg - 1);
        int itB = 255 / (Kb - 1);
        var bmpRect = new System.Windows.Int32Rect(0, 0, width, height);
        bitmap.WritePixels(bmpRect, originalCopy, bitmap.BackBufferStride, 0); // Copy cached original image

        bitmap.Lock();

        unsafe
        {
            byte* bmpArray = (byte*)bitmap.BackBuffer.ToPointer();
            for (int i = 0; i < height; ++i)
            {
                byte* currPos = bmpArray + i * bitmap.BackBufferStride;
                Position row = GetPos(i, height);
                for (int j = 0; j < width; ++j)
                {
                    Position col = GetPos(j, width);

                    byte newVal = RoundToNeareastMultiple(currPos[0], itB).ToByte();
                    PropagateError(currPos[0] - newVal, 0, currPos, row, col);
                    currPos[0] = newVal;

                    newVal = RoundToNeareastMultiple(currPos[1], itG).ToByte();
                    PropagateError(currPos[1] - newVal, 1, currPos, row, col);
                    currPos[1] = newVal;

                    newVal = RoundToNeareastMultiple(currPos[2], itR).ToByte();
                    PropagateError(currPos[2] - newVal, 2, currPos, row, col);
                    currPos[2] = newVal;

                    currPos += bytesPerPixel;
                }
            }
        }
        bitmap.AddDirtyRect(bmpRect);

        bitmap.Unlock();
    }


    private unsafe void PropagateError(int error, int colorNum, byte* currPos, Position row, Position col)
    {
        // x - from left to right
        // y - from top to bottom

        int ind;
        if (col != Position.Last)
        {
            ind = bytesPerPixel + colorNum;
            // pixel[x + 1][y] := pixel[x + 1][y] + quant_error * 7 / 16
            currPos[ind] = (currPos[ind] + ((error * 7) >> 4)).ToByte();
        }

        if (row != Position.Last)
        {
            if (col != Position.First)
            {
                ind = bitmap.BackBufferStride - bytesPerPixel + colorNum;
                // pixel[x - 1][y + 1] := pixel[x - 1][y + 1] + quant_error * 3 / 16
                currPos[ind] = (currPos[ind] + ((error * 3) >> 4)).ToByte();
            }

            ind = bitmap.BackBufferStride + colorNum;
            // pixel[x][y + 1] := pixel[x][y + 1] + quant_error * 5 / 16
            currPos[ind] = (currPos[ind] + ((error * 5) >> 4)).ToByte();

            if (col != Position.Last)
            {
                ind = bitmap.BackBufferStride + bytesPerPixel + colorNum;
                //pixel[x + 1][y + 1] := pixel[x + 1][y + 1] + quant_error * 1 / 16
                currPos[ind] = (currPos[ind] + ((error * 1) >> 4)).ToByte();
            }
        }
    }

    private enum Position { First, Last, Other };

    private Position GetPos(int r, int dim)
    {
        return r == dim - 1 ? Position.Last : r == 0 ? Position.First : Position.Other;
    }
}

此外,您在此处看到的图片与我的计算机上的图片看起来不一样 - 就像将其保存为不同格式后,它以其他方式显示。
我还在另一台计算机上测试了应用程序,但没有出现问题。

我完全不知道问题的真正原因是什么 - 屏幕、系统、软件、代码?

我已经在其他计算机上测试过它并且工件消失了。
这是我的笔记本电脑矩阵的问题 - 它已被更换并且与我的笔记本电脑不完全兼容。