using System . Runtime . InteropServices;
[ DllImport ( "gdi32.dll" )]
public static extern IntPtr ExtCreateRegion( IntPtr lpXform, uint nCount,
ref byte lpRgnData);
public static int RGN_AND = 1 ;
public static int RGN_OR = 2 ;
public static int RGN_XOR = 3 ;
public static int RGN_DIFF = 4 ;
public static int RGN_COPY = 5 ;
public static int RGN_MIN = RGN_AND;
public static int RGN_MAX = RGN_COPY;
[ DllImport ( "gdi32.dll" )]
public static extern int CombineRgn( IntPtr hrgnDest, IntPtr hrgnSrc1, IntPtr hrgnSrc2,
int fnCombineMode);
[ DllImport ( "gdi32.dll" )]
public static extern bool DeleteObject( IntPtr hObject);
public Region ImageToRegion( Image AImage, Color ATransparent)
{
//
if (AImage == null ) return null ;
Bitmap vBitmap = new Bitmap (AImage);
BitmapData vBitmapData = vBitmap . LockBits(
new Rectangle ( 0 , 0 , vBitmap . Width, vBitmap . Height),
ImageLockMode . ReadOnly, PixelFormat . Format32bppRgb);
int vAddress = ( int )vBitmapData . Scan0;
int vOffset = vBitmapData . Stride - vBitmap . Width * 4 ; //
int h = vBitmap . Height, w = vBitmap . Width;
int vTransparent = ColorTranslator . ToWin32(ATransparent); //
int vAllocRect = ( 0x1000 - sizeof (uint) * 8 ) / sizeof (int); //
if (h * w < vAllocRect) vAllocRect = h * w;
Byte [] vBuffer = new byte [sizeof(uint) * 8 + sizeof (int) * 4 * vAllocRect];
//\iType\nCount\nRegSize
uint vCount = 0 ;
vBuffer[ 0 ] = sizeof ( uint ) * 8 ; //dwSize//
vBuffer[ 4 ] = 1 ; //iType//int RDH_RECTANGLES = 1;//
IntPtr vResult = IntPtr . Zero;
uint vPointer = sizeof ( uint ) * 8 ;
bool vWriteRect = false ;
bool vWriteAlways = false ;
for ( int y = 0 ; y < h; y ++ )
{
int vBlockStart = 0 ;
bool vLastMaskBit = false ;
for ( int x = 0 ; x < w; x ++ )
{
int i = Marshal . ReadInt32(( IntPtr )vAddress) & 0x00FFFFFF ;
if (vTransparent == i) //
{
if (vLastMaskBit)
vWriteRect = true ;
}
else
{
if ( ! vLastMaskBit)
{
vBlockStart = x;
vLastMaskBit = true ;
}
}
if (x == w - 1 )
{
if (y == h - 1 )
{
vWriteRect = true ;
vWriteAlways = true ;
}
else if (vLastMaskBit)
{
vWriteRect = true ;
}
x ++ ;
}
if (vWriteRect)
{
if (vLastMaskBit)
{
vCount ++ ;
WriteRect(vBuffer, ref vPointer,
new Rectangle (vBlockStart, y, x - vBlockStart, 1 ));
}
if (vCount == vAllocRect || vWriteAlways)
{
vBuffer[ 8 ] = ( byte )vCount;
vBuffer[ 9 ] = ( byte )(vCount >> 8 );
vBuffer[ 10 ] = ( byte )(vCount >> 16 );
vBuffer[ 11 ] = ( byte )(vCount >> 24 );
IntPtr hTemp = ExtCreateRegion( IntPtr . Zero,
sizeof ( uint ) * 8 + sizeof ( int ) * 4 * vCount,
ref vBuffer[ 0 ]);
if (vResult == IntPtr . Zero)
vResult = hTemp;
else
{
CombineRgn(vResult, vResult, hTemp, RGN_OR);
DeleteObject(hTemp);
}
vCount = 0 ;
vPointer = sizeof ( uint ) * 4 ;
vWriteAlways = false ;
}
vWriteRect = false ;
vLastMaskBit = false ;
}
vAddress += 4 ;
}
vAddress += vOffset;
}
vBitmap . UnlockBits(vBitmapData);
return Region . FromHrgn(vResult);
}
private void WriteRect( byte [] ARGNData , ref uint ptr , Rectangle r)
{
ARGNData[ptr] = ( byte )r . X;
ARGNData[ptr + 1 ] = ( byte )(r . X >> 8 );
ARGNData[ptr + 2 ] = ( byte )(r . X >> 16 );
ARGNData[ptr + 3 ] = ( byte )(r . X >> 24 );
ARGNData[ptr + 4 ] = ( byte )r . Y;
ARGNData[ptr + 5 ] = ( byte )(r . Y >> 8 );
ARGNData[ptr + 6 ] = ( byte )(r . Y >> 16 );
ARGNData[ptr + 7 ] = ( byte )(r . Y >> 24 );
ARGNData[ptr + 8 ] = ( byte )r . Right;
ARGNData[ptr + 9 ] = ( byte )(r . Right >> 8 );
ARGNData[ptr + 10 ] = ( byte )(r . Right >> 16 );
ARGNData[ptr + 11 ] = ( byte )(r . Right >> 24 );
ARGNData[ptr + 12 ] = ( byte )r . Bottom;
ARGNData[ptr + 13 ] = ( byte )(r . Bottom >> 8 );
ARGNData[ptr + 14 ] = ( byte )(r . Bottom >> 16 );
ARGNData[ptr + 15 ] = ( byte )(r . Bottom >> 24 );
ptr += 16 ;
}
private void button1_Click( object sender , EventArgs e)
{
Region = ImageToRegion(pictureBox1 . Image, Color . FromArgb( 216 , 233 , 236 ));
}