WriteableBitmap Копирование утечки памяти - PullRequest
0 голосов
/ 20 октября 2018

Я работаю над WriteableBitmaps, и у меня есть метод, который:

  1. Копирует WriteableBitmap из параметра в переменную, которая находится за пределами метода
  2. Работает на первом растровом изображении
  3. Добавляет скопированное растровое изображение в 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,Не работает без копирования растрового изображения

1 Ответ

0 голосов
/ 20 октября 2018

Растровые изображения, как известно, большие по размеру.Вы продолжаете добавлять старые состояния в стек отмены, не позволяя GC их очистить.Это именно то, что вы не должны делать с объемными данными, такими как изображения.

Я думаю, вы просто случайно сделали пример того, чего не следует делать:)

Решение:

Хватит хранить много неиспользуемых изображений!Установите разумные ограничения на размер стека отмены.Или решите эту проблему таким образом, чтобы не требовалось использовать оперативную память MiB.

Особо следует помнить, что изображения в памяти полностью не сжаты.Сжатие применяется только к изображениям на дисках или передаче по сети.Чтобы отобразить или обработать изображение, каждый шаг должен быть отменен.И они занимают пространство, равное высоте X по глубине цвета X, как и несжатое растровое изображение.

...