首页  编辑  

取得一张图片的不规则区域

Tags: /C#/图形图像/   Date Created:

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 ));

}