C#将图形快速处理成不规则区域

来源:互联网 发布:isis 剿灭 知乎 编辑:程序博客网 时间:2024/05/17 04:07

C#将图形快速处理成不规则区域

来源:
http://blog.sina.com.cn/u/589d32f5010009nf

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)

{

    //转贴请注明出处ZswangY37(wjhu111#21cn.com) 时间2007-05-25

    if (AImage == nullreturn null;

    Bitmap vBitmap = new Bitmap(AImage);

    BitmapData vBitmapData = vBitmap.LockBits(

        new Rectangle(00, 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];

    //头信息dwSize/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(216233236));

}


0 0
原创粉丝点击