博客
关于我
c# 图片带水纹波动
阅读量:413 次
发布时间:2019-03-06

本文共 13965 字,大约阅读时间需要 46 分钟。

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Runtime.InteropServices;using System.Drawing.Imaging;namespace myControl{    public struct DropData    {        public int x;        public int y;        public int radius;        public int height;    }     public partial class Form1 : Form    {               public Form1()        {            InitializeComponent();                        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);            this.SetStyle(ControlStyles.DoubleBuffer, true);            this.SetStyle(ControlStyles.ResizeRedraw, true);            this.SetStyle(ControlStyles.Selectable, true);            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);            this.SetStyle(ControlStyles.UserPaint, true);            Timer myWaterTimer = new Timer();            myWaterTimer.Interval = 50;            myWaterTimer.Tick += new EventHandler(myWaterTimer_Tick);            Timer myDropsTimer = new Timer();            myDropsTimer.Interval = 50000;            myDropsTimer.Tick += new EventHandler(myDropsTimer_Tick);        }        private void myDropsTimer_Tick(object sender, EventArgs e)        {            try            {                                this.myDropsTimer.Enabled = false;                int _percent = (int)(0.005 * (this.Width + this.Height));                int _dropsNumber = r.Next(_percent);                int _drop = 0;                for (int i = 0; i < _dropsNumber; i++)                {                    _drop = r.Next(drops.Length);                    DropWater(drops[_drop].x, drops[_drop].y, drops[_drop].radius, drops[_drop].height);                }                this.myDropsTimer.Interval = r.Next(15 * _percent) + 1;                this.myDropsTimer.Enabled = true;            }            catch { }        }        private void myWaterTimer_Tick(object sender, EventArgs e)        {            try            {                if (fastImage.IsLocked()) return;                this.myWaterTimer.Stop();                PaintWater();                this.myWaterTimer.Start();            }            catch { }        }        private static int bitmapWidth = 0;        private static int bitmapHeight = 0;        private static int bits = 4;        private static DropData[] drops;        private FastBitmap fastImage = null;        private FastBitmap originalImage = null;        public int currentHeightBuffer = 0;        public int newHeightBuffer = 0;        private byte[] bitmapOriginalBytes;        private Random r = new Random();        private static int[][][] waveHeight;        bool isLoaded = false;        private Image image;        private bool auto;        private int number;        private Timer myWaterTimer, myDropsTimer;        ///         /// 绘画的图片        ///         public Image Image        {            get { return image; }            set { image = value; }        }        ///         /// 自动产生        ///         public bool Auto        {            get { return auto; }            set { auto = value; }        }        ///         /// 源点数        ///         public int Number        {            get { return number; }            set { number = value; }        }        public void load()        {            try            {                isLoaded = true;                this.Width = image.Width;                this.Height = image.Height;                bitmapWidth = image.Width;                bitmapHeight = image.Height;                waveHeight = new int[bitmapWidth][][];                for (int i = 0; i < bitmapWidth; i++)                {                    waveHeight[i] = new int[bitmapHeight][];                    for (int j = 0; j < bitmapHeight; j++)                    {                        waveHeight[i][j] = new int[2];                    }                }                CreateBitmap();                if (auto)                {                    CreateWaterDrops();                    this.myWaterTimer.Enabled = true;                    this.myDropsTimer.Interval = 50;                    this.myDropsTimer.Enabled = true;                }                else                {                    this.MouseMove += new MouseEventHandler(myWaterWave_MouseMove);                }            }            catch { }        }        private void CreateBitmap()        {            originalImage = new FastBitmap((Bitmap)(image).Clone(), bits);            originalImage.LockBits();            fastImage = new FastBitmap((Bitmap)(image).Clone(), bits);            bitmapOriginalBytes = new byte[bits * fastImage.Width() * fastImage.Height()];            fastImage.LockBits();            Marshal.Copy(fastImage.Data().Scan0, bitmapOriginalBytes, 0, bitmapOriginalBytes.Length);            fastImage.Release();        }        private void DropWater(int x, int y, int radius, int height)        {            long _distance;            int _x;            int _y;            Single _ratio;            _ratio = (Single)((Math.PI / (Single)radius));            for (int i = -radius; i <= radius; i++)            {                for (int j = -radius; j <= radius; j++)                {                    _x = x + i;                    _y = y + j;                    if ((_x >= 0) && (_x <= bitmapWidth - 1) && (_y >= 0) && (_y <= bitmapHeight - 1))                    {                        _distance = (long)Math.Sqrt(i * i + j * j);                        if (_distance <= radius)                        {                            waveHeight[_x][_y][currentHeightBuffer] = (int)(height * Math.Cos((Single)_distance * _ratio));                        }                    }                }            }        }        private void PaintWater()        {            newHeightBuffer = (currentHeightBuffer + 1) % 2;            fastImage.LockBits();            byte[] _bufferBits = new byte[bits * fastImage.Width() * fastImage.Height()];            Marshal.Copy(fastImage.Data().Scan0, _bufferBits, 0, _bufferBits.Length);            int _offX;            int _offY;            for (int _x = 1; _x < bitmapWidth - 1; _x++)            {                for (int _y = 1; _y < bitmapHeight - 1; _y++)                {                    unchecked                    {                        waveHeight[_x][_y][newHeightBuffer] = ((                            waveHeight[_x - 1][_y][currentHeightBuffer] +                            waveHeight[_x - 1][_y - 1][currentHeightBuffer] +                            waveHeight[_x][_y - 1][currentHeightBuffer] +                            waveHeight[_x + 1][_y - 1][currentHeightBuffer] +                            waveHeight[_x + 1][_y][currentHeightBuffer] +                            waveHeight[_x + 1][_y + 1][currentHeightBuffer] +                            waveHeight[_x][_y + 1][currentHeightBuffer] +                            waveHeight[_x - 1][_y + 1][currentHeightBuffer]) >> 2)                        - waveHeight[_x][_y][newHeightBuffer];                    }                    waveHeight[_x][_y][newHeightBuffer] -= (waveHeight[_x][_y][newHeightBuffer] >> 5);                    _offX = ((waveHeight[_x - 1][_y][newHeightBuffer] - waveHeight[_x + 1][_y][newHeightBuffer])) >> 3;                    _offY = ((waveHeight[_x][_y - 1][newHeightBuffer] - waveHeight[_x][_y + 1][newHeightBuffer])) >> 3;                    if ((_offX == 0) && (_offY == 0)) continue;                    if (_x + _offX <= 0) _offX = -_x;                    if (_x + _offX >= bitmapWidth - 1) _offX = bitmapWidth - _x - 1;                    if (_y + _offY <= 0) _offY = -_y;                    if (_y + _offY >= bitmapHeight - 1) _offY = bitmapHeight - _y - 1;                    _bufferBits[bits * (_x + _y * bitmapWidth) + 0] = bitmapOriginalBytes[bits * (_x + _offX + (_y + _offY) * bitmapWidth) + 0];                    _bufferBits[bits * (_x + _y * bitmapWidth) + 1] = bitmapOriginalBytes[bits * (_x + _offX + (_y + _offY) * bitmapWidth) + 1];                    _bufferBits[bits * (_x + _y * bitmapWidth) + 2] = bitmapOriginalBytes[bits * (_x + _offX + (_y + _offY) * bitmapWidth) + 2];                }            }            Marshal.Copy(_bufferBits, 0, fastImage.Data().Scan0, _bufferBits.Length);            currentHeightBuffer = newHeightBuffer;            this.Invalidate();        }        private void CreateWaterDrops()        {            int _dropX;            int _dropY;            int _dropRadius;            int _height;            int _percent = (int)(0.0015 * (this.Width + this.Height));            drops = new DropData[number];            for (int i = 0; i < drops.Length; i++)            {                _dropX = r.Next(bitmapWidth);                _dropY = r.Next(bitmapHeight);                _height = r.Next(400);                _dropRadius = r.Next(4 * _percent);                if (_dropRadius < 4) _dropRadius = 4;                drops[i].x = _dropX;                drops[i].y = _dropY;                drops[i].radius = _dropRadius;                drops[i].height = _height;            }        }        private void myWaterWave_Paint(object sender, PaintEventArgs e)        {            try            {                if (isLoaded)                {                    fastImage.Release();                    e.Graphics.DrawImage(fastImage.Bitmap, 0, 0, fastImage.Width(), fastImage.Height());                }            }            catch { }        }        private void myWaterWave_MouseMove(object sender, MouseEventArgs e)        {            int dropX;            int dropY;            int dropRadius;            int height;            int percent = (int)(0.0015 * (this.Width + this.Height));            drops = new DropData[1];            dropX = e.X;            dropY = e.Y;            height = r.Next(400);            dropRadius = r.Next(4 * percent);            if (dropRadius < 4) dropRadius = 4;            drops[0].x = dropX;            drops[0].y = dropY;            drops[0].radius = dropRadius;            drops[0].height = height;            this.myWaterTimer.Enabled = true;            this.myDropsTimer.Interval = 50;            this.myDropsTimer.Enabled = true;        }        private void Form1_MouseLeave(object sender, EventArgs e)        {          this.myDropsTimer.Enabled = false;        }        private void Form1_Load(object sender, EventArgs e)        {        }    }    public unsafe class FastBitmap    {        public struct PixelData        {            public byte blue;            public byte green;            public byte red;            public byte alpha;        }        Bitmap Subject;        int SubjectWidth;        BitmapData bitmapData = null;        Byte* pBase = null;        bool isLocked = false;        int _bits = 0;        public FastBitmap(Bitmap SubjectBitmap, int bits)        {            this.Subject = SubjectBitmap;            _bits = bits;            try            {                //LockBits();            }            catch (Exception ex)            {                throw ex;            }        }        public void Release()        {            try            {                UnlockBits();            }            catch (Exception ex)            {                throw ex;            }        }        public Bitmap Bitmap        {            get            {                return Subject;            }        }        public void SetPixel(int X, int Y, Color Colour)        {            try            {                PixelData* p = PixelAt(X, Y);                p->red = Colour.R;                p->green = Colour.G;                p->blue = Colour.B;            }            catch (AccessViolationException ave)            {                throw (ave);            }            catch (Exception ex)            {                throw ex;            }        }        public Color GetPixel(int X, int Y)        {            try            {                PixelData* p = PixelAt(X, Y);                return Color.FromArgb((int)p->red, (int)p->green, (int)p->blue);            }            catch (AccessViolationException ave)            {                throw (ave);            }            catch (Exception ex)            {                throw ex;            }        }        public int Width() { return Subject.Width; }        public int Height() { return Subject.Height; }        public bool IsLocked() { return isLocked; }        public BitmapData Data() { return bitmapData; }        public void LockBits()        {            if (isLocked) return;            try            {                GraphicsUnit unit = GraphicsUnit.Pixel;                RectangleF boundsF = Subject.GetBounds(ref unit);                Rectangle bounds = new Rectangle((int)boundsF.X,                    (int)boundsF.Y,                    (int)boundsF.Width,                    (int)boundsF.Height);                SubjectWidth = (int)boundsF.Width * sizeof(PixelData);                if (SubjectWidth % _bits != 0)                {                    SubjectWidth = _bits * (SubjectWidth / _bits + 1);                }                if (_bits == 3)                    bitmapData = Subject.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);                else                    bitmapData = Subject.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);                pBase = (Byte*)bitmapData.Scan0.ToPointer();            }            finally            {                isLocked = true;            }        }        private PixelData* PixelAt(int x, int y)        {            return (PixelData*)(pBase + y * SubjectWidth + x * sizeof(PixelData));        }        private void UnlockBits()        {            if (bitmapData == null) return;            Subject.UnlockBits(bitmapData);            bitmapData = null;            pBase = null;            isLocked = false;        }    }}

 

转载地址:http://ukjuz.baihongyu.com/

你可能感兴趣的文章
开源项目在闲鱼、b 站上被倒卖?这是什么骚操作?
查看>>
Vue3发布半年我不学,摸鱼爽歪歪,哎~就是玩儿
查看>>
《实战java高并发程序设计》源码整理及读书笔记
查看>>
Java开源博客My-Blog(SpringBoot+Docker)系列文章
查看>>
程序员视角:鹿晗公布恋情是如何把微博搞炸的?
查看>>
Spring+SpringMVC+MyBatis+easyUI整合进阶篇(七)一次线上Mysql数据库崩溃事故的记录
查看>>
【JavaScript】动态原型模式创建对象 ||为何不能用字面量创建原型对象?
查看>>
ClickHouse源码笔记4:FilterBlockInputStream, 探寻where,having的实现
查看>>
Linux应用-线程操作
查看>>
多态体验,和探索爷爷类指针的多态性
查看>>
系统编程-进程间通信-无名管道
查看>>
记2020年初对SimpleGUI源码的阅读成果
查看>>
C语言实现面向对象方法学的GLib、GObject-初体验
查看>>
系统编程-进程-ps命令、进程调度、优先级翻转、进程状态
查看>>
为什么我觉得需要熟悉vim使用,难道仅仅是为了耍酷?
查看>>
一个支持高网络吞吐量、基于机器性能评分的TCP负载均衡器gobalan
查看>>
HDOJ2017_字符串统计
查看>>
高等软工第二次作业《需求分析阶段总结》
查看>>
404 Note Found 团队会议纪要
查看>>
CentOS安装Docker-ce并配置国内镜像
查看>>