Вопрос или проблема
Документация Microsoft по функции GDI TransparentBlt()
утверждает:
Функция TransparentBlt поддерживает все форматы исходных растровых изображений. Однако для растровых изображений с глубиной цвета 32 бита она просто копирует значение альфа-канала.
Это ошибка?
Код ниже противоречит этой документации, демонстрируя, что TransparentBlt()
обнуляет значение альфа-канала для непрозрачного пикселя и не копирует никакие каналы исходного прозрачного пикселя вообще (как и должно):
#include <windows.h>
void foo(void)
{
BITMAPINFO bmi = { {sizeof(BITMAPINFOHEADER), 2, 1,1,32,BI_RGB,0,0,0,0,0} };
PDWORD PixelsSrc;
HBITMAP hBmpSrc = CreateDIBSection(0, &bmi, DIB_RGB_COLORS, reinterpret_cast<PVOID*>(&PixelsSrc), NULL, 0);
PixelsSrc[0] = 0xEE555555; PixelsSrc[1] = 0xFFAAAAAA;
PDWORD PixelsDst;
HBITMAP hBmpDst = CreateDIBSection(0, &bmi, DIB_RGB_COLORS, reinterpret_cast<PVOID*>(&PixelsDst), NULL, 0);
PixelsDst[0] = 0xCC222222; PixelsDst[1] = 0xDD333333;
HDC hDCsrc = CreateCompatibleDC(NULL);
HDC hDCdst = CreateCompatibleDC(NULL);
SelectObject(hDCsrc, hBmpSrc);
SelectObject(hDCdst, hBmpDst);
printf("Src: %08X, %08X\n", PixelsSrc[0], PixelsSrc[1]);
printf("Dst: %08X, %08X\n", PixelsDst[0], PixelsDst[1]);
TransparentBlt(hDCdst, 0, 0, 2, 1, hDCsrc, 0, 0, 2, 1, 0x00555555);
printf("DST: %08X, %08X\n", PixelsDst[0], PixelsDst[1]);
}
Вывод:
Src: EE555555, FFAAAAAA
Dst: CC222222, DD333333
DST: CC222222, 00AAAAAA
Если бы значение альфа-канала для непрозрачного пикселя было скопировано, то вывод был бы следующим:
Src: EE555555, FFAAAAAA
Dst: CC222222, DD333333
DST: CC222222, FFAAAAAA
Примечание: альфа-канал закодирован в старшем бите данных пикселя (bigendian DWORD).
Ответ или решение
Вопрос о правильности документации функции TransparentBlt() в контексте ее работы с 32-битными битмапами требует детального рассмотрения. Согласно документации Microsoft, функция TransparentBlt() поддерживает все форматы исходных битмапов, однако для 32-битных битмапов "просто копирует значение альфа-канала". Этот вывод вызывает определенные сомнения, особенно в свете приведенного вами кода и результатов его выполнения.
Анализ кода и поведения TransparentBlt()
Приведенный код демонстрирует создание двух битмапов (источника и назначения) с 32-битной глубиной цвета, а также применение функции TransparentBlt() для копирования пикселей из исходного битмапа в битмап назначения с учетом прозрачности.
Ключевые моменты:
-
Инициализация пикселей:
- Пиксель
0xEE555555
в исходном битмапе имеет альфа-канал (первый байт) со значениемEE
, и RGB-значение555555
. - Пиксель
0xFFAAAAAA
в исходном битмапе — полностью непрозрачный (альфа-каналFF
), с RGB-значениемAAAAAA
. - В битмапе назначения инициализированы пиксели
0xCC222222
и0xDD333333
.
- Пиксель
-
Вызов TransparentBlt():
- В вашем коде вызывается TransparentBlt() с аргументом
0x00555555
, где00
указывает на прозрачный цвет. По идее, при обработке функции, пиксель с альфа-каналомEE
должен был бы скопироваться в пиксель назначения, а пиксель с альфа-каналомFF
— оставить в исходном состоянии.
- В вашем коде вызывается TransparentBlt() с аргументом
-
Результаты выполнения:
- После вызова функции TransparentBlt() вывод показывает, что альфа-канал для второго пикселя в битмапе назначения стал
00AAAAAA
, что свидетельствует о том, что функция обнуляет альфа-канал для пикселей, которые не являются прозрачными, вместо того чтобы копировать значение из исходного битмапа.
- После вызова функции TransparentBlt() вывод показывает, что альфа-канал для второго пикселя в битмапе назначения стал
Доказательство ошибки в документации
Ваши наблюдения подтверждают несоответствие между заявленной функциональностью в документации и фактическим поведением функции:
- Документация утверждает, что альфа-канал копируется, что подразумевает, что пиксель, который не является прозрачным, должен сохранить свое значение альфа-канала. Однако, на практике, альфа-канал для пикселя с RGB
AAAAAA
изменился на00
.
Таким образом, можно сделать вывод о наличии ошибки в документации функции TransparentBlt(). Основной проблемой является несоответствие между тем, что было заявлено, и тем, что действительно происходит при вызове функции. Функция, по факту, не выполняет ожидаемую операцию копирования альфа-канала для непроводимых пикселей.
Заключение
Для программистов, работающих с Windows GDI и использующих функцию TransparentBlt(), важно знать о данной несоответствующей документации, чтобы избежать неожиданных результатов. Рекомендуется также обратиться в службу поддержки Microsoft с сообщением о данной проблеме, чтобы улучшить документы и восстановить соответствие между описанием и реальным поведением функции.