Создание картинки в Bitmap
Мне нужно создать картинку используя структуру BITMAPINFO и функции bitmap типа BitBlt. Как хронить и передавать данные для картинки?
Для этих целей используй функцию CreateDIBSection.
Хелп в MSDN есть.
Для этих целей используй функцию CreateDIBSection.
Хелп в MSDN есть.
Спасибо.Я это видел. но как передать туда данные если для этого есть указатель типа **void а мои значения скажем храняться массиве типа int?
Спасибо.Я это видел. но как передать туда данные если для этого есть указатель типа **void а мои значения скажем храняться массиве типа int?
Эх, молодежь...
Читаем внимательно Хелп. Что есть ** указатель? Это, русским языком говоря указатель на указатель.
Тобишь, после того как отработает функция CreateDIBSection, в переменной на которую будет указвать **void указатель вернется значение указателя на память, связанную с растровыми данными.
Пример:
void *dib_bits;
HBITMAP rgbBMP;
BITMAPINFO bmInfo;
BITMAP rgbBMPinfo;
// Создаем контекст
memDC=CreateCompatibleDC(image_dc);
memset(&bmInfo,0,sizeof(BITMAPINFO));
bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmInfo.bmiHeader.biWidth=rgbBMPinfo.bmWidth;
bmInfo.bmiHeader.biHeight=rgbBMPinfo.bmHeight;
bmInfo.bmiHeader.biPlanes=1;
bmInfo.bmiHeader.biBitCount=32;
bmInfo.bmiHeader.biCompression=BI_RGB;
// Создаем диб секцию
rgbBMP=CreateDIBSection(memDC,&bmInfo,DIB_RGB_COLORS,&dib_bits,NULL,0);
SelectObject(memDC,rgbBMP);
// Теперь в переменной dib_bits находится указатель на растр изображения (в простанородии пиксели)
// Если брать твой пример то дальше можно сделать так:
int *src_bits; // это твой интовый массив.
memcpy(dib_bits,src_bits,размер);
Вот и все собственно. Есть еще например функция SetDIBBits - можешь ее посмотреть. Также не следует забывать - что если ты прибегнешь к описанному мной способу - тут очень четко надо остлеживать следующие вещи:
1. Глубина цвета изображения (тобишь количество бит на пиксел)
2. Размер одного скана в байтах не всегда равен ширине изображения. Не забываем про выравнивание.
Можно это сделать проще:
GetObject(rgbBMP,sizeof(DIBSECTION),&dibinfo);
После этого dibinfo.dsBm.bmWidthBytes - это как раз полный размер скана вместе со всеми выравниваниями.
Хорошо,скажем я это сделал. Но мне надо вывести картинку на экран. Если я делаю потом
CDC memMyPic;
memMyPic.SelectObject(&rgbBMPinfo);
dc.BitBlt(m_rectWind.left+20 ,m_rectWind.top+20,
rgbBMPinfo.bmWidth,rgbBMPinfo.bmHeight,&mmemMyPic,0,0,SRCCOPY);
как я выведу на экран данные? Да я забыл сказать, картинка должна быть черно-белой.
Заранее спасибо
Спасибо, но все равно не все понятно.
Хорошо,скажем я это сделал. Но мне надо вывести картинку на экран. Если я делаю потом
CDC memMyPic;
memMyPic.SelectObject(&rgbBMPinfo);
dc.BitBlt(m_rectWind.left+20 ,m_rectWind.top+20,
rgbBMPinfo.bmWidth,rgbBMPinfo.bmHeight,&mmemMyPic,0,0,SRCCOPY);
как я выведу на экран данные? Да я забыл сказать, картинка должна быть черно-белой.
Заранее спасибо
Черно-белая картинка - что ты под этим подразумеваешь?
Монохром или Grayscale?
Если монохром - тогда просто создаешь диб секцию с глубиной цвета в 1 бит.
Если тебе нужен Grayscale - тогда 8 бит и grayscale палитра. Как это сделать - смотри здесь
CDC memMyPic;
memMyPic.SelectObject(&rgbBMPinfo);
dc.BitBlt(m_rectWind.left+20 ,m_rectWind.top+20,
rgbBMPinfo.bmWidth,rgbBMPinfo.bmHeight,&mmemMyPic,0,0,SRCCOPY);
Бред какой-то. Ничерта не понял. Если приводишь пример - то по крайней мере хоть комментарии давай чего откуда и куда.
Откуда я например знаю что за контекст находится в переменной dc? Или что такое rgbBMPinfo? Если rgbBMPinfo из моего примера - то приведееный тобой код в корне неправильный. В контескт выбирается битмапа - тоесть HBITMAP получаемый при помощи CreateDIBSection (см. мой пример).
По поводу того как вывести данные на экран. Ответ прост - надо сблитить картинку при помощи BitBlt в контекст того устройства, которое имеет графическое отображение. Например в контекст окна. Это же элементарно, Ватсон....
мы определяем их новое значение. Так?
Но не мог ли бы ты объяснить как послать в BitBlt все данные,если я рисую в классе CPaint диалога. Ибо не знаю в чем проблема но моя программа вырубаеться.
Да спасибо. Так если я правильно понял пиксели для построения беруться из переменной dib_bits и командой memcpy(dib_bits,src_bits,размер);
мы определяем их новое значение. Так?
Но не мог ли бы ты объяснить как послать в BitBlt все данные,если я рисую в классе CPaint диалога. Ибо не знаю в чем проблема но моя программа вырубаеться.
Ладно. Тогда приведу немного теории.
Что из себя представляет Bitmap? Bitmap - это растр, тоесть, набор точек (пикселов). Каждая точка изображения характеризуется цветовым значением. Наиболее часто употребляемый цветовой формат - это RGB - тоесть, конечное значение цвета формируется тремя компонентами R(ed-Красный), G(reen-Зеленый) и B(lue-Синий). Чтобы особо не вдаваться в подробности, скажу что для битмапов используется именно формат RGB от этого и будем плясать. Вернее даже не RGB, а BGR (по умолчанию).
Далее.
Растровые изображения делятся на 2 группы:
1. Палетризованые изображения.
2. RGB изображения.
В чем их отличие?
В RGB изображениях каждый элемент растра (тобишь пиксел) содержит непосредственную последовательность R,G и B компонент, в то время, как в палетризованых изображениях, каждый пиксел - это индекс в предопределеной цветовой таблице, называемой палитрой. А уже каждый элемент палитры это RGB значение.
Теперь введем такое понятие как BPP (Bits Per Pixel). Это зачение характеризует сколько бит отводится под каждый пиксел. Существует несколько общепринятых стандартов BPP.
Для палетризованых изображений:
1 бит ( монохром )
4 бита ( 16 цветов )
8 бит ( 256 цветов )
Для RGB изображений:
15 бит ( R5-G5-B5 )
16 бит ( R5-G6-B5 )
24 бита ( R8-G8-B8 )
32 бита ( R8-G8-B8-A8 )
Все выше описаное - это краткое определение растра Bitmap изображений.
Далее. Как это устроено физически.
С точки зрения организации данных - растр - это есть линейный участок памяти (массив), размер которого характеризуется следующими параметрами:
Высотой(Height), Шириной(Width), размером пиксела (BPP) и выравниванием на границу 2 байт.
Чтобы было проще:
Размер массива(растра) в байтах равен:
размер скан-линии*высоту.
Что такое скан-линия?
Скан-линия, или скан это одна горизонталь изображения - тоесть ее видимая часть+выравнивание.
Размер видимой части скан-линии: ширина*BPP.
Ну соответсвенно чтобы получить полный размер - полученное выше значение нужно выровнять на границу 2 байт.
Далее. Для битмапов существует такое понятие как ориентация сканов. Тоесть, сканы могут идти в порядке снизу-вверх (down-top), или сверху вниз(top-down). Это тоже не стоит забывать. По умолчанию используется down-top ориентация. Чтобы создать битмап с ориентацие top-down при вызове CreateDIBSection нужно указать отрицательное значение высоты изображения.
А теперь вернемся к вопросу.
Так если я правильно понял пиксели для построения беруться из переменной dib_bits и командой memcpy(dib_bits,src_bits,размер);
Исходя из всего выше сказанного dib_bits - это и есть сами пиксели. Иными словами - это указатель на тот самый массив памяти, который и формирует растр изображения.
а команда memcpy - это как знаешь обычная команда копирования данных из одного участка памяти в другой. Поэтому - если src_bits - это твой int массив, который ты хочешь вывести на экран, а dib_bits это указатель на память растра - то после отработки memcpy данные из src_bits окажутся в массиве dib_bits - тоесть станут пикселями растра. Ясно?
Далее. Как работает BitBlt.
Что по этому поводу говорит MSDN:
BOOL BitBlt(
HDC hdcDest, // DC куда рисовать
int nXDest, // x-куда рисовать
int nYDest, // y-куда рисовать
int nWidth, // ширина области отрисовки
int nHeight, // высота области отрисовки
HDC hdcSrc, // DC откуда рисовать
int nXSrc, // x-откуда рисовать
int nYSrc, // y-откуда рисовать
DWORD dwRop // растровая операция
);
Соответсвенно, если говоришь что у тебя падает - значет ты задал где-то не те параметры.
Уж извини - про CPaint ничего тебе не скажу - я не использую MFC.
Вообще, говоря общими словами, алгоритм следующий:
Тебе нужно создать memDC, создать Bitmap. Загрузить битмап в memDC. Далее тебе необходимо получит DC этого CPaint а потом выполнить BitBlt где в качестве hdcDest будет DC CPaint-а в качестве hdcSrc будет memDC.