Страницы

Поиск по вопросам

воскресенье, 7 июля 2019 г.

Как конвертировать Bitmap в HBITMAP без потери прозрачности?

Здравствуйте! Мне нужно загрузить из файла/ресурса png рисунок с альфа пикселями и вывести его на контекст. С загрузкой хорошо справляется GDI+, но вот с выводом изображения Graphics::DrawImage() всё плохо, поэтому я решил использовать GDI (StretchBlt и т.д.). Но в StretchBlt Bitmap не запихнёшь, нужен HBITMAP. У Bitmap есть метод GetHBITMAP(Color, HBITMAP*), и в нём-то и проблема: он, почему-то конвертирует с потерей прозрачности. Я пробовал передавать Color::Black и Color::Transparent, но ничего не помогает. Как тогда получить HBITMAP с прозрачностью?
ОБНОВЛЕНО
Я понял в чём была ошибка и она глупая. Ниже вы можете увидить мой код, звёздочками я выделил то чего не было. То есть я рисовал изображение на второй буффер, на котором ничего не было, и удивлялся почему-это, альфа пиксели чёрные. Теперь я додумался что нужно сначала нарисовать на буфер фон, а потом уже рисовать изображение. Но опять проблема: Рисую несколько картинок, вместо картинки 1920/1080(мой экран) просто чёрное(у картинки нет альфа пикселей), картинки других размеров, 100/100 например, в произвольных расположениях рисуются, но с чёрным прямоугольником в левом верхнем углу(у картинки нет альфа пикселей). Если закрасить главный фон(перед выводом изображения 1920/1080, то фон таким же и будет(картинка вообще никак не выводится, получается?), у маленьких картинок цвет прямоугольника такой же становится(походу это прозрачность(но альфа пикселей,ещё раз, там нет).
Я так понимаю, второй раз использовать SelectObject нельзя, да? В общем, подскажите в чём тут проблема?
class Imagee { HDC hdc; HBITMAP bm;
Imagee(HDC hdc, HBITMAP bm, another args) { this->hdc=CreateCompatibleDC(hdc); this->bm=bm; SelectObject(this->hdc,this->bm); }
void draw(int hdcc, int x,int y, int cx, int cy) { **StretchBlt(this->hdc,0,0,cx,cy,hdcc,x,y,cx,cy,SRCCOPY); SelectObject(this->hdc,this->bm); **
StretchBlt(this->hdcc,x,y,cx,cy,hdc,0,0,cx,cy,SRCCOPY); };
};
Imagee *image;
void render() { for(;;) {
//здесь я загружая через гди+ битмам, конвертирую его в хбитмап, записывая в перменную HBITMAP hbm
if(image==0) image=new Imagee(hdc_mem, hbm, x, y и т.д.);
image->draw(hdc_mem, x, y и т.д.);
StretchBlt(hdc_main,0,0,1920,1080,hdc_mem,0,0,1920,1080,SRCCOPY); //hdc_main главный дс, hdc_mem буфер
} }


Ответ

Отвечая на вопрос:
_Check_return_ ::HBITMAP LoadPng(_In_z_ const ::LPWSTR psz_file_path) { ::HBITMAP bitmap_handle{}; if(psz_file_path) { const ::BOOL embedded_color_management{TRUE}; ::Gdiplus::Bitmap bitmap{psz_file_path, embedded_color_management}; if(::Gdiplus::Status::Ok == bitmap.GetLastStatus()) { const ::Gdiplus::Color background{0, 0, 0, 0}; if(::Gdiplus::Status::Ok != bitmap.GetHBITMAP(background, &bitmap_handle)) { bitmap_handle = NULL; } } } return(bitmap_handle); }
Как ни странно, но Color::Transparent это не то же самое, что 0, 0, 0, 0. Еще стоит отметить что полученная картинка будет уже с предварительно умноженным (premultiplied) альфа каналом, т.е. пригодная для рисования посредством GdiAlphaBlend и прочих функций.

Комментариев нет:

Отправить комментарий