本文共 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/