我正在研究WriteableBitmaps
,并且有一种方法可以实现:
WriteableBitmap
从参数复制到方法外部的变量UndoStack
此方法的重点是在位图上进行更改,然后在更改前将其添加到撤消堆栈位图。
如果经常调用此方法,则会导致OutOfMemoryException
。
变量
private WriteableBitmap _oldBitmap;
private Image _oldImage;
方法
public Layer ExecuteTool(Layer layer, Coordinates startingCoords, Color color,int toolSize, ToolType tool)
{
if (toolSize < 1) return null;
Layer cLayer = layer;
_oldBitmap = new WriteableBitmap(layer.LayerBitmap);
_oldImage = layer.LayerImage;
_oldImage.Source = _oldBitmap;
switch (tool)
{
case ToolType.Pen:
cLayer.LayerBitmap = DrawPixel(cLayer.LayerBitmap, startingCoords, toolSize,color);
break;
case ToolType.Bucket:
cLayer.LayerBitmap = FloodFill(cLayer.LayerBitmap, startingCoords, color);
break;
case ToolType.Line:
if (_toolIsExecuting == false)
{
LineAsync(cLayer, startingCoords, color, toolSize);
}
break;
case ToolType.Circle:
if(_toolIsExecuting == false)
{
CircleAsync(cLayer, startingCoords, color);
}
break;
case ToolType.Rectangle:
if(_toolIsExecuting == false)
{
RectangleAsync(cLayer, startingCoords, color);
}
break;
case ToolType.Earser:
cLayer.LayerBitmap = DrawPixel(cLayer.LayerBitmap, startingCoords, toolSize, Colors.Transparent);
break;
case ToolType.Lighten:
if(Mouse.LeftButton == MouseButtonState.Pressed)
{
cLayer.LayerBitmap = Lighten(cLayer.LayerBitmap, startingCoords);
}
else if(Mouse.RightButton == MouseButtonState.Pressed)
{
cLayer.LayerBitmap = Darken(cLayer.LayerBitmap, startingCoords);
}
break;
default:
break;
}
if (tool != ToolType.ColorPicker)
{
UndoManager.RecordChanges("ActiveLayer", new Layer(_oldBitmap, _oldImage), cLayer, string.Format("{0} Tool.", tool.ToString()));
}
return cLayer;
}
PS。没有复制位图就无法工作
答案 0 :(得分:-1)
众所周知,位图的大小很大。您一直将旧状态添加到撤消堆栈中,以防止GC清除它们。这正是您不应该对图像等批量数据执行的操作。
我认为您只是无意中举例说明了不该做什么:)
解决方案:
停止保留大量未使用的图像!对撤消堆栈的大小设置一些合理的限制。或以不需要MiB精打细算的方式解决此问题。
尤其要记住的一件事是,内存中的图像是完全未压缩的。压缩仅适用于磁盘上的图像或通过网络传输的图像。为了显示或处理图像,每个高级步骤都必须撤消。它们占用的空间等于未压缩的位图图像的高度X宽度X颜色深度。