您的位置:首页 > 其它

任意不规则形状的图片剪裁

2014-07-13 12:15 423 查看
转自:http://blog.csdn.net/lexiaoyao20/article/details/6607225

原理:根据选择的区域(区域的选择需要用到GraphicsPath),根据区域可以得到这部分区域的边境矩形,从而不需要循环整张图片,只需要循环边境矩形,将矩形中的选择区域复制到另一种图片,这样大大提高了效率。根据选择的区域,可以得到复制出位于GraphicsPath中的这部分图片,同时设置这部分图片为透明,同时还要设置另一种图片不在GraphicsPath内的区域为透明,这样看起来的效果就是从图片中扣出来的一样,意思和PhotoShop的套索工具差不多。

说得有点晕了,还是看效果图吧:(左边是剪裁出来的图)



 下面说说关键的代码。

方法一:像素级的处理,循环整张图片,一个一个像素复制出来,效率比较低。

[csharp] view
plaincopy

/// <summary>  

        /// 图片剪裁(像素级的处理,效率比较低)  

        /// </summary>  

        /// <param name="bitmap">原图</param>  

        /// <param name="path">选择的路径</param>  

        /// <param name="outputBitmap">输出的图片(即剪裁出来的图片)</param>  

        /// <returns></returns>  

        public static Bitmap BitmapCrop(Bitmap bitmap, GraphicsPath path, out Bitmap outputBitmap)  

        {  

            RectangleF rect = path.GetBounds();  

            int left = (int)rect.Left;  

            int top = (int)rect.Top;  

            int width = (int)rect.Width;  

            int height = (int)rect.Height;  

            Bitmap image = (Bitmap)bitmap.Clone();  

            outputBitmap = new Bitmap(width, height);  

            for (int i = left; i < left + width; i++)  

            {  

                for (int j = top; j < top + height; j++)  

                {  

                    //判断坐标是否在路径中  

                    if (path.IsVisible(i, j))  

                    {  

                        //复制原图区域的像素到输出图片  

                        outputBitmap.SetPixel(i - left , j - top , image.GetPixel(i, j));  

                        //设置原图这部分区域为透明  

                        image.SetPixel(i, j, Color.FromArgb(0, image.GetPixel(i, j)));  

                    }  

                    else  

                    {  

                        outputBitmap.SetPixel(i - left, j - top, Color.FromArgb(0, 255, 255, 255));                             

                    }  

                }  

            }  

            bitmap.Dispose();  

            return image;  

        }  

方法二:将图片锁定在内存中,在内存处理,效率得到提升。

[csharp] view
plaincopy

/// <summary>  

      /// 剪裁选定区域的图片  

      /// </summary>  

      /// <param name="bitmap">原图</param>  

      /// <param name="path">用户选定的区域</param>  

      /// <param name="outputBitmap">剪裁出来的图(输出图)</param>  

      /// <returns></returns>  

      public static Bitmap BitmapCrop(Bitmap bitmap, GraphicsPath path, out Bitmap outputBitmap)  

      {  

          Rectangle rect = Rectangle.Round(path.GetBounds());  

          outputBitmap = new Bitmap(rect.Width, rect.Height);  

          if (bitmap == null) return null;  

  

          Bitmap bmp = (Bitmap)bitmap.Clone();  

          bitmap.Dispose();  

          BitmapData data = bmp.LockBits(rect,  

              ImageLockMode.ReadWrite, bmp.PixelFormat);  

          BitmapData outData = outputBitmap.LockBits(new Rectangle(0, 0, rect.Width, rect.Height),  

              ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);  

          unsafe  

          {  

              byte* q = (byte*)outData.Scan0;  

              int offset = outData.Stride - rect.Width * 4;  

              int PixelSize = 4;  

              for (int y = rect.Top; y < rect.Top + rect.Height; y++)  

              {  

                  //每一行内存中的位置  

                  byte* row = (byte*)data.Scan0 + ((y - rect.Top) * data.Stride);  

                  for (int x = rect.Left; x < rect.Left + rect.Width; x++)  

                  {  

                      //判断坐标点是否在路径中  

                      //在路径中,则复制原图这部分给输出图,同时设置原图这部分透明  

                      //坐标点和内存中值的对应  

                      if (path.IsVisible(x, y))    

                      {  

                          q[0] = row[(x - rect.Left) * PixelSize];  

                          q[1] = row[(x - rect.Left) * PixelSize + 1];  

                          q[2] = row[(x - rect.Left) * PixelSize + 2];  

                          q[3] = row[(x - rect.Left) * PixelSize + 3];  

  

                          row[(x - rect.Left) * PixelSize + 3] = 0;  

                      }  

                      else //不在路径中,则设置输出图这部分为透明  

                      {  

                          q[3] = 0;  

                      }  

                      q += 4;  

                  }  

                  q += offset;  

              }  

          }  

          bmp.UnlockBits(data);  

          outputBitmap.UnlockBits(outData);  

  

          return bmp;  

      }  

 注意:因为有不安全代码,所以要设置项目的属性 ->生成,勾选允许不安全代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: