Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / C++ Новый топик    Ответить
 Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
Mandarin
Member

Откуда: Саратов
Сообщений: 1174
Всем привет! Подскажите пожалуйста, правильно ли я делаю снимок экрана.
#include <windows.h>

const int bit = 16;

int main()
{
    BITMAPFILEHEADER bfHeader;
    BITMAPINFOHEADER biHeader;
    BITMAPINFO bInfo;
    HGDIOBJ hTempBitmap;
    HBITMAP hBitmap;
    BITMAP bAllDesktops;
    HDC hDC, hMemDC;
    LONG lWidth, lHeight;
    BYTE* bBits = NULL;
    HANDLE hHeap = GetProcessHeap();
    DWORD cbBits, dwWritten = 0;
    HANDLE hFile;
    INT x = GetSystemMetrics(SM_XVIRTUALSCREEN);
    INT y = GetSystemMetrics(SM_YVIRTUALSCREEN);

    ZeroMemory(&bfHeader, sizeof(BITMAPFILEHEADER));
    ZeroMemory(&biHeader, sizeof(BITMAPINFOHEADER));
    ZeroMemory(&bInfo, sizeof(BITMAPINFO));
    ZeroMemory(&bAllDesktops, sizeof(BITMAP));

    hDC = GetDC(NULL);
    hTempBitmap = GetCurrentObject(hDC, OBJ_BITMAP);
    GetObjectW(hTempBitmap, sizeof(BITMAP), &bAllDesktops);

    lWidth = bAllDesktops.bmWidth;
    lHeight = bAllDesktops.bmHeight;

    DeleteObject(hTempBitmap);

    bfHeader.bfType = (WORD)('B' | ('M' << 8));
    bfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    biHeader.biSize = sizeof(BITMAPINFOHEADER);
    biHeader.biBitCount = bit;
    biHeader.biCompression = BI_RGB;
    biHeader.biPlanes = 1;
    biHeader.biWidth = lWidth;
    biHeader.biHeight = lHeight;
 
    bInfo.bmiHeader = biHeader;

    cbBits = (((bit * lWidth + 31) & ~31) / 8) * lHeight;

    hMemDC = CreateCompatibleDC(hDC);
    hBitmap = CreateDIBSection(hDC, &bInfo, DIB_PAL_COLORS, (VOID**)&bBits, NULL, 0);
    SelectObject(hMemDC, hBitmap);
    BitBlt(hMemDC, 0, 0, lWidth, lHeight, hDC, x, y, SRCCOPY);


    hFile = CreateFileW(L"000_16.bmp", GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    WriteFile(hFile, &bfHeader, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
    WriteFile(hFile, &biHeader, sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
    WriteFile(hFile, bBits, cbBits, &dwWritten, NULL);

    CloseHandle(hFile);

    DeleteDC(hMemDC);
    ReleaseDC(NULL, hDC);
    DeleteObject(hBitmap);
}

Этот код я подсмотрел в интернете. Вместо 16bit, в примере, было 24bit. Я поменял на 16bit. На выходе файл получается вроде как нормальный в windows он открывается и изображение выглядит правильно. Мне нужно закодировть полученное изображение в PNG. Кодировку изображение я делаю уже в JAVA. Если я кодирую BMP 24bit, то на выходе получается правильный PNG, если кодирую 16bit то на выходе получается "кривой" PNG, цвета изображения правильные, но само изображение испорченное получается.
Ещё обратил внимание на то, что если DIB_PAL_COLORS заменить на DIB_RGB_COLORS, то изображение получается правильное, а цвета не правильные, всё как в синем тумане.
Если код получения BMP правильный, то я буду искать ошибку на стороне JAVA, если код, который я привёл как пример, не правильный, подскажите пожалуйста где ошибка.
29 мар 20, 09:39    [22107528]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
Изопропил
Member

Откуда:
Сообщений: 31461
Mandarin,


BMP получается вроде как правильным,
но формат BMP 16 бит на пиксель изначально кривой,
потому во избежание недоразумений снимок экрана лучше делать 32bpp и затем енкодировать
29 мар 20, 11:18    [22107552]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
Mandarin
Member

Откуда: Саратов
Сообщений: 1174
Изопропил,

Спасибо большое за совет!
29 мар 20, 11:57    [22107563]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
mayton
Member

Откуда: loopback
Сообщений: 46320
Как-то автор умудрился в топик втащить примерно 3 разные темы.

Просто хотел напомнить что количество бит на цвет и количество бит на канал - это разные понятия.
И мне на секундочку показалось что автор их путает. Или путается в техническом задании.

И кривой png - это какое-то слишком... философское или гуманитарное понятие. Это все равно что
вместо "освещенность в люменах стала ниже" сказать "смеркалось".

Понимаешь да?
29 мар 20, 13:45    [22107612]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 49957

mayton
И мне на секундочку показалось что автор их путает.

Ну он же сразу сказал, что он гуглопрограмист и просто плясал с бубном вокруг чужого кода.

Posted via ActualForum NNTP Server 1.5

29 мар 20, 13:51    [22107614]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
Изопропил
Member

Откуда:
Сообщений: 31461
mayton,

я о кривом BMP, а не  PNG

в коде топикстартера формируется BITMAPINFOHEADER(да и тот максимально нулями заполнен), а не BITMAPV4HEADER, позволяющий различать RGB 5-5-5 и 5-6-5

что там наделает CreateDIBSection - ХЗ
29 мар 20, 15:20    [22107637]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
mayton
Member

Откуда: loopback
Сообщений: 46320
GI-GO
29 мар 20, 15:20    [22107638]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 5914
Изопропил
mayton,

я о кривом BMP, а не  PNG

в коде топикстартера формируется BITMAPINFOHEADER(да и тот максимально нулями заполнен), а не BITMAPV4HEADER, позволяющий различать RGB 5-5-5 и 5-6-5

что там наделает CreateDIBSection - ХЗ
нормально будет, всё он отличает, старый же формат
30 мар 20, 12:00    [22108009]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
Изопропил
Member

Откуда:
Сообщений: 31461
kealon(Ruslan),
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader

и каким образом?
30 мар 20, 12:17    [22108022]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 5914
Изопропил,

вот этим и задаётся всё
автор
biBitCount

Specifies the number of bits per pixel (bpp). For uncompressed formats, this value is the average number of bits per pixel. For compressed formats, this value is the implied bit depth of the uncompressed image, after the image has been decoded.

biClrUsed

Specifies the number of color indices in the color table that are actually used by the bitmap. See Remarks for more information.


PS: это не теоретизирование, а практический опыт создания таких битмапов (15-ти и 16-ти битных)

ну а то, что некоторые новые программы не могут, ну кто им доктур ....
30 мар 20, 16:09    [22108200]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
CEMb
Member

Откуда: Столько
Сообщений: 1994
Mandarin
Мне нужно закодировть полученное изображение в PNG. Кодировку изображение я делаю уже в JAVA
Не уверен, но вроде бы GDI+ умеет сохранять PNG.
Я PNG сохраняю, используя родной PNG-шный код.
2 апр 20, 05:52    [22109704]     Ответить | Цитировать Сообщить модератору
 Re: Создание снимка экрана в формате BMP с глубиной цвета 16bit  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 5914
CEMb
Mandarin
Мне нужно закодировть полученное изображение в PNG. Кодировку изображение я делаю уже в JAVA
Не уверен, но вроде бы GDI+ умеет сохранять PNG.
Я PNG сохраняю, используя родной PNG-шный код.

умеет, и очень неплохо
там строчек 5:
в данном случае создать битмап на основе DIB-секции и дальше сохранить, указав GUID PNG-конвертера

Сообщение было отредактировано: 2 апр 20, 14:35
2 апр 20, 14:34    [22109889]     Ответить | Цитировать Сообщить модератору
Все форумы / C++ Ответить