2011-01-04 3 views
10

У меня есть приложение, которое загружает некоторые данные из базы данных из базы данных, которые могут представлять png форматированные или необработанные двоичные данные для различных растровых изображений и значков. Это хранится в std::vector<unsigned char>Создание HBITMAP из буфера памяти

Я использую объекты CImageList для отображения различных изображений в виде дерева, изображений на панели инструментов и т. Д., Но проблема создания растровых изображений из данных в памяти выходит нечеткой, как если бы отсутствовали пиксели, когда делать что-то, как показано ниже:

std::vector<unsigned char> bits; 
HBITMAP hbitmap = CreateBitmap(16, 16, 1, 32, bits.data()); 

чтобы обойти эту проблему сейчас я просто выписывая данные() в векторе временный файл, а затем с помощью LoadImage, чтобы прочитать его обратно и создания HBITMAP от этого , Это прекрасно работает, но это, по общему признанию, бесстыдный хак, и я должен был быть совершенно ненужным.

Я искал в Интернете, но не нашел действительно хороших примеров того, как «правильно» создавать hbitmaps из памяти. Я хотел бы иметь возможность создавать эти растровые изображения, которые будут добавлены в список изображений без ввода файлов и ограниченных копий данных, если это возможно.

Ищите лучший способ сделать это, и, очевидно, конкретный код Windows в порядке.

UPDATE:

На основании ответа JDV, я начал играть с CreateCompatibleBitmap, CreateDIBitmap, и, наконец, CreateDIBSection. Все это привело к созданию прекрасных черных растровых изображений вместо предыдущих нечетких растровых изображений, поэтому я должен снова что-то делать неправильно, и я предполагаю, что это создание растрового изображения выполняется в объекте, который не имеет понятия о экране или окнах экрана, которые используют GetDC(NULL) и CreateCompatibleDC(NULL) - это не хорошо. Пример кода:

BITMAPINFO bmi; 
    ZeroMemory(&bmi, sizeof(BITMAPINFO)); 
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    bmi.bmiHeader.biBitCount = 32; 
    bmi.bmiHeader.biHeight = 16; 
    bmi.bmiHeader.biWidth = 16; 
    bmi.bmiHeader.biPlanes = 1; 

    HDC dc = CreateCompatibleDC(NULL); 
    HBITMAP hbitmap = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, (void**)blobData.GetMember<FILEDATAFIELD_DATA>().data(), NULL, 0); 

Я сейчас, конечно, думая, что надо быть более простой способ идти об этом, возможно, избегая HBITMAP вообще и работать непосредственно с CBitmap класса? Когда дело доходит до добавления изображения в CImageList, я все равно использую CBitmap::FromHandle(HBITMAP hbitmap, COLORREF mask). Кто-нибудь знает простой способ инициализировать объект CBitmap из std::vector<unsigned char>?

+0

Пожалуйста, не отредактировать вопрос в новом значении, как это аннулирует ответы. Не стесняйтесь публиковать новый вопрос и ссылаться на старый. –

+0

Извините, только что сделал шаг назад и осознал единственную причину, по которой я собирался попасть на землю GDI, потому что я использовал метод FromHandle при добавлении в CImageList ... MFC CBitmap просто в любом случае обматывает вызовы GDI, так что это очень похоже. – AJG85

ответ

3

Использование GdiPlus У меня есть что-то, что работает очень хорошо и не требует вытягивания зубов!

Gdiplus::Bitmap* pBitmap = NULL; 
IStream* pStream = NULL; 

HRESULT hResult = ::CreateStreamOnHGlobal(NULL, TRUE, &pStream); 
if(hResult == S_OK && pStream) 
{ 
    hResult = pStream->Write(&bits[0], ULONG(bits.size()), NULL); 
    if(hResult == S_OK) 
     pBitmap = Gdiplus::Bitmap::FromStream(pStream); 
    pStream->Release(); 
} 

Edit: Изменено на Jegatheesh

+1

И как получить HBITMAP из 'Gdiplus :: Bitmap *'? –

5

Я бы использовал CreateCompatibleBitmap, а затем позвонил SetDIBits, чтобы заполнить его вашими данными. Это функции, которые я видел для работы, и SetDIBits довольно гибкий, хотя и подробный.

В мои годы MFC CreateBitmap был исключен из-за подозрительных проблем с производительностью.

+1

Теперь я смотрю CreateDIBitmap, который из того, что я могу сказать, в основном создает DC-совместимое растровое изображение, а затем вызывает эквивалент SetDIBits, если вы указываете флаг CBM_INIT. Кто-нибудь, кто назвал параметры и члены структур в API Windows, должен быть застрелен. – AJG85

+0

О, верно, был также CreateDIBitmap. –

Смежные вопросы