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

📄 effect.extend.cs

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

    /// <summary>
    /// 对图像进行波浪特效处理
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="degree">波浪振幅[1, 32]</param>
    /// <returns></returns>
    public Bitmap Wave(Bitmap b, int degree)
    {
      if (degree < 1) degree = 1;
      if (degree > 32) degree = 32;

      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.WriteOnly, 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, Y;
        // 圆周率 2*pi
        double PI2 = Math.PI * 2.0;

        for (int y = 0; y < height; y++)
        {
          for (int x = 0; x < width; x++)
          {
            X = (int)(degree * Math.Sin(PI2 * y / 128.0)) + x;
            Y = (int)(degree * Math.Cos(PI2 * x / 128.0)) + y;

            // 边界约束
            if (X < 0) X = 0;
            if (X >= width) X = width - 1;
            if (Y < 0) Y = 0;
            if (Y >= height) Y = height - 1;

            src = (byte*)srcScan0 + Y * stride + X * BPP;

            dst[3] = src[3]; // A
            dst[2] = src[2]; // R
            dst[1] = src[1]; // G
            dst[0] = src[0]; // B

            dst += BPP;
          } // x
          dst += offset;
        } // y
      }

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

      b.Dispose();

      return dstImage;
    } // end of Wave


    /// <summary>
    /// 对图像进行摩尔纹特效处理
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="degree">强度[1, 16]</param>
    /// <returns></returns>
    public Bitmap MoireFringe(Bitmap b, int degree)
    {
      if (degree < 1) degree = 1;
      if (degree > 16) degree = 16;

      int width = b.Width;
      int height = b.Height;
      int midX = width / 2;
      int midY = height / 2;

      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.WriteOnly, 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, Y;
        int offsetX, offsetY;

        // 弧度、半径
        double radian, radius;

        for (int y = 0; y < height; y++)
        {
          for (int x = 0; x < width; x++)
          {
            // 当前点与图像中心点的偏移量
            offsetX = x - midX;
            offsetY = y - midY;

            // 弧度
            radian = Math.Atan2(offsetX, offsetY);

            // 半径
            radius = Math.Sqrt(offsetX * offsetX + offsetY * offsetY);

            // 映射实际像素点
            X = (int)(radius * Math.Sin(radian + degree * radius));
            Y = (int)(radius * Math.Sin(radian + degree * radius));

            // 边界约束
            if (X < 0) X = 0;
            if (X >= width) X = width - 1;
            if (Y < 0) Y = 0;
            if (Y >= height) Y = height - 1;

            src = (byte*)srcScan0 + Y * stride + X * BPP;

            dst[3] = src[3]; // A
            dst[2] = src[2]; // R
            dst[1] = src[1]; // G
            dst[0] = src[0]; // B

            dst += BPP;
          } // x
          dst += offset;
        } // y
      }

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

      // 将处理后的纹理图与原图像进行色彩混合
      return Inosculate(b, dstImage, 128);
    } // end of MoireFringe


    /************************************************************
     * 
     * 扩散、查找边缘、照亮边缘、灯光、马赛克、油画、曝光
     * 
     ************************************************************/


    /// <summary>
    /// 扩散
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="degree">扩散幅度[1, 32]</param>
    /// <returns></returns>
    public Bitmap Diffuse(Bitmap b, int degree)
    {
      if (degree < 1) degree = 1;
      if (degree > 32) degree = 32;

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

      // 目标图像
      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;

        Random myRand = new Random();
        int X, Y;

        for (int y = 0; y < height; y++)
        {
          for (int x = 0; x < width; x++)
          {
            // 获取当前像素点周围的一随机点
            X = x + myRand.Next(-degree, degree);
            Y = y + myRand.Next(-degree, degree);

            // 如果越界,则用图像边界上的点代替
            if (X < 0) X = 0;
            if (X >= width) X = width - 1;
            if (Y < 0) Y = 0;
            if (Y >= height) Y = height - 1;

            // 指向源图像的随机点
            src = (byte*)srcScan0 + (Y * stride) + (X * BPP);

            dst[3] = src[3];
            dst[2] = src[2];
            dst[1] = src[1];
            dst[0] = src[0];

            dst += BPP;
          } // x
          dst += offset;
        } // y
      }

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

      b.Dispose();

      return dstImage;
    } // end of Diffuse


    /// <summary>
    /// 对图像进行查找边缘处理
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="angle">角度[0, 360]</param>
    /// <returns></returns>
    public Bitmap FindEdge(Bitmap b, int angle)
    {
      // 角度转弧度
      double radian = (double)angle * 2.0 * Math.PI / 360.0;

      // 每一权的弧度间隔
      double pi4 = Math.PI / 4.0;

      // 对图像进行卷积变换
      Matrix3x3 m = new Matrix3x3();

      m.TopLeft = Convert.ToInt32(Math.Cos(radian + pi4) * 256);
      m.TopMid = Convert.ToInt32(Math.Cos(radian + 2.0 * pi4) * 256);
      m.TopRight = Convert.ToInt32(Math.Cos(radian + 3.0 * pi4) * 256);

      m.MidLeft = Convert.ToInt32(Math.Cos(radian) * 256);
      m.Center = 0;
      m.MidRight = Convert.ToInt32(Math.Cos(radian + 4.0 * pi4) * 256);

      m.BottomLeft = Convert.ToInt32(Math.Cos(radian - pi4) * 256);
      m.BottomMid = Convert.ToInt32(Math.Cos(radian - 2.0 * pi4) * 256);
      m.BottomRight = Convert.ToInt32(Math.Cos(radian - 3.0 * pi4) * 256);

      m.Scale = 256;

      b = m.Convolute(b);

      // 对图像进行负像处理
      Adjustment a = new Adjustment();
      b = a.Invert(b);

      return b;
    } // end of FindEdge


    /// <summary>
    /// 照亮边缘
    /// </summary>
    /// <param name="b">位图流</param>
    /// <returns></returns>
    public Bitmap GlowingEdge(Bitmap b)
    {
      int width = b.Width;
      int height = b.Height;

      BitmapData data = b.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

      // 图像实际处理区域
      // 不考虑最右 1 列,和最下 1 行
      int rectTop = 0;
      int rectBottom = height - 1;
      int rectLeft = 0;
      int rectRight = width - 1;

      unsafe
      {
        int stride = data.Stride;
        int offset = stride - width * BPP;

        byte* p = (byte*)data.Scan0;
        byte* bottom = p + stride;
        byte* right = p + BPP;

        int pixel;

        for (int y = rectTop; y < rectBottom; y++)
        {
          for (int x = rectLeft; x < rectRight; x++)
          {
            // 指向当前点下方像素点
            bottom = p + stride;

            // 指向当前点右边像素点
            right = p + BPP;

            for (int i = 0; i < 3; i++)
            {
              pixel = 
                (p[i] - bottom[i]) * (p[i] - bottom[i]) + 
                (p[i] - right[i]) * (p[i] - right[i]);
              pixel = (int)(Math.Sqrt(pixel) * 2);

              if (pixel < 0) pixel = 0;
              if (pixel > 255) pixel = 255;

              p[i] = (byte)pixel;
            } // i

            // 向后移一像素
            p += BPP;
          } // x

          // 移向下一行
          // 这里得注意要多移 1 列,因最右列不必处理
          p += offset + BPP;
        } // y
      }

      b.UnlockBits(data);

      return b;
    } // end of GlowingEdge


    /// <summary>
    /// 灯光
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="power">光照强度</param>
    /// <returns></returns>
    public Bitmap Lighting(Bitmap b, int power)
    {
      int width = b.Width;
      int height = b.Height;

      // 光源中心点 X, Y 坐标
      int x0 = width / 2;
      int y0 = height / 2;

      // 光源辐射半径
      int radius = (int)Math.Sqrt(x0 * x0 + y0 * y0);

      BitmapData data = b.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

      unsafe
      {
        byte* p = (byte*)data.Scan0;
        int offset = data.Stride - width * BPP;

        int pixel, brightness;

        int distance, squareDistance;
        int squareRadius = radius * radius;

        for (int y = 0; y < height; y++)
        {
          for (int x = 0; x < width; x++)
          {
            // 求当前点与光源中心点的距离
            squareDistance = (x - x0) * (x - x0) + (y - y0) * (y - y0);

            if (squareDistance < squareRadius)
            {
              distance = (int)Math.Sqrt(squareDistance);

              // 当前点的光照强度
              brightness = power * (radius - distance) / radius;

              for (int i = 0; i < 3; i++)
              { 
                pixel = p[i] + brightness;
                if (pixel > 255) pixel = 255;
                p[i] = (byte)pixel;
              } // i
            }

            p += BPP;
          } // x

          p += offset;
        } // y
      }

      b.UnlockBits(data);

      return b;
    } // end of Lighting


    /// <summary>
    /// 对图像进行马赛克特效处理
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="degree">块大小[1, 32]</param>
    /// <returns></returns>
    public Bitmap Mosaic(Bitmap b, int degree)
    {
      if (degree < 1) degree = 1;
      if (degree > 32) degree = 32;

      // 块大小
      int block = degree;

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

      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.WriteOnly, PixelFormat.Format32bppArgb);

      int srcStride = srcData.Stride;
      int dstStride = dstData.Stride;

      System.IntPtr srcScan0 = srcData.Scan0;
      System.IntPtr dstScan0 = dstData.Scan0;

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

        // 方块累加和
        int sum = 0;

        // 方块积
        int product = block * block;

        byte brightness = 0;

        for (int y = 0; y < height; y += block)
        {
          for (int x = 0; x < width; x += block)
          {
            // 处理 B, G, R 三分量,不考虑 A 分量
            for (int i = 0; i < 3; i++)
            {
              // 求小块内的亮度平均值
              sum = 0;
              for (int yB = 0; yB < block && (y + yB) < height; yB++)
              {
                for (int xB = 0; xB < block && (x + xB) < width; xB++)
                {
                  src = (byte*)srcScan0 + ((y + yB) * srcStride) + ((x + xB) * BPP);

                  sum += src[i];
                } // xB
              } // yB
              brightness = (byte)(sum / product);

              // 将亮度值赋予目标图像
              for (int yB = 0; yB < block && (y + yB) < height; yB++)
              {
                for (int xB = 0; xB < block && (x + xB) < width; xB++)
                {
                  dst = (byte*)dstScan0 + ((y + yB) * dstStride) + ((x + xB) * BPP);

                  dst[i] = brightness;
                } // xB
              } // yB
            } // i
          } // x
        } // y
      }

⌨️ 快捷键说明

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