Когда я создаю новый Gdiplus :: Bitmap с помощью функции Bitmap :: FromHBITMAP, результирующее растровое изображение непрозрачно - частичная прозрачность исходного HBITMAP не сохраняется.
Есть ли способ создать Gdiplus :: Bitmap из HBITMAP, который передает данные альфа-канала?
Да, прозрачность есть. Он прекрасно рисуется с помощью функции :: AlphaBlend ().
(Я создал его на C#, используя новое изображение Bitmap (строковое имя файла) и вызов GetHBitmap () для объекта растрового изображения .NET)





Оказывается, GDI + никогда не использует альфа-канал при создании Bitmap из HBITMAP.
Ответ таков:
В моем случае формат входного HBITMAP является правильным для выполнения прямого memcpy из входных данных пикселей растрового изображения в новые данные пикселей растрового изображения.
Если вы не получили входные данные пикселей из GetObject, используйте GetDIBits, чтобы получить копию в правильном формате.
Я считаю, что рабочий код более полезен, чем инструкции, поэтому:
#include <GdiPlus.h>
#include <memory>
Gdiplus::Status HBitmapToBitmap( HBITMAP source, Gdiplus::PixelFormat pixel_format, Gdiplus::Bitmap** result_out )
{
BITMAP source_info = { 0 };
if ( !::GetObject( source, sizeof( source_info ), &source_info ) )
return Gdiplus::GenericError;
Gdiplus::Status s;
std::auto_ptr< Gdiplus::Bitmap > target( new Gdiplus::Bitmap( source_info.bmWidth, source_info.bmHeight, pixel_format ) );
if ( !target.get() )
return Gdiplus::OutOfMemory;
if ( ( s = target->GetLastStatus() ) != Gdiplus::Ok )
return s;
Gdiplus::BitmapData target_info;
Gdiplus::Rect rect( 0, 0, source_info.bmWidth, source_info.bmHeight );
s = target->LockBits( &rect, Gdiplus::ImageLockModeWrite, pixel_format, &target_info );
if ( s != Gdiplus::Ok )
return s;
if ( target_info.Stride != source_info.bmWidthBytes )
return Gdiplus::InvalidParameter; // pixel_format is wrong!
CopyMemory( target_info.Scan0, source_info.bmBits, source_info.bmWidthBytes * source_info.bmHeight );
s = target->UnlockBits( &target_info );
if ( s != Gdiplus::Ok )
return s;
*result_out = target.release();
return Gdiplus::Ok;
}
У меня была аналогичная проблема с CBitmap, из которого я получил HBITMAP. В этом случае ::GetObject() оставил source_info.bmBits установленным в NULL. Я мог бы решить эту проблему, позвонив в myCBitmapPtr->GetBitmapBits(source_info.bmWidthBytes * source_info.bmHeight, target_info.Scan0).
Кстати, возвращаемые значения хорошо проверены в вашем примере, но если source_info.bmBits равен NULL, есть нарушение прав доступа при вызове CopyMemory().
Вы точно знаете, что у HBITMAP есть альфа-канал для начала? Например, вы создали его как DIB с BI_RGB и 32bpp или каким-то другим способом?