C# WPF-调整大小时位图图像上的瑕疵
我正在用C#(WPF)实现错误扩散算法(颜色减少),我正在使用writeableBitmap。C# WPF-调整大小时位图图像上的瑕疵,c#,wpf,windows,canvas,bitmap,C#,Wpf,Windows,Canvas,Bitmap,我正在用C#(WPF)实现错误扩散算法(颜色减少),我正在使用writeableBitmap。 以下函数使用计算图像打开新窗口: private void OpenNewWindow() { // TODO: Bug with image resizes const int margin = 50; currAlgWindow = new Window { Owner = this }; var w = algorithmBitmap.Width; var
以下函数使用计算图像打开新窗口:
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();
}
我遇到了我遇到过的最奇怪的问题,因为在调整新窗口的大小时,指定的图像会发生变化,即使在任何地方都没有onSizeChanged
事件示例:
1.紧跟在currAlgWindow.Show()之后的图像
2.调整窗口大小后的图像
3.进一步调整大小后的图像
移动窗口也会稍微改变图像(刷新可见)
所有问题都不会出现在原始图像上,只会出现在计算出的图像上
我还提供了算法代码:
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);
}
}
公共类错误扩散:算法
{
公共错误扩散位图(可写位图图像位图)
{
this.Bitmap=imageBitmap;
}
公共覆盖无效应用(整数Kr、整数Kg、整数Kb)
{
int-itR=255/(Kr-1);
int itG=255/(千克-1);
国际投标人须知=255/(Kb-1);
var bmpRect=new System.Windows.Int32Rect(0,0,宽度,高度);
bitmap.WritePixels(bmpRect,originalCopy,bitmap.BackBufferStride,0);//复制缓存的原始图像
Lock();
不安全的
{
byte*bmpArray=(byte*)bitmap.BackBuffer.ToPointer();
对于(int i=0;i>4)).ToByte();
}
if(行!=位置最后一个)
{
如果(列!=位置第一)
{
ind=bitmap.BackBufferStride-字节/像素+colorNum;
//像素[x-1][y+1]:=像素[x-1][y+1]+数量误差*3/16
currPos[ind]=(currPos[ind]+((错误*3)>>4)).ToByte();
}
ind=位图.BackBufferStride+colorNum;
//像素[x][y+1]:=像素[x][y+1]+数量误差*5/16
currPos[ind]=(currPos[ind]+((错误*5)>>4)).ToByte();
if(col!=最后一个位置)
{
ind=bitmap.BackBufferStride+字节/像素+colorNum;
//像素[x+1][y+1]:=像素[x+1][y+1]+数量误差*1/16
currPos[ind]=(currPos[ind]+((错误*1)>>4)).ToByte();
}
}
}
私有枚举位置{First,Last,Other};
私人位置GetPos(内部r、内部dim)
{
返回r==dim-1位置。最后一个:r==0位置。第一个:位置。其他;
}
}
此外,您可以在这里看到的图片上的人工制品与在我的计算机上看到的图片上的外观不同,就像将其保存为不同格式后以其他方式显示一样我还在另一台计算机上测试了这个应用程序,但问题并没有出现。
我完全搞不清楚问题的真正原因是什么——屏幕、系统、软件、代码?我已经在其他计算机上测试过了,工件也不见了。
这是我的笔记本电脑矩阵的问题-它已被更换,与我的笔记本电脑不完全兼容。
var img=new Image{Source=algorithmBitmap,Strech=Stretch.None}代码>禁用拉伸它可能会篡改您的图像。因为Image
的默认值为Uniform。@请注意,画布不会调整其子元素的大小,即使它自身的大小不会像这里一样固定。图像元素从不拉伸。可写位图的像素格式是什么?“指定的图像更改”-请更具体。你是说作业本身发生了变化吗?还是仅仅是图像?不管是哪种方式,它具体以什么方式发生了变化?根据布局配置,在调整容器的大小时,图像以不同的大小绘制并不罕见。你需要提供更多的细节,包括一个可靠地再现问题的好方法。改变我在图片上提供的方式-它被重新绘制。我特别做的是调整窗口的大小,图像被分配到该窗口。
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;
}
}