Возможно ли изменить WPF BitmapSource в памяти «небезопасно» из другого потока - PullRequest
2 голосов
/ 13 октября 2010

Я хотел бы выполнить некоторую обработку изображений в приложении WPF.Тем не менее, я хотел бы изменить пиксели BitmapSource в памяти во время выполнения.

В настоящее время мне удается сделать это, используя «небезопасный» код для устаревшего System.Drawing.Bitmap, и это работает(заблокировать рабочую область, поиграть с пикселями) работа сделана.Подход описан в этом посте: http://blogs.msdn.com/b/ericgu/archive/2007/06/20/lost-column-2-unsafe-image-processing.aspx

Чтобы заставить это работать в WPF, я затем создаю BitmapSource WPF, используя этот подход:

    BitmapSource destination;
    IntPtr hBitmap = bitmap.GetHbitmap();
    BitmapSizeOptions sizeOptions = BitmapSizeOptions.FromEmptyOptions();
    destination = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, sizeOptions);
    destination.Freeze();
    return destination;

Однако это создает многокопий в памяти, и я действительно хочу попасть туда и возиться с базовыми битами внутри BitmapSource, как EricGu показал в примере Bitmap.Это возможно?

Я понимаю, что PixelShaders, вероятно, может сделать это, но это академическое упражнение, включающее несколько потоков (которое поддерживается при редактировании растрового изображения в небезопасном режиме).

Заранее спасибо

1 Ответ

3 голосов
/ 13 октября 2010

Я расскажу вам столько, сколько знаю.

Сначала вы, кажется, уже знаете о заморозке растровых изображений, прежде чем возвращать их в основной поток.Это хорошее начало.

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

Конечно, вы также можете создать BitmapSource непосредственно из массива байтов (и потерять служебную информацию из битовой карты GDI). msdn docs

Рассматривали ли вы WriteableBitmap ?Это был ответ команды WPF на общую жалобу на все копии.

Редактировать : MSDN явно говорит (в документации WritableBitmap.BackBuffer), что его можно использовать из фонового потока:

Вы можете передать указатель BackBuffer навнешние компоненты и другие потоки для обработки, но если вы делаете, вы должны предоставить собственную координацию потоков.В частности, вы должны убедиться, что поток пользовательского интерфейса указывает измененные области, вызывая метод AddDirtyRect, и чтобы поток пользовательского интерфейса разблокировал буфер, вызывая метод Unlock.

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

...