⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 effect.common.cs

📁 一个C#开发的类似PHOTOSHOP的软件,用到了很多图形算法.
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace PhotoSprite.ImageProcessing
{
  /// <summary>
  /// 滤镜特效类
  /// </summary>
  public partial class Effect : ImageInfo
  {
    /// <summary>
    /// 八方向枚举
    /// </summary>
    public enum Direction : int
    {
      /// <summary>
      /// 北,North
      /// </summary>
      N = 1,

      /// <summary>
      ///  东北,North east
      /// </summary>
      NE = 2,

      /// <summary>
      /// 东,East
      /// </summary>
      E = 3,

      /// <summary>
      /// 东南,South east
      /// </summary>
      SE = 4,

      /// <summary>
      /// 南,South
      /// </summary>
      S = 5,

      /// <summary>
      /// 西南,South west
      /// </summary>
      SW = 6,

      /// <summary>
      /// 西,West
      /// </summary>
      W = 7,

      /// <summary>
      /// 西北,North west
      /// </summary>
      NW = 8
    }


    /************************************************************
     * 
     * 平滑、模糊、锐化、浮雕、杂点
     * 
     ************************************************************/


    /// <summary>
    /// 对图像进行平滑处理
    /// </summary>
    /// <param name="b">位图流</param>
    /// <returns></returns>
    public Bitmap Smooth(Bitmap b)
    {
      //    1  1  1
      //    1  1  1
      //    1  1  1 / 9
      Matrix3x3 m = new Matrix3x3();
      m.Init(1);
      m.Scale = 9;

      return m.Convolute(b);
    } // end of Smooth


    /// <summary>
    /// 对图像采用高斯模板进行模糊处理
    /// </summary>
    /// <param name="b">位图流</param>
    /// <returns></returns>
    public Bitmap GaussBlur(Bitmap b)
    {
      //    1  2  1
      //    2  4  2
      //    1  2  1 / 16
      Matrix3x3 m = new Matrix3x3();
      m.Init(1);
      m.TopMid = m.MidLeft = m.MidRight = m.BottomMid = 2;
      m.Center = 4;
      m.Scale = 16;

      return m.Convolute(b);
    } // end of GaussBlur


    /// <summary>
    /// 运动模糊
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="angle">角度方向[0, 360]</param>
    /// <param name="distance">距离[1, 200]</param>
    /// <returns></returns>
    public Bitmap MotionBlur(Bitmap b, int angle, int distance)
    {
      angle %= 360;

      if (distance < 1) distance = 1;
      if (distance > 200) distance = 200;

      // 弧度、距离
      double radian = ((double)angle + 180.0) * Math.PI / 180.0;
      int dx = Convert.ToInt32((double)distance * Math.Cos(radian));
      int dy = Convert.ToInt32((double)distance * Math.Sin(radian));

      // 首点、尾点
      Point start = new Point(-dx / 2, dy / 2);
      Point end = new Point(dx / 2, -dy / 2);

      // 获取由首尾点组成的线段中的所有点的集合
      Point[] points = Function.GetLinePoints(start, end);

      int width = b.Width;
      int height = b.Height;

      // 目标图像
      Bitmap dstImage = new Bitmap(width, height);

      BitmapData srcData = b.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
      BitmapData dstData = dstImage.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

      int stride = srcData.Stride;
      System.IntPtr srcScan0 = srcData.Scan0;
      System.IntPtr dstScan0 = dstData.Scan0;
      int offset = stride - width * BPP;

      unsafe
      {
        byte* src = (byte*)srcScan0;
        byte* dst = (byte*)dstScan0;

        int X = 0, Y = 0;

        for (int y = 0; y < height; y++)
        {
          for (int x = 0; x < width; x++)
          {
            long bSum = 0;
            long gSum = 0;
            long rSum = 0;
            long aSum = 0;
            int div = 1;
            int validPoint = 0;

            foreach (Point point in points)
            {
              X = x + point.X;
              Y = y + point.Y;

              if ((X >= 0 && X < width) && (Y >= 0 && Y < height))
              {
                src = (byte*)srcScan0 + Y * stride + X * BPP;

                if (src[3] > 0)
                {
                  bSum += src[0] * src[3]; // B * A
                  gSum += src[1] * src[3]; // G * A
                  rSum += src[2] * src[3]; // R * A
                  aSum += src[3];          // A
                  div += src[3];
                }

                validPoint++;
              }
            } // point

            dst[3] = (byte)(aSum /= validPoint);
            dst[2] = (byte)(rSum /= div);
            dst[1] = (byte)(gSum /= div);
            dst[0] = (byte)(bSum /= div);

            dst += BPP;
          } // x

          dst += offset;
        } // y
      }

      b.UnlockBits(srcData);
      dstImage.UnlockBits(dstData);

      b.Dispose();

      return dstImage;
    } // end of MotionBlur


    /// <summary>
    /// 径向模糊
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="angle">径向角度[0, 360]</param>
    /// <returns></returns>
    public Bitmap RadialBlur(Bitmap b, int angle)
    {
      // 角度、弧度
      angle %= 360;
      double radian = (double)angle * Math.PI / 180.0;
      double radian2 = radian * radian;

      int width = b.Width;
      int height = b.Height;

      int midX = width / 2;
      int midY = height / 2;

      // 目标图像
      Bitmap dstImage = (Bitmap)b.Clone();

      BitmapData srcData = b.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
      BitmapData dstData = dstImage.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

      int stride = srcData.Stride;
      System.IntPtr srcScan0 = srcData.Scan0;
      System.IntPtr dstScan0 = dstData.Scan0;
      int offset = stride - width * BPP;

      unsafe
      {
        byte* src = (byte*)srcScan0;
        byte* dst = (byte*)dstScan0;

        int alpha, red, green, blue;
        int validPoint;
        int X = 0, Y = 0;
        double xOffset, yOffset, xOffsetCCW, yOffsetCCW, xOffsetCW, yOffsetCW;

        for (int y = 0; y < height; y++)
        {
          for (int x = 0; x < width; x++)
          {
            // 初始化颜色统计变量
            alpha = dst[3];
            red   = dst[2] * dst[3];
            green = dst[1] * dst[3];
            blue  = dst[0] * dst[3];
            validPoint = 1;

            xOffsetCCW = xOffsetCW = x - midX;
            yOffsetCCW = yOffsetCW = y - midY;

            for (int i = 0; i < 64; i++)
            {
              // 逆时针(正向)偏移
              xOffset = xOffsetCCW;
              yOffset = yOffsetCCW;
              xOffsetCCW = xOffset - radian * yOffset / 64.0 - radian2 * xOffset / 8192.0;
              yOffsetCCW = yOffset + radian * xOffset / 64.0 - radian2 * yOffset / 8192.0;

              X = (int)xOffsetCCW + midX;
              Y = (int)yOffsetCCW + midY;

              if ((X >= 0 && X < width) && (Y >= 0 && Y < height))
              {
                src = (byte*)srcScan0 + Y * stride + X * BPP;

                alpha += src[3];          // A
                red   += src[2] * src[3]; // R * A
                green += src[1] * src[3]; // G * A
                blue  += src[0] * src[3]; // B * A
                validPoint++;
              }

              // 顺时针(反向)偏移
              xOffset = xOffsetCW;
              yOffset = yOffsetCW;
              xOffsetCW = xOffset + radian * yOffset / 64.0 - radian2 * xOffset / 8192.0;
              yOffsetCW = yOffset - radian * xOffset / 64.0 - radian2 * yOffset / 8192.0;

              X = (int)xOffsetCW + midX;
              Y = (int)yOffsetCW + midY;

              if ((X >= 0 && X < width) && (Y >= 0 && Y < height))
              {
                src = (byte*)srcScan0 + Y * stride + X * BPP;

                alpha += src[3];          // A
                red   += src[2] * src[3]; // R * A
                green += src[1] * src[3]; // G * A
                blue  += src[0] * src[3]; // B * A
                validPoint++;
              }
            } // i

            blue  = blue  / alpha;
            green = green / alpha;
            red   = red   / alpha;
            alpha = alpha / validPoint;

            if (alpha > 255) alpha = 255;
            if (red   > 255) red   = 255;
            if (green > 255) green = 255;
            if (blue  > 255) blue  = 255;

            dst[3] = (byte)alpha;
            dst[2] = (byte)red;
            dst[1] = (byte)green;
            dst[0] = (byte)blue;

            dst += BPP;
          } // x

          dst += offset;
        } // y
      }

      b.UnlockBits(srcData);
      dstImage.UnlockBits(dstData);

      b.Dispose();

      return dstImage;
    } // end of RadialBlur


    /// <summary>
    /// 对图像进行锐化处理
    /// </summary>
    /// <param name="b">位图流</param>
    /// <returns></returns>
    public Bitmap Sharpen(Bitmap b)
    {
      //    0 -1  0
      //   -1  5 -1
      //    0 -1  0 / 1
      Matrix3x3 m = new Matrix3x3();
      m.Init(0);
      m.Center = 5;
      m.TopMid = m.MidLeft = m.MidRight = m.BottomMid = -1;
      m.Scale = 1;

      return m.Convolute(b);
    } // end of Sharpen


    /// <summary>
    /// 对图像进行加强锐化处理
    /// </summary>
    /// <param name="b">位图流</param>
    /// <returns></returns>
    public Bitmap SharpenMore(Bitmap b)
    {
      //   -1 -1 -1
      //   -1  9 -1
      //   -1 -1 -1 / 1
      Matrix3x3 m = new Matrix3x3();
      m.Init(-1);
      m.Center = 9;

      return m.Convolute(b);
    } // end of SharpenMore


    /// <summary>
    /// 对图像进行锐化处理
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="degree">锐化度[1, 100]</param>
    /// <returns></returns>
    public Bitmap Sharpen(Bitmap b, int degree)
    {
      if (degree < 1) degree = 1;
      if (degree > 100) degree = 100;

      int width = b.Width;
      int height = b.Height;

      //   -1 -1 -1
      //   -1  8 -1
      //   -1 -1 -1 / 1
      Matrix3x3 m = new Matrix3x3();
      m.Init(-1);
      m.Center = 8;
      Bitmap dstImage = m.Convolute((Bitmap)b.Clone());

      BitmapData srcData = b.LockBits(new Rectangle(0, 0, width, height), 
        ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
      BitmapData dstData = dstImage.LockBits(new Rectangle(0, 0, width, height), 
        ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

      unsafe
      {
        byte* src = (byte*)srcData.Scan0;
        byte* dst = (byte*)dstData.Scan0;
        int offset = srcData.Stride - width * BPP;

        int pixel = 0;

        for (int y = 0; y < height; y++)
        {
          for (int x = 0; x < width; x++)
          {
            // 处理 B, G, R 三分量,不考虑 A 分量
            for (int i = 0; i < 3; i++)
            {
              pixel = src[i] + dst[i] * degree / 10;

              if (pixel < 0) pixel = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -