Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleBitmap)
От: пффф  
Дата: 19.02.24 10:31
Оценка:
Здравствуйте!

Есть BMP файл произвольного формата (1/4/8/16/24/32 бита на цвет), он лежит в памяти

У меня есть (не зависящие от виндовых хидеров, но дублирующие их) структуры, BitmapFileHeader и BitmapInfoHeader, с их помощью я распарсил заголовки, и узнал базовую инфу — размер картинки и тп

  Скрытый текст
        BitmapFileHeader fileHdr;
        if (!fileHdr.extractFromRawData(bmpRawData, 0u))
        {
            return (HBITMAP)0;
        }

        if (fileHdr.bfType!=0x4d42) // the ASCII string "BM"
        {
            return (HBITMAP)0;
        }

        BitmapInfoHeader bmpHeader; // follows immediately file header
        if (!bmpHeader.extractFromRawData(bmpRawData, sizeof(fileHdr)))
        {
            return (HBITMAP)0;
        }

        int xSize = (int)bmpHeader.biWidth ;
        int ySize = (int)bmpHeader.biHeight;
        if (xSize<0)
            xSize = -xSize;
        if (ySize<0)
            ySize = -ySize;


Далее собаководы говорят, что надо сделать CreateCompatibleBitmap и SetDIBits (или за один вызов CreateDIBitmap сделать).

Я так делаю, вроде отрабатывает, но
        BITMAP bm;
        if (hbmp!=0 && GetObject(hbmp,sizeof(bm),&bm)==0)
        {
            DeleteObject((HGDIOBJ)hbmp);
            hbmp = 0;
        }


возвращает мне, что у меня картинка монохромная

Копаю дальше. Если я создаю HDC при помощи CreateCompatibleDC, то там:

Note: When a memory device context is created, it initially has a 1-by-1 monochrome bitmap selected into it. If this memory device context is used in CreateCompatibleBitmap, the bitmap that is created is a monochrome bitmap.


Я кажется понял, почему я получаю монохромную картинку. Ок.
Хорошо, я допустим возьму экранный DC через GetDC. Я пока не проверил, но у меня есть подозрение, что там если и будет не монохромная битмапка, то она будет 24бпп, а если я гружу картинку с 32бпп с альфаканалом?

Тут какой-то замкнутый круг — для того чтобы загрузить в HBITMAP картинку в нужном формате, нужно создать hdc с картинкой в нужном формате, а для этого нужно иметь HBITMAP картинки в нужном формате.

Чего я не понял?
Re: Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleBitm
От: Carc Россия https://vk.com/gosha_mazov
Дата: 19.02.24 10:53
Оценка:
Здравствуйте, пффф, Вы писали:

П>Здравствуйте!


П>Есть BMP файл произвольного формата (1/4/8/16/24/32 бита на цвет), он лежит в памяти


П>У меня есть (не зависящие от виндовых хидеров, но дублирующие их) структуры, BitmapFileHeader и BitmapInfoHeader, с их помощью я распарсил заголовки, и узнал базовую инфу — размер картинки и тп

П>Чего я не понял?
[skipped]

Можно попробовать грузить из памяти через IStream, или GDI+ поюзать.
IStream* pStream = NULL;
::CreateStreamOnHGlobal(m_hBuffer, FALSE, &pStream)
m_pBitmap = Gdiplus::Bitmap::FromStream(pStream);
pStream->Release();

Куда-то сюда копать.
Aml Pages Home
Re[2]: Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleB
От: пффф  
Дата: 19.02.24 11:05
Оценка:
Здравствуйте, Carc, Вы писали:


C>Можно попробовать грузить из памяти через IStream, или GDI+ поюзать.

C>
C>IStream* pStream = NULL;
C>::CreateStreamOnHGlobal(m_hBuffer, FALSE, &pStream)
C>m_pBitmap = Gdiplus::Bitmap::FromStream(pStream);
C>pStream->Release();
C>

C>Куда-то сюда копать.

Не, для битмапок хочется обойтись без GDI+
Re[3]: Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleB
От: Carc Россия https://vk.com/gosha_mazov
Дата: 19.02.24 11:22
Оценка:
Здравствуйте, пффф, Вы писали:

П>Здравствуйте, Carc, Вы писали:



C>>Можно попробовать грузить из памяти через IStream, или GDI+ поюзать.

C>>
C>>IStream* pStream = NULL;
C>>::CreateStreamOnHGlobal(m_hBuffer, FALSE, &pStream)
C>>m_pBitmap = Gdiplus::Bitmap::FromStream(pStream);
C>>pStream->Release();
C>>

C>>Куда-то сюда копать.

П>Не, для битмапок хочется обойтись без GDI+

Тогда можно покопать в сторону CreateStreamOnHGlobal
Aml Pages Home
Re: Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleBitm
От: Pavel Dvorkin Россия  
Дата: 19.02.24 11:54
Оценка: 4 (2)
Здравствуйте, пффф, Вы писали:


Попробуй вот это

https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createdibsection
With best regards
Pavel Dvorkin
Re: Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleBitm
От: пффф  
Дата: 19.02.24 12:17
Оценка:
Здравствуйте, пффф, Вы писали:

Похоже, я нашел, что нужно.

Надо создать hdc = CreateCompatibleDC(0)
Надо создать пустую битмапку через CreateBitmap — размер 1x1, nPlanes и nBitCount беру из прочитанного заголовка, lpBits задаю 0
Затем — выбираю её в hdc
Затем создаю CreateCompatibleBitmap
Затем SetDIBits

И дело в шляпе (но пака ещё не проверил).

Блин, как всё просто-то
Re[2]: Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleB
От: пффф  
Дата: 19.02.24 12:48
Оценка:
Здравствуйте, пффф, Вы писали:

А вот фиг.

П>Похоже, я нашел, что нужно.


П>Надо создать hdc = CreateCompatibleDC(0)

П>Надо создать пустую битмапку через CreateBitmap — размер 1x1, nPlanes и nBitCount беру из прочитанного заголовка, lpBits задаю 0
П>Затем — выбираю её в hdc

Ломается на данном этапе
SelectObject(hdc, hBmpPattern);

GetLastError() возвращает 6 — ERROR_INVALID_HANDLE

Хотя перед этим CreateCompatibleDC(0) и CreateBitmap вернули не 0:
hBmpPattern    0xffffffff9a051445    void *
hdc        0xffffffffcc011533 {unused=??? }    HDC__ *
Re[2]: Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleB
От: пффф  
Дата: 19.02.24 13:11
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Попробуй вот это


PD>https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createdibsection


Спасибо, так работает
Re[3]: Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleB
От: Carc Россия https://vk.com/gosha_mazov
Дата: 19.02.24 16:00
Оценка:
Здравствуйте, пффф, Вы писали:

П>Здравствуйте, пффф, Вы писали:


П>GetLastError() возвращает 6 — ERROR_INVALID_HANDLE


П>Хотя перед этим CreateCompatibleDC(0) и CreateBitmap вернули не 0:

Что возвращает GetObjectType на полученный Gdi Handle?

Хотя и упомянутая выше GetObjectType, может тупить, и работать не очень прям синхронно по факту вызова.
Лично, в своем же коде видел как на DeletObject (HFONT) возвращала TRUE.
А вот строчкой ниже Винда радостно говорила на GetObjectType(тот же самый HFONT, убитый строчкой выше) == OBJ_FONT (всё ништяк, чувак — шрифт живой).

«Вона-она-как-она быватЪ» ©
Хотя, конечно же такое поведение вполне обьянимо и разумно.
Aml Pages Home
Re[4]: Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleB
От: qaz77  
Дата: 19.02.24 16:32
Оценка:
Здравствуйте, Carc, Вы писали:

C>Лично, в своем же коде видел как на DeletObject (HFONT) возвращала TRUE.

C>А вот строчкой ниже Винда радостно говорила на GetObjectType(тот же самый HFONT, убитый строчкой выше) == OBJ_FONT (всё ништяк, чувак — шрифт живой).

По битам самого хэндла тип объекта определяется.
GDI только 16 бит хэндла использует под индекс в таблице, а остальное — под информацию о типе и т.п.
Re[5]: Создать HBITMAP из байтов BMP-файла в памяти (SetDIBits/CreateCompatibleB
От: Carc Россия https://vk.com/gosha_mazov
Дата: 19.02.24 17:28
Оценка:
Здравствуйте, qaz77, Вы писали:

Q>Здравствуйте, Carc, Вы писали:


C>>Лично, в своем же коде видел как на DeletObject (HFONT) возвращала TRUE.

C>>А вот строчкой ниже Винда радостно говорила на GetObjectType(тот же самый HFONT, убитый строчкой выше) == OBJ_FONT (всё ништяк, чувак — шрифт живой).

Q>По битам самого хэндла тип объекта определяется.

Q>GDI только 16 бит хэндла использует под индекс в таблице, а остальное — под информацию о типе и т.п.
Не тот случай.
Я тогда специально проверял этот убитый HGDIOBJ на Font, в отдельном куске кода, который выполнялся несколько погодя...
Дык вот в куске кода (который "погодя") уже ожидаемо было: GetObjectType(на убитый шрифт) выдавало ожидаемое значение OBJ_ERROR.
Aml Pages Home
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.