Это очень простая функция, создающая регион из 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; m_dwHeight= bm.bmHeight;
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;
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;
LPBYTEpColor = pBits; LPRECTpRects; DWORDcBlocks = 0;
INTi, j; INTfirst = 0;, // в которой была найдена маска boolwasfirst = false; boolismask;
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 ) { first = j; wasfirst = true; } }
delete pBits;
HRGN hRgn = ExtCreateRegion( NULL, RDHDR + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData );
delete pRgnData;
return hRgn; } |