Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 8 мая!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Возможности языков семейства Си по истине безграничны, однако, в этой свободе кроются и недостатки: всегда нужно программисту держать ухо востро и контроллировать "переполнение буфера", чтобы потом программа не вылетала в "синий экран" на массе разнообразных версий Windows и железа у пользователей. Те же крэкеры и реверсеры специально ищут в коде программ на Си уязвимости, куда можно подсадить любой вирусный код, об этом более подробно автор рассказывал в своём видеокурсе здесь. Я там многое узнал и теперь мой код стал значительно более безопасный.

Создаём регион из файла


Автор: Yuriy Zaporozhets

Описание

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

Компилятор: Visual C++ 4-6

Функция называется CreateRgn и имеет два параметра:
szFileName - имя файла, содержащего картинку.
pPoint - указатель на структуру POINT , которая содержит координаты цвета, который используется для конструирования региона, если параметр NULL, то будет использоваться цвет в координате (0, 0).

HRGN CreateRgn(LPTSTR szFileName, LPPOINT pPoint)
 {
 	HBITMAP hBmp = (HBITMAP)LoadImage( NULL, szFileName,
                                IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
 	if ( !hBmp ) return NULL;
 
 	BITMAP bi;
 	BYTE bpp;
 	DWORD e;
 	DWORD f, t;
 	INT i, j;
 	bool b = false;
 	HRGN Rgn, ResRgn = CreateRectRgn( 0, 0, 0, 0 );
 
 	GetObject( hBmp, sizeof( BITMAP ), &bi );
 
 	bpp = bi.bmBitsPixel >> 3;
 
 	BYTE *pBits = new BYTE[ bi.bmWidth * bi.bmHeight * bpp ];
 
 	int  p = GetBitmapBits( hBmp, bi.bmWidth * bi.bmHeight * bpp,
                                                                 pBits );
 
 	if ( pPoint == NULL || pPoint->x >= bi.bmWidth ||
                                              pPoint->y >= bi.bmHeight )
 		e = *(DWORD*)pBits;
 	else
 		e = *(DWORD*)(pBits + (pPoint->y * bi.bmWidth + pPoint->x) * bpp );
 
 	e <<= 32 - bi.bmBitsPixel;
 
 	for ( i = 0; i < bi.bmHeight; i++ )
 	for ( j = 0; j < bi.bmWidth; j++ )
 	{
 		t = *(DWORD*)(pBits + (i * bi.bmWidth +
                                         j) * bpp) << (32 - bi.bmBitsPixel);
 
 		if ( t == e )
 		{
 			if ( !b )
 			{
 				f = j;
 				b = true;
 			} else if ( j == (bi.bmWidth - 1) )
 			{
 				Rgn = CreateRectRgn( f, i, j, i + 1 );
 				CombineRgn( ResRgn, ResRgn, Rgn, RGN_OR );
 				b = false;
 			}
 		} else if ( b )
 		{
 			Rgn = CreateRectRgn( f, i, j, i + 1 );
 			CombineRgn( ResRgn, ResRgn, Rgn, RGN_OR );
 			b = false;
 		}
 	}
 
 	delete pBits;
 
 	return ResRgn;
 }

Update: Ниже представлена улучшенная версия функции, которая требует маску битмапа для TrueColor. В Win9x ширина маски битмапа  должна быть DWORD.

HRGN CreateRgnFromFile(HBITMAP hBmp, COLORREF color)
 {
 	// получаем размер маски
 	BITMAP bm = { 0 };
 	GetObject( hBmp, sizeof(BITMAP), &bm );
 
 	m_dwWidth	= bm.bmWidth;		// ширина bitmap
 	m_dwHeight	= bm.bmHeight;		// высота bitmap
 
 	// Распределяем буфер для маски
 	LPBYTE pBits = new BYTE[ bm.bmWidthBytes * bm.bmHeight ];
 	// заполняем буфер свойствами
 	BITMAPINFO bi = { 0 };
 	bi.bmiHeader.biSize	= sizeof( BITMAPINFOHEADER );
 	bi.bmiHeader.biBitCount	= bm.bmBitsPixel;
 	bi.bmiHeader.biHeight	= bm.bmHeight;
 	bi.bmiHeader.biWidth	= bm.bmWidth;
 	bi.bmiHeader.biPlanes	= bm.bmPlanes;
 	// заполняем биты буфера
 	HDC hdc = ::GetDC( NULL );
 	GetDIBits( hdc, hBmp, 0, bm.bmHeight, pBits, &bi, DIB_RGB_COLORS );
 	::ReleaseDC( NULL, hdc );
 
 	if ( bi.bmiHeader.biBitCount < 16 ) return NULL;
 
 	// сдвигаем биты и байт на пиксель (для сравнения цветов)
 	BYTE sb = 32 - bi.bmiHeader.biBitCount;
 	BYTE bpp = bi.bmiHeader.biBitCount >> 3;
 
 	LPBYTE pClr = (LPBYTE)&color;
 	// переставляем красный и синий компоненты
 	BYTE tmp = pClr[0]; pClr[0] = pClr[2]; pClr[2] = tmp;
 	// convert color if curent DC is 16-bit (5:5:5)
 	if ( bpp == 2 )	color = ((DWORD)(pClr[0] & 0xf8) >> 3) |
 				((DWORD)(pClr[1] & 0xf8) << 2) |
 				((DWORD)(pClr[2] & 0xf8) << 7);
 	// выравниваем цвет для сравнения
 	color <<= sb;
 
 	const DWORD RDHDR = sizeof(RGNDATAHEADER);
 	const DWORD MAXBUF = 40;	// размер одного блока в RECT-ах
 					// (т.e. MAXBUF*sizeof(RECT)
                                         // в байтах)
 	LPBYTE	pColor = pBits;
 	LPRECT	pRects;
 	DWORD	cBlocks = 0;		// кол-во распределённых блоков
 
 	INT	i, j;			// текущая позиция в маске картинки
 	INT	first = 0;		// левая координата текущей линии,
                                         // в которой была найдена маска
 	bool	wasfirst = false;	// устанавливается, если маска была
                                         // найдена в текущей линии
 	bool	ismask;			// устанавливается, если текущий
                                         // цвет является маской
 
 	// распределяем память для данных региона
 	RGNDATAHEADER* pRgnData = (RGNDATAHEADER*)new BYTE[ RDHDR +
                                  ++cBlocks * MAXBUF * sizeof(RECT) ];
 	memset( pRgnData, 0, RDHDR + cBlocks * MAXBUF * sizeof(RECT) );
 	// заполняем его по умолчанию
 	pRgnData->dwSize	= RDHDR;
 	pRgnData->iType		= RDH_RECTANGLES;
 	pRgnData->nCount	= 0;
 
 	for ( i = 0; i < bm.bmHeight; i++ )
 	for ( j = 0; j < bm.bmWidth; j++ )
 	{
 		// получаем цвет
 		ismask = *(DWORD*)pColor << sb != color;
 		// сдвиг указателя на следующий цвет
 		pColor += bpp;
 		// помещаем часть сканируемой линии как регион RECT,
                 // если прозрачный цвет найден после цвета маски либо
 		// цвет маски найден в конце маски изображения
 		if ( wasfirst && (ismask ^ (j < bm.bmWidth - 1)) )
 		{
 			// получаем смещение в массиве RECT
 			pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR);
 			// сохраняем текущий RECT
 			pRects[ pRgnData->nCount++ ] = CRect( first,
                                  bm.bmHeight - i - 1, j, bm.bmHeight - i );
 			// если буфер полон, то перераспределяем его
 			if ( pRgnData->nCount >= cBlocks * MAXBUF )
 			{
 				LPBYTE pRgnDataNew = new BYTE[ RDHDR +
                                        ++cBlocks * MAXBUF * sizeof(RECT) ];
 				memcpy( pRgnDataNew, pRgnData, RDHDR +
                                     (cBlocks - 1) * MAXBUF * sizeof(RECT));
 
 				delete pRgnData;
 				pRgnData = (RGNDATAHEADER*)pRgnDataNew;
 			}
 			wasfirst = false;
 		}
 		else if ( !wasfirst && ismask )	    // устанавливаем
                                                     // wasfirst когда
                                                     // маска найдена
 		{
 			first = j;
 			wasfirst = true;
 		}
 	}
 
 	delete pBits;
 
 	// создаём регион
 	HRGN hRgn = ExtCreateRegion( NULL, RDHDR +
                     pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData );
 
 	delete pRgnData;
 
 	return hRgn;
 }
 







<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU Проект ReactOS