Визуализация GDI в direct2D ID2D1BitmapRenderTarget всегда прозрачна - PullRequest
4 голосов
/ 05 января 2011

Я хочу портировать программное обеспечение для рендеринга фильмов с DirectDraw на Direct2D.Из-за проблем с совместимостью рендеринг GDI должен выполняться поверх изображения.Чтобы оптимизировать производительность, я хочу реализовать некоторый механизм резервного буфера, но, похоже, существует проблема с информацией об альфа-канале: весь рисунок GDI выглядит каким-то прозрачным .

Я создаю ID2D1HwndRenderTarget для моего дескриптора окна и ID2D1Bitmap для копирования изображений в.Пиксельный формат растрового изображения: DXGI_FORMAT_B8G8R8A8_UNORM , альфа-режим: D2D1_ALPHA_MODE_IGNORE .HwdRenderTarget совместим с GDI, поэтому моя функция рендеринга выглядит примерно так:

HwdRenderTarget.BeginDraw;
HwdRenderTarget.DrawBitMap(myBitMap);
HwdRenderTarget.GetDC(dc);

... do GDI drawing here ...

HwdRenderTarget.ReleaseDC();
HwdRenderTarget.EndDraw;

Эта версия прекрасно работает: объекты GDI рисуют сплошными цветами, DrawTextEx-Text имеет прозрачный фон.

Чтобы оптимизировать производительность, я хочу сделать чертеж GDI в «резервном буфере», так что это нужно делать только тогда, когда что-то меняется.В противном случае я просто могу отобразить кэшированное растровое изображение.Растровое изображение пустое и прозрачное, поэтому должны отображаться только нарисованные объекты.

Поэтому я создаю CompatibleRenderTarget ID2D1BitmapRenderTarget , альфа-режим равен D2D1_ALPHA_MODE_PREMULTIPLIED :

 HwdRenderTarget.CreateCompatibleRenderTarget(nil, nil, nil, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE, CompatibleRenderTarget);

Теперь я выполняю рендеринг GDI в CompatibleRenderTarget:

CompatibleRenderTarget.BeginDraw;
if Supports(CompatibleRenderTarget, ID2D1GdiInteropRenderTarget, GdiInteropRenderTarget) then
begin
  GdiInteropRenderTarget.GetDC(D2D1_DC_INITIALIZE_MODE_CLEAR, dc);

  ... do GDI drawing here ...

  GdiInteropRenderTarget.ReleaseDC(fDstSize);
end;
GdiInteropRenderTarget := nil;
CompatibleRenderTarget.EndDraw;
CompatibleRenderTarget.GetBitmap(BackBuffer); // save the bitmap for drawing

, и теперь моя функция рендеринга выглядит следующим образом:

HwdRenderTarget.BeginDraw;
HwdRenderTarget.DrawBitMap(myBitMap);
HwdRenderTarget.DrawBitmap(BackBuffer);
HwdRenderTarget.EndDraw;

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

Так откуда берется альфа-информация?У кого-нибудь есть идея?Заранее спасибо!

Кстати, использование Direct2D-рисования на CompatibleRenderTarget также работает нормально.

Ответы [ 2 ]

2 голосов
/ 15 июня 2011

У меня была такая же проблема.Следующее сработало для меня (вам нужно создать цель рендеринга, используя D2D1_ALPHA_MODE_IGNORE, а не D2D1_ALPHA_MODE_PREMULTIPLIED).

ID2D1HwndRenderTarget* pRenderTarget; // render target created sometime earlier

D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat(
    DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);

ID2D1BitmapRenderTarget* pOffscreenRT = NULL;
pRenderTarget->CreateCompatibleRenderTarget(NULL, NULL, &pixelFormat,
    D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE, &pOffscreenRT);
1 голос
/ 22 февраля 2012

В рендеринге с помощью GDI есть маленький грязный секрет: он всегда заглушает альфа-канал. Все, что вы рисуете с этим, устанавливает нулевые значения альфа в этой области. Я подозреваю, что это потому, что он никогда не был разработан для работы с альфа-каналом или любым типом композитинга. Он был разработан для отображения непосредственно на экране и на принтерах, где нет альфа-каналов.

...