При рисовании изображений PixelFormat32bppPARGB с помощью GDI+ вместо предварительно умноженной используется обычная формула
Вот некоторый минимальный код, чтобы показать проблему:
static const int MAX_WIDTH = 320;
static const int MAX_HEIGHT = 320;
Gdiplus::Bitmap foregroundImg(MAX_WIDTH,MAX_HEIGHT,PixelFormat32bppPARGB);
{
Gdiplus::Graphics g(&foregroundImg);
g.Clear(Gdiplus::Color(10,255,255,255));
}
Gdiplus::Bitmap softwareBitmap(MAX_WIDTH,MAX_HEIGHT,PixelFormat32bppPARGB);
Gdiplus::Graphics g(&softwareBitmap);
g.SetCompositingMode(Gdiplus::CompositingModeSourceOver);
g.SetCompositingQuality(Gdiplus::CompositingQualityDefault);
g.Clear(Gdiplus::Color(255,0,0,0));
g.DrawImage(foregroundImg,0,0);
CLSID encoder;
GetEncoderClsid(L"image/png",&encoder);
softwareBitmap.Save(L"d:\\image.png",&encoder);
В результате я получаю изображение, заполненное значениями RGB, равными 10
, Похоже, GDI+ использует традиционный алгоритм:
255 * (10/255) + 0 * (1-10 / 255) == 10.
Но я ожидаю, что будет использоваться предварительно умноженный алгоритм (потому что на переднем плане изображение предварительно умножено PixelFormat32bppPARGB
формат):
255 + 0 * (1-10 / 255) == 255
Итак, мой вопрос, почему GDI+ использует обычную формулу, когда изображение находится в предварительно умноженном альфа-формате? И есть ли обходной путь, чтобы заставить GDI+ использовать предварительно умноженный альфа-алгоритм?
1 ответ
Формат изображения переднего плана не имеет значения (учитывая, что оно имеет альфа-канал), потому что вы устанавливаете его в Gdiplus::Color. Цветовые значения определены как неумноженные, поэтому gdiplus умножает компоненты на альфа-значение, когда очищает изображение переднего плана. Альтернативой было бы, чтобы значения Color имели различное значение в зависимости от формата цели рендеринга, и в этом заключается безумие.
Возможно, вы сможете сделать то, что намереваетесь, установив биты исходного изображения напрямую, или вы не сможете этого сделать. Компоненты со значениями, превышающими 100%, на самом деле недопустимы в модели рендеринга gdiplus, поэтому я не удивлюсь, если они будут ограничены во время рендеринга. Если вы действительно хотите этот уровень контроля над рендерингом, вам придется заблокировать биты растрового изображения и сделать это самостоятельно.