Как вы можете рисовать изображения 32bppargb с помощью функции Win32 AlphaBlend?

Я возился с этим большую часть ночи, так что, может быть, кто-нибудь из вас поможет мне.

Я обнаружил, что GDI+ DrawImage в C# слишком медленный для того, что я пытаюсь отобразить, и, судя по форумам, это то же самое и для других людей.

Я решил попробовать использовать AlphaBlend или BitBlt из API Win32 для повышения производительности. В любом случае, мои изображения отображаются нормально, за исключением одной маленькой детали: независимо от того, какой формат изображения я использую, я не могу заставить белый фон исчезнуть из моей (прозрачной) графики.

До сих пор я пробовал форматы BMP и PNG и убедился, что они загружаются как изображения 32bppargb в С#.

Вот звонок, который я делаю:

// Draw the tile to the screen.
Win32GraphicsInterop.AlphaBlend(graphicsCanvas, destination.X, destination.Y, this.TileSize, this.TileSize,
                                this.imageGraphicsPointer, tile.UpperLeftCorner.X, tile.UpperLeftCorner.Y,
                                this.TileSize, this.TileSize,
                                new Win32GraphicsInterop.BLENDFUNCTION(Win32GraphicsInterop.AC_SRC_OVER, 0,
                                                                                   Convert.ToByte(opacity * 255),
                                                                                   Win32GraphicsInterop.AC_SRC_ALPHA));

Для справки, AC_SRC_OVER — это 0x00, а AC_SRC_ALPHA — это 0x01, что согласуется с тем, что MSDN говорит, что они должны быть.

Кто-нибудь из вас, ребята, знает хорошее решение этой проблемы или знает лучший (но все же быстрый) способ сделать это?


person Ed Altorfer    schedule 15.01.2010    source источник


Ответы (3)


Скорость Graphics.DrawImage() критически зависит от формата пикселей. Format32bppPArgb в 10 раз быстрее, чем любой другой на любой последней машине, которую я пробовал.

Также убедитесь, что размер изображения не изменяется, обязательно используйте перегрузку DrawImage(), которая устанавливает целевой размер равным размеру растрового изображения. Очень важно, если настройка DPI видеоадаптера не соответствует разрешению растрового изображения.

person Hans Passant    schedule 15.01.2010
comment
Я не уверен, как получить мое изображение в Format32bppPArgb... оно загружается как Format32bppArgb. Какие-нибудь мысли? - person Ed Altorfer; 15.01.2010
comment
Используйте конструктор Bitmap, который позволяет указать PixelFormat. Нарисуйте исходное растровое изображение с помощью Graphics.FromImage(). - person Hans Passant; 15.01.2010
comment
Как преобразовать обратно из Graphics в Image? - person Ed Altorfer; 15.01.2010

Вы пробовали непрозрачность всего 255, а не расчетную?

В этом сообщении блога описывается, что вы пытаетесь сделать: images.aspx" rel="nofollow noreferrer">http://blogs.msdn.com/andreww/archive/2007/10/10/preserving-the-alpha-channel-when-converting-images.aspx

Критически важно то, что он выполняет преобразование изображения, чтобы сделать альфа-канал совместимым.

person Community    schedule 15.01.2010

Ok. С чистой точки зрения Win32:

Для того, чтобы AlphaBlend действительно выполнял альфа-смешивание... ему необходимо, чтобы контекст исходного устройства содержал выбранный HBITMAP, представляющий изображение с растровым изображением 32bpp с предварительно умноженным альфа-каналом. Чтобы получить растровое изображение устройства с 32 битами на пиксель, вы можете вызвать одну из многих функций, которые создадут растровое изображение, совместимое с экраном, и надеяться, что пользователь выбрал 32 бита на пиксель в качестве разрядности рабочего стола. ИЛИ убедитесь, что исходное растровое изображение является DIBSection. Ну, библиотека или фреймворк, который создает его из загруженного образа для вас.

Итак, С# загружает ваши изображения с 32-битным argb, НО, как вы конвертируете это С#-представление растрового изображения в HBITMAP? Вам необходимо убедиться, что создается раздел DIB, а не DDB (или растровое изображение, зависящее от устройства), и что раздел DIB имеет размер 32 бита на пиксель.

person Chris Becke    schedule 15.01.2010