2016-11-24 19 views
3

Я рисую растровые изображения в Direct2D. Растровые изображения используют прозрачность (альфа-канал).Direct2D - Как сделать гамма-правильную прозрачность (альфа) с растровыми изображениями

Смешивание выглядит неправильно.

В качестве теста я загрузил чистое черно-белое изображение PNG с прозрачностью 50% и нарисовал его на белом фоне. Результат - пиксели с красным, зеленым и синим значением 127 (0x7F7F7F). Это предполагает, что смесь Direct2D игнорирует гамма и обрабатывает значения цвета, как если бы они были линейными.

(Растровые изображения используют обычное цветовое пространство sRGB и имеют 32 бита на пиксель, по 8 бит для красных, зеленых, синих и альфа). Они загружаются в формате GUID_WICPixelFormat32bppPBGRA.

В sRGB смесь между черным и белым составляет 186 (0xBABABA). Это идеальный результат, который я хочу.

Может ли Direct2D отображать прозрачность с учетом гаммы? Как мне это сделать? Любая помощь оценивается.

Direct2D vs Gamma-correct blend

+0

Я думаю, что у вас есть это в обратном направлении. В sRGB 50% будут выглядеть наполовину между черным и белым (по яркости, по-разному). Это выглядит слишком ярким или слишком темным? Это может быть связано с тем, как он отображается. –

+0

Мое понимание - цветовое пространство sRGB определяет нелинейное преобразование между интенсивностью пикселей и фактическим сохраненным числом. т.е. гамма-кривой. Например, 8-битное значение цвета колеблется от 0 до 255, но из-за гамма-кривой значение 127 (на полпути) отображается при яркости около 20%. Таким образом, гамма-правильная 50% -ная смесь черного и белого должна иметь значение в пикселях 186 (полная шкала 73%). Так что в Direct2d моя смесь выглядит слишком темной. –

+0

@astraycat, если вы просматриваете чередующиеся черно-белые пиксели и сравниваете их с твердым блоком, блок BABABA должен быть одинаковой яркости на правильно откалиброванном мониторе. Даже на некалиброванном мониторе BABABA должен быть ближе, чем 7F7F7F. –

ответ

1

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

  1. обращенный к линейным
  2. смесь
  3. преобразовать обратно в SRGB.

Обратите внимание, что с черными или белыми пикселями шаги (1) и (3) не являются op-операциями и могут быть опущены.

См. Раздел спецификации PNG alpha channel processing. В частности, отметить следующее:

Уравнение для вычисления скомбинированы значение выборки является

output = alpha * foreground + (1-alpha) * background

, где значение альфа и выборочных значений входных и выходных являются выражены в виде долей в диапазоне от 0 до 1. Это вычисление должно быть , выполненное с образцами интенсивности (без образцов с гамма-кодированием)

Этот раздел содержит образец C-кода для обработки альфа-канала

В то время, когда этот вопрос задавался, HWND Render target (рисунок на экран) не поддерживал линейные пиксельные форматы; однако, Direct-2D цели HwndRender теперь были заменены интерфейсом ID2D1DeviceContext. Они создаются с помощью IDXGIFactory2::CreateSwapChainForHwnd() и поддерживают больше форматов пикселей, таких как DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, которые автоматически выполняют правильные преобразования цветового пространства при смешивании (информация предоставлена ​​@Jeff McClintock).

+0

Cheers, что имеет смысл (исполняющая смесь в линейном цветовом пространстве), но как реализовать это в Direct2D? (возможно, цель рендеринга и растровое изображение должны быть установлены в определенный формат пикселей?). –

+1

Я сделал некоторые исследования. AFAIK Direct2D HWND Цели рендеринга (рисунок на экран) не поддерживают линейные пиксельные форматы, и если вы преобразуете растровое изображение в линейный формат, он больше не поддерживает аппаратное ускорение (основное преимущество Direct2D). DIrect3D (на котором основан Direct2D) поддерживает операции с растровыми изображениями, посредством которых пиксели преобразуются в линейное цветовое пространство и обратно во время операции смешивания. Pity Direct2D этого не поддерживает. –

+0

UPDATE: Цели Direct-2D HwndRender заменяются интерфейсом \t \t ID2D1DeviceContext. Они создаются с помощью IDXGIFactory2 :: CreateSwapChainForHwnd() и поддерживают больше форматов пикселей, таких как DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, которые автоматически выполняют правильные преобразования цветового пространства при смешивании. –

0

Direct-2D 1.0 HwndRenderTarget выполняет смешение вычислений непосредственно по значениям пикселей. Это приводит к ошибкам, составляющим стандартные изображения sRGB с использованием альфа-канала. Ошибка заключается в том, что Direct 2D обрабатывает гамма-сжатые значения интенсивности, как если бы они были линейными значениями интенсивности.

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

Существует обходное решение, которое заключается в «предварительном преобразовании» альфа-значений растрового изображения для компенсации ошибок, возникающих при вычислении смешивания.

пример: Изображение на левом рисунке - правильное составление композиции путем смешивания в линейном цветовом пространстве, центральное изображение - прямое 2D (тень слишком темная и «контрастная»), изображение справа - это Direct2D после предварительного кодирования альфа-канала.

Direct 2D Renders alpha blends to dark and 'contrasty'

см: https://bel.fi/alankila/lcd/alpcor.html

ОБНОВЛЕНИЕ !: Новые версии Direct-2D (1.1) Поддержка SRGB резервных буферов, которые выполняют правильно смешивание. Используйте IDXGIFactory2 :: CreateSwapChainForHwnd(), чтобы использовать улучшенные параметры глубины цвета.