Проблема отображения растрового изображения в WPF - PullRequest
0 голосов
/ 21 декабря 2018

Мне нужно отобразить 8k RGB-изображение из байтового массива RAW, которое я получаю от фрейм-граббера в управлении wpf на высокой скорости fps.Я могу успешно преобразовать и байтовый массив в BitmapSource и отобразить его в окнах изображений в WPF.Но так как граббер генерирует изображения со скоростью около 5 FPS после отображения, я освобождаю удержание объекта, но GC требуется время, чтобы собрать память, в которой увеличивается память моего приложения и замораживает приложение и мою систему.Как правильно утилизировать BitmapSource (CachedBitmap), созданный с использованием метода ниже.Помогите, пожалуйста, избавиться от объекта после использования.

Я пытался использовать GC.Collect () во время изменения изображения, но он не работает.

Вот мой код преобразования байтового массива в растровое изображение,

    int Width = 7680;
    int Height = 4320;
    PixelFormat PixelFormat = PixelFormats.Bgr24;
    int BytesPerPixel = 3;

    public BitmapSource ByteToImage(byte[] imageData)
    {            
        var stride = BytesPerPixel * Width;
        BitmapSource bitmapSource = BitmapSource.Create(Width, Height, 96d, 96d, PixelFormat, null, imageData, stride);
        bitmapSource.Freeze();
        return bitmapSource;
    }

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

Возможно, вам следует попробовать записываемое растровое изображение:

        WriteableBitmap writeableBitmap = new WriteableBitmap(
            (int)width,
            (int)height,
            96,
            96,
            PixelFormats.Bgr32,
            null);

        int stride = width * writeableBitmap.Format.BitsPerPixel / 8

Теперь, когда вы получаете кадр, вы можете записать его в записываемое растровое изображение:

        writeableBitmap.Lock();
        writeableBitmap.WritePixels(new Int32Rect(0, 0, width, height), imageData, stride, 0);
        writeableBitmap.Unlock();

Таким образом, вам не нужносоздать новое изображение.Вы просто перезаписываете растровые данные.Но будьте осторожны, чтобы всегда получать данные из источника в один и тот же буферный массив.

0 голосов
/ 21 декабря 2018

Это звучит как возможный кандидат для рендеринга композиционной цели, попробуйте добавить это в свой конструктор MainWindow:

CompositionTarget.Rendering += CompositionTarget_Rendering;

А затем реализовать саму функцию:

void CompositionTarget_Rendering(object sender, EventArgs e)
{
    // dispose previous image, create and assign the new one
}

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

ОБНОВЛЕНИЕ: BitmapSource просто использует обычную память, поэтому правильное поведение состоит в том, чтобы GC мог ее очистить,Если этого не происходит в вашем случае, то это означает, что что-то удерживает эту память по какой-то причине, возможно, на дисплее.Вот пример, в котором используется CompositionTarget.Rendering. Я собираю дамп памяти GC как до, так и после сбора, чтобы вы могли видеть, что он достаточно четко собирается:

    public MainWindow()
    {
        InitializeComponent();
        CompositionTarget.Rendering += CompositionTarget_Rendering;
    }       

    private void CompositionTarget_Rendering(object sender, EventArgs e)
    {
        // remove reference to old image
        this.theImage.Source = null;

        // invoke GC
        Debug.WriteLine(GC.GetTotalMemory(false));
        GC.Collect();
        Debug.WriteLine(GC.GetTotalMemory(false));

        // create and assign new image
        const int width = 1000;
        const int height = 1000;
        var pixels = new uint[width * height];
        uint color = (uint)((new Random((int)DateTime.Now.Ticks)).Next(0x1000000) | 0xff000000);
        for (int i = 0; i < width * height; i++)
            pixels[i] = color;
        this.theImage.Source = BitmapSource.Create(width, height, 96, 96, PixelFormats.Bgra32, null, pixels, width * 4);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...