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


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

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

    下面说说关键的代码。

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

    View Code

    方法二:指针法,效率得到提升。

    复制代码
      /// <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;
    }
     
    复制代码

    注意:因为有不安全代码,所以要设置项目的属性 ->生成,勾选允许不安全代码。

  • 相关阅读:
    HDU 4291 A Short problem 第37届ACM/ICPC 成都赛区网络赛1004题 (找规律,取模求循环节)
    POJ 1276 Cash Machine(多重背包)
    HDU 4296 Buildings 第37届ACM/ICPC 成都赛区网络赛1009题 (贪心)
    POJ 2392 Space Elevator (多重背包)
    Mysql配置SSL
    error C2471: cannot update program database vc90.pdb
    Android 总结 转载
    MAX SDK的INode的变换矩阵,以及Object的一些常识
    C++游戏开发需要阅读的书籍
    游戏程序员养成计划
  • 原文地址:https://www.cnblogs.com/Alex80/p/4211160.html
Copyright © 2020-2023  润新知