【Code Art / C#】随机贝塞尔曲线效果测试


贝塞尔曲线是通过几个控制点来绘制曲线的一种方法。通过若干个贝塞尔曲线随机组合,然后随机移动每个控制点,会实现怎样的效果呢?

用这样简单粗暴的思路,写了以下绘制代码。

然后将画完的一帧做模糊处理,不擦除画布继续画一帧,然后用Timer循环绘制,便实现了如图所示的效果。


以下为随机绘制一帧的代码,如需要动画效果和如图所示的效果请参照以上思路自行实现。

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using sf = RandBezier.SystemFramework;

namespace RandBezier
{
    /// <summary>
    /// 贝塞尔节点结构
    /// </summary>
    public class RandPoint
    {
        public RandPoint()
        {
            this.X = sf.Rand.Next(0, sf.Win_Width);
            this.Y = sf.Rand.Next(0, sf.Win_Height);
            this.dx = sf.Rand.Next(-100, 100) * 1f / 100;
            this.dy = sf.Rand.Next(-100, 100) * 1f / 100;
            this.offset_dx = sf.Rand.Next(-100, 100) * 1f / 1000;
            this.offset_dy = sf.Rand.Next(-100, 100) * 1f / 1000;
        }

        public float X { get; set; }
        public float Y { get; set; }
        public float dx = 0f;
        public float dy = 0f;

        private float offset_dx = 0f;
        private float offset_dy = 0f;
        private int count = 0;

        /// <summary>
        /// 移动处理
        /// </summary>
        public void Do()
        {
            this.X += this.dx;
            if (this.X < 0 || this.X > sf.Win_Width)
            {
                this.dx = -this.dx;
                this.offset_dx = -this.offset_dx;
            }
            this.Y += this.dy;
            if (this.Y < 0  || this.Y > sf.Win_Height)
            {
                this.dy = -this.dy;
                this.offset_dy = -this.offset_dy;
            }
            this.dx += this.offset_dx;
            if (Math.Abs(this.dx) > 10)
            {
                this.offset_dx = -this.offset_dx;
            }
            this.dy += this.offset_dy;
            if (Math.Abs(this.dy) > 10)
            {
                this.offset_dy = -this.offset_dy;
            }
            if (this.count > 150)
            {
                this.count = 0;
                this.offset_dx = sf.Rand.Next(-100, 100) * 1f / 1000;
                this.offset_dy = sf.Rand.Next(-100, 100) * 1f / 1000;
            }
            this.count++;
        }
    }

    /// <summary>
    /// 颜色结构
    /// </summary>
    public class RandColor
    {
        private int min = 180;
        private int max = 255;

        public RandColor()
        {
            this.R = sf.Rand.Next(min, max);
            this.G = sf.Rand.Next(min, max);
            this.B = sf.Rand.Next(min, max);
            this.offset_r = sf.Rand.Next(-5, 5);
            this.offset_g = sf.Rand.Next(-5, 5);
            this.offset_b = sf.Rand.Next(-5, 5);
        }

        public int R { get; set; }
        public int G { get; set; }
        public int B { get; set; }

        private int offset_r = 0;
        private int offset_g = 0;
        private int offset_b = 0;
        private int count = 0;

        public void Do()
        {
            this.R += this.offset_r;
            if (this.R < min)
            {
                this.R = min;
                this.offset_r = -this.offset_r;
            }
            if (this.R > max)
            {
                this.R = max;
                this.offset_r = -this.offset_r;
            }
            this.G += this.offset_g;
            if (this.G < min)
            {
                this.G = min;
                this.offset_g = -this.offset_g;
            }
            if (this.G > max) 
            {
                this.G = max;
                this.offset_g = -this.offset_g;
            }
            this.B += this.offset_b;
            if (this.B < min)
            {
                this.B = min;
                this.offset_b = -this.offset_b;
            }
            if (this.B > max) 
            {
                this.B = max;
                this.offset_b = -this.offset_b;
            }
            if (this.count > 100)
            {
                this.count = 0;
                this.offset_r = sf.Rand.Next(-5, 5);
                this.offset_g = sf.Rand.Next(-5, 5);
                this.offset_b = sf.Rand.Next(-5, 5);
            }
            this.count++;
        }

        public Color GetColor()
        {
            return Color.FromArgb(this.R, this.G, this.B);
        }
    }

    /// <summary>
    /// 贝塞尔绘制器
    /// </summary>
    public class BezierDraw
    {
        private int Width = 800;
        private int Height = 600;
        private Graphics graphics = null;
        private Bitmap bmp_temp = null;
        private Bitmap bmp_back = null;
        private List<RandPoint> pointList;
        private List<PointF> pointDrawList;
        private RandColor randColor;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="g"></param>
        public BezierDraw(int width,int height,Graphics g)
        {
            this.Width = width;
            this.Height = height;
            this.graphics = g;
            this.bmp_temp = new Bitmap(width, height);
            this.bmp_back = new Bitmap(width, height);
            this.pointList = new List<RandPoint>();
            this.randColor = new RandColor();
            this.pointDrawList = new List<PointF>();
            for (int i = 0; i < 100; i++)
            {
                pointList.Add(new RandPoint());
            }
        }

        /// <summary>
        /// 处理
        /// </summary>
        public void Do()
        {
            if (randColor != null)
            {
                randColor.Do();
            }
            if (pointDrawList != null && pointList != null)
            {
                pointDrawList.Clear();
                foreach (RandPoint p in pointList)
                {
                    p.Do();
                    pointDrawList.Add(new PointF(p.X,p.Y));
                }
            }
        }

        private int count = 0;

        /// <summary>
        /// 画出
        /// </summary>
        public void Draw()
        {
            if (graphics != null && bmp_temp != null && randColor != null)
            {
                // 背景图
                Graphics gb = Graphics.FromImage(bmp_back);
                gb.FillRectangle(new SolidBrush(Color.Black), 0, 0, Width, Height);

                // 渐变
                if (count > 25)
                {
                    bmp_temp = BitmapCtrlOpacity(bmp_temp, 0.89f);
                    count = 0;
                }
                else
                {
                    bmp_temp = BitmapCtrlOpacity(bmp_temp, 0.95f);
                }
                count++;
                bmp_temp = BimapZoom(bmp_temp);
                // bmp_temp = GaussianBlur(bmp_temp);
                // bmp_temp = BitmapOpacity(bmp_temp, 0.95f);
                Graphics g = Graphics.FromImage(bmp_temp);
                g.SmoothingMode = SmoothingMode.AntiAlias;

                // 画曲线
                Pen pen = new Pen(randColor.GetColor());
                pen.Width = 1.5f;
                g.DrawBeziers(pen, pointDrawList.ToArray());
                
                // 画到背景上
                gb.DrawImage(bmp_temp, 0, 0);
                // 画到设备上
                graphics.DrawImage(bmp_back, 0, 0);
            }
        }

        public static Bitmap BimapZoom(Bitmap srcBitmap)
        {
            Bitmap bmp = new Bitmap(srcBitmap.Width, srcBitmap.Height);
            Bitmap bmp_temp = new Bitmap((int)(srcBitmap.Width / 2.5), (int)(srcBitmap.Height / 2.5));
            Graphics g = Graphics.FromImage(bmp_temp);
            g.SmoothingMode = SmoothingMode.HighSpeed;
            g.DrawImage(srcBitmap, 0, 0, bmp_temp.Width, bmp_temp.Height);
            g = Graphics.FromImage(bmp);
            g.SmoothingMode = SmoothingMode.HighSpeed;
            g.DrawImage(bmp_temp, 0, 0, srcBitmap.Width, srcBitmap.Height);
            return bmp;
        }

        /// <summary>
        /// 设置图像透明度
        /// </summary>
        /// <param name="srcImage">源图像</param>
        /// <param name="opacity">透明度</param>
        /// <returns>返回图像</returns>
        public static Bitmap BitmapCtrlOpacity(Bitmap srcImage, float opacity)
        {
            float[][] nArray ={ new float[] {1, 0, 0, 0, 0}, 
                new float[] {0, 1, 0, 0, 0}, 
                new float[] {0, 0, 1, 0, 0}, 
                new float[] {0, 0, 0, opacity, 0}, 
                new float[] {0, 0, 0, 0, 1}
                              };
            ColorMatrix matrix = new ColorMatrix(nArray);
            ImageAttributes attributes = new ImageAttributes();
            attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            Bitmap resultImage = new Bitmap(srcImage.Width, srcImage.Height);
            Graphics g = Graphics.FromImage(resultImage);
            g.SmoothingMode = SmoothingMode.HighSpeed;
            g.DrawImage(srcImage, new Rectangle(0, 0, srcImage.Width, srcImage.Height), 0, 0, srcImage.Width, srcImage.Height, GraphicsUnit.Pixel, attributes);
            //DrawImage(srcImage, ref resultImage, new Rectangle(0, 0, srcImage.Width, srcImage.Height), new Point(0, 0));
            g.Dispose();
            return resultImage;
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ls9512

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值