LoadImage из памяти
От: Vaynamond Россия  
Дата: 13.05.19 12:03
Оценка:
Доброго дня!

Подскажите, плз, существует-ли элегантный способ загрузки bmp-картинки, которая находится не в файле, а в памяти ?
Контекст задачи: bmp-файл передается по сети на другой компьютер в виде байтового массива. Т.е. на компьютере-приемнике содержимое файла уже находится в памяти.
На ум приходит только вариант с временным файлом (т.е. содержимое памяти сбрасываем в файл, к которому применяем LoadImage штатным образом).
Re: LoadImage из памяти
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 13.05.19 14:14
Оценка:
Здравствуйте, Vaynamond, Вы писали:

V>Подскажите, плз, существует-ли элегантный способ загрузки bmp-картинки, которая находится не в файле, а в памяти ?

V>Контекст задачи: bmp-файл передается по сети на другой компьютер в виде байтового массива. Т.е. на компьютере-приемнике содержимое файла уже находится в памяти.

Просто создать заголовок руками.
Re[2]: LoadImage из памяти
От: Vaynamond Россия  
Дата: 13.05.19 14:54
Оценка:
Здравствуйте, Nuzhny, Вы писали:

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


V>>Подскажите, плз, существует-ли элегантный способ загрузки bmp-картинки, которая находится не в файле, а в памяти ?

V>>Контекст задачи: bmp-файл передается по сети на другой компьютер в виде байтового массива. Т.е. на компьютере-приемнике содержимое файла уже находится в памяти.

N>Просто создать заголовок руками.

Это не совсем то, что нужно. У меня есть полноценный bmp-файл в памяти. Задача — превратить указатель на эту память
в нечто HBITMAP-образное.
Re[3]: LoadImage из памяти
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 13.05.19 15:08
Оценка:
Здравствуйте, Vaynamond, Вы писали:

N>>Просто создать заголовок руками.

V>Это не совсем то, что нужно. У меня есть полноценный bmp-файл в памяти. Задача — превратить указатель на эту память
V>в нечто HBITMAP-образное.

Тогда просто скастить указатели в памяти на PBITMAPINFO, а потом вызвать CreateBitmap (или CreateCompatibleBitmap для конкретного HDC) с твоими данными.
Re[4]: LoadImage из памяти
От: Vaynamond Россия  
Дата: 13.05.19 19:12
Оценка:
Здравствуйте, Nuzhny, Вы писали:

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


N>>>Просто создать заголовок руками.

V>>Это не совсем то, что нужно. У меня есть полноценный bmp-файл в памяти. Задача — превратить указатель на эту память
V>>в нечто HBITMAP-образное.

N>Тогда просто скастить указатели в памяти на PBITMAPINFO, а потом вызвать CreateBitmap (или CreateCompatibleBitmap для конкретного HDC) с твоими данными.

О, завтра попробую.
Re: LoadImage из памяти
От: uuuser  
Дата: 14.05.19 00:15
Оценка:
Здравствуйте, Vaynamond, Вы писали:

V>Подскажите, плз, существует-ли элегантный способ загрузки bmp-картинки, которая находится не в файле, а в памяти ?

V>Контекст задачи: bmp-файл передается по сети на другой компьютер в виде байтового массива. Т.е. на компьютере-приемнике содержимое файла уже находится в памяти.
V>На ум приходит только вариант с временным файлом (т.е. содержимое памяти сбрасываем в файл, к которому применяем LoadImage штатным образом).

куда загрузить? gdi/dgi+/wic/dx ?

для gdi+

GlobalAlloc
GlobalLock
CreateStreamOnHGlobal
Gdiplus::Bitmap()
Re[2]: LoadImage из памяти
От: Vaynamond Россия  
Дата: 14.05.19 07:48
Оценка:
Здравствуйте, uuuser, Вы писали:

U>куда загрузить? gdi/dgi+/wic/dx ?


Сейчас используется такой алгоритм (схематично):

HANDLE hBmp = LoadImage(NULL, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
...
SelectObject(hBmpDC, hBmp);
...
StretchBlt(hDC, dstX, dstY, dstWidth, dstHeight, hBmpDC, srcX, srcY, srcWidth, srcHeight, SRCCOPY);

Функция LoadImage загружает картинку из файла на диске и возвращает дескриптор.
В моём случае файл с картинкой уже загружен в память (как массив байт), и мне нужно каким-то способом
превратить указатель на эту память в дескриптор hBmp.
Re[3]: LoadImage из памяти
От: loginx  
Дата: 14.05.19 08:17
Оценка:
Здравствуйте, Vaynamond, Вы писали:


V>HANDLE hBmp = LoadImage(NULL, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);


интересно, что аналогичная проблемка с запуском ехе на исполнение из памяти, а не с диска...
Re[4]: LoadImage из памяти
От: Vaynamond Россия  
Дата: 14.05.19 10:24
Оценка:
Здравствуйте, loginx, Вы писали:

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



V>>HANDLE hBmp = LoadImage(NULL, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);


L>интересно, что аналогичная проблемка с запуском ехе на исполнение из памяти, а не с диска...

Возможно, для exe-файла ограничение связано с безопасностью, а вот что помешало для LoadImage сделать
режим LR_LOADFROMMEM, для меня загадка...
Re[5]: LoadImage из памяти
От: loginx  
Дата: 14.05.19 14:50
Оценка:
Здравствуйте, Vaynamond, Вы писали:

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


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



V>>>HANDLE hBmp = LoadImage(NULL, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);


L>>интересно, что аналогичная проблемка с запуском ехе на исполнение из памяти, а не с диска...

V>Возможно, для exe-файла ограничение связано с безопасностью, а вот что помешало для LoadImage сделать
V>режим LR_LOADFROMMEM, для меня загадка...

вряд ли с безопасностью — так как визуал бэйсик может из текста исполнять и диск форматнуть, ну и C# рефлексия тоже есть
это скорее какая-то религиозная догма у некрософта — все что угодно только не из памяти
Re[3]: LoadImage из памяти
От: uuuser  
Дата: 15.05.19 03:10
Оценка:
Здравствуйте, Vaynamond, Вы писали:

U>>куда загрузить? gdi/dgi+/wic/dx ?

V>Сейчас используется такой алгоритм (схематично):
V>HANDLE hBmp = LoadImage(NULL, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

ну тогда

GlobalAlloc
GlobalLock
CreateStreamOnHGlobal
Bitmap::FromStream()
Bitmap::GetHBITMAP()

тут пример кода, кусок по получению адреса из ресурса выкинуть
https://www.codeproject.com/Articles/3537/Loading-JPG-PNG-resources-using-GDI
Отредактировано 15.05.2019 3:57 uuuser . Предыдущая версия .
Re[4]: LoadImage из памяти
От: Vaynamond Россия  
Дата: 15.05.19 07:12
Оценка:
Здравствуйте, uuuser, Вы писали:

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


U>>>куда загрузить? gdi/dgi+/wic/dx ?

V>>Сейчас используется такой алгоритм (схематично):
V>>HANDLE hBmp = LoadImage(NULL, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

U>ну тогда


U>GlobalAlloc

U>GlobalLock
U>CreateStreamOnHGlobal
U>Bitmap::FromStream()
U>Bitmap::GetHBITMAP()

U>тут пример кода, кусок по получению адреса из ресурса выкинуть

U>https://www.codeproject.com/Articles/3537/Loading-JPG-PNG-resources-using-GDI
Я смотрел варианты на GDI+, там это можно сделать проще. Меня интересует "чистый" WIN API.
Нашел такой вариант.
В моем случае почти работает. Почему почти — картинка выводится, но в каком-то виде, напоминающем инверсию + часть
сползших цветов.
Re: LoadImage из памяти
От: qaz77  
Дата: 15.05.19 07:49
Оценка:
Здравствуйте, Vaynamond, Вы писали:
V>Подскажите, плз, существует-ли элегантный способ загрузки bmp-картинки, которая находится не в файле, а в памяти ?

Можно создать IStream с помощью CreateStreamOnHGlobal и скормить его в OleLoadPicture.
Получим IPicture, у которой есть Handle, его можно скастить в HBITMAP.

OleLoadPicture поддерживает bmp, gif и jpeg, но не png
Re[5]: LoadImage из памяти
От: Pavel Dvorkin Россия  
Дата: 16.05.19 04:25
Оценка:
Здравствуйте, Vaynamond, Вы писали:

V>В моем случае почти работает. Почему почти — картинка выводится, но в каком-то виде, напоминающем инверсию + часть

V>сползших цветов.

Какой формат данных ? 32bpp ? 24 bpp ?

Если 24 bpp — строки выровнены на DWORD ?

The scan lines must be aligned on a DWORD except for RLE-compressed bitmaps.

https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-setdibits
With best regards
Pavel Dvorkin
Отредактировано 16.05.2019 4:30 Pavel Dvorkin . Предыдущая версия .
Re[2]: LoadImage из памяти
От: Vaynamond Россия  
Дата: 16.05.19 14:22
Оценка:
Здравствуйте, qaz77, Вы писали:

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

V>>Подскажите, плз, существует-ли элегантный способ загрузки bmp-картинки, которая находится не в файле, а в памяти ?

Q>Можно создать IStream с помощью CreateStreamOnHGlobal и скормить его в OleLoadPicture.

Q>Получим IPicture, у которой есть Handle, его можно скастить в HBITMAP.

Q>OleLoadPicture поддерживает bmp, gif и jpeg, но не png

Вообщем, пришлось выкрутиться с помощью GDI+. Но заработало сходу.
Re[3]: LoadImage из памяти
От: uuuser  
Дата: 16.05.19 22:10
Оценка:
Здравствуйте, Vaynamond, Вы писали:

Q>>OleLoadPicture поддерживает bmp, gif и jpeg, но не png

V>Вообщем, пришлось выкрутиться с помощью GDI+. Но заработало сходу.

костыли с ручным парсингом bmp проиграли... а гонору-то...
Re[6]: LoadImage из памяти
От: Vaynamond Россия  
Дата: 17.05.19 07:34
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


V>>В моем случае почти работает. Почему почти — картинка выводится, но в каком-то виде, напоминающем инверсию + часть

V>>сползших цветов.

PD>Какой формат данных ? 32bpp ? 24 bpp ?

8 bpp
Картинка в градациях серого.
Re[7]: LoadImage из памяти
От: Pavel Dvorkin Россия  
Дата: 17.05.19 09:12
Оценка:
Здравствуйте, Vaynamond, Вы писали:

V>8 bpp

V>Картинка в градациях серого.

Тогда надо палитру настроить

RGBQUAD bmiColors[1];

https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/ns-wingdi-tagbitmapinfo

Здесь один элемент в массиве вроде как, но это неверно. Их количество в BITMAPINFOHEADER.biClrUsed, и надо все их установить. А в примере , что ты взял, только один поставлен.
With best regards
Pavel Dvorkin
Re[8]: LoadImage из памяти
От: Vaynamond Россия  
Дата: 20.05.19 20:21
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


V>>8 bpp

V>>Картинка в градациях серого.

PD>Тогда надо палитру настроить


PD> RGBQUAD bmiColors[1];


PD>https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/ns-wingdi-tagbitmapinfo


PD>Здесь один элемент в массиве вроде как, но это неверно. Их количество в BITMAPINFOHEADER.biClrUsed, и надо все их установить. А в примере , что ты взял, только один поставлен.


Конструкция bmiColors[1] предполагает, что bmiColors является началом массива RGBQUAD,
который размещается в bmp-файле за заголовками. Подозреваю, что нужно было попробовать наложить
BITMAPINFO на начало BITMAPINFOHEADER.
Re[5]: LoadImage из памяти
От: RonWilson Россия  
Дата: 22.05.19 12:56
Оценка:
Здравствуйте, Vaynamond, Вы писали:

L>>интересно, что аналогичная проблемка с запуском ехе на исполнение из памяти, а не с диска...

V>Возможно, для exe-файла ограничение связано с безопасностью, а вот что помешало для LoadImage сделать
V>режим LR_LOADFROMMEM, для меня загадка...

вроде можно, сам не проверял
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.