30种图像动画特效算法(C#多线程版)(中)
2011-01-06 16:54
281 查看
这是截屏动画效果:
这次是(中),共10种特效:
源程序没有必要解释了,当初编写的时候我就加了非常详细的注释,只要你又一定的.NET基础,应该完全可以读懂!
这里是本文的最后一部分:http://mengliao.blog.51cto.com/876134/473214
这次是(中),共10种特效:
#region 随机竖条 // 原理:将图像分成宽度相等的列,然后随机选择每一列并从上到下显示 private void Animator11() { const float lineWidth = 40; // 竖条宽度 const int stepCount = 12; // 竖条每次前进量 try { OnDrawStarted(this, EventArgs.Empty); ClearBackground(); Random rnd = new Random(); // 随机数类 // 生成每个列随机显示的次序 int[] colIndex = new int[(int)Math.Ceiling(bmp.Width / lineWidth)]; int index = 1; // 数组索引 // 数组被自动初始化为0,因此可以通过判断其中的元素是否为0而得知该位置是否产生了随机数 // 为了区别自动初始化的元素值,index从1开始 do { int s = rnd.Next(colIndex.Length); if (colIndex[s] == 0) { colIndex[s] = index++; } } while (index <= colIndex.Length); // 按照上面随机生成的次序逐一显示每个竖条 for (int i = 0; i < colIndex.Length; i++) { for (int y = 0; y < bmp.Height; y += stepCount) { RectangleF rect = new RectangleF((colIndex[i] - 1) * lineWidth, y, lineWidth, stepCount); dc.DrawImage(bmp, rect, rect, GraphicsUnit.Pixel); Thread.Sleep(1 * delay); ShowBmp(rect); } Thread.Sleep(10 * delay); } } catch (Exception ex) { ShowError(ex.Message); } finally { OnDrawCompleted(this, EventArgs.Empty); } } #endregion #region 随机拉丝 // 原理:每次随机显示图像的一个像素行 private void Animator12() { try { OnDrawStarted(this, EventArgs.Empty); ClearBackground(); Random rnd = new Random(); // 随机数类 // 生成每个像素行的显示次序 int[] rowIndex = new int[bmp.Height]; int index = 1; // 数组索引 do { int s = rnd.Next(rowIndex.Length); if (rowIndex[s] == 0) { rowIndex[s] = index++; } } while (index <= rowIndex.Length); // 按照上面随机生成的次序逐一显示每个像素行 for (int i = 0; i < rowIndex.Length; i++) { RectangleF rect = new RectangleF(0, (rowIndex[i] - 1), bmp.Width, 1); dc.DrawImage(bmp, rect, rect, GraphicsUnit.Pixel); ShowBmp(rect); Thread.Sleep(1 * delay); } } catch (Exception ex) { ShowError(ex.Message); } finally { OnDrawCompleted(this, EventArgs.Empty); } } #endregion #region 垂直对切 // 原理:由图像中心向分左右两半分别向上下两个方向显示,到达边缘后按同样方向补齐另外的部分 private void Animator13() { const int stepCount = 4; // 上下前进的增量像素,应能被高度整除 try { OnDrawStarted(this, EventArgs.Empty); ClearBackground(); // 第一次循环,左半部分从垂直中心向上显示,右半部分从垂直中心向下显示 for (int y = 0; y <= bmp.Height / 2; y += stepCount) { // 左半部分 Rectangle rectLeft = new Rectangle(0, bmp.Height / 2 - y - stepCount, bmp.Width / 2, stepCount); dc.DrawImage(bmp, rectLeft, rectLeft, GraphicsUnit.Pixel); // 右半部分 Rectangle rectRight = new Rectangle(bmp.Width / 2, bmp.Height / 2 + y, bmp.Width / 2, stepCount); dc.DrawImage(bmp, rectRight, rectRight, GraphicsUnit.Pixel); ShowBmp(Rectangle.Union(rectLeft, rectRight)); Thread.Sleep(10 * delay); } // 第二次循环,左半部分从底边向上显示,右半部分从顶边向下显示 for (int y = 0; y <= bmp.Height / 2; y += stepCount) { // 左半部分 Rectangle rectLeft = new Rectangle(0, bmp.Height - y - stepCount, bmp.Width / 2, stepCount); dc.DrawImage(bmp, rectLeft, rectLeft, GraphicsUnit.Pixel); // 右半部分 Rectangle rectRight = new Rectangle(bmp.Width / 2, y, bmp.Width / 2, stepCount); dc.DrawImage(bmp, rectRight, rectRight, GraphicsUnit.Pixel); ShowBmp(Rectangle.Union(rectLeft, rectRight)); Thread.Sleep(10 * delay); } } catch (Exception ex) { ShowError(ex.Message); } finally { OnDrawCompleted(this, EventArgs.Empty); } } #endregion #region 随机分块 // 原理:框像分割为相等的正方块,然后逐个随机显示其中之一,直到全部显示完成 private void Animator14() { const float blockSize = 50; // 分块尺寸,如果该尺寸为4到6时,显示效果为随机图点 try { OnDrawStarted(this, EventArgs.Empty); ClearBackground(); Random rnd = new Random(); // 随机数类 // 定义二维数组,对应每个分块,其中保存该块的位置索引(基于总块数) int[,] blockIndex = new int[(int)Math.Ceiling(bmp.Width / blockSize), (int)Math.Ceiling(bmp.Height / blockSize)]; // 生成随机快坐标,并填充顺序号 int s = 1; // 分块次序(从左到右,从上到下) do { int x = rnd.Next(blockIndex.GetLength(0)); int y = rnd.Next(blockIndex.GetLength(1)); if (blockIndex[x, y] == 0) { blockIndex[x, y] = s++; } } while (s <= blockIndex.GetLength(0) * blockIndex.GetLength(1)); // 按照上面随机生成的次序逐一显示所有分块 for (int x = 0; x < blockIndex.GetLength(0); x++) { for (int y = 0; y < blockIndex.GetLength(1); y++) { // blockIndex[x, y]中保存的是分块的显示次序,可以将其转换为对应的坐标 RectangleF rect = new RectangleF(((blockIndex[x, y] - 1) % blockIndex.GetLength(0)) * blockSize, ((blockIndex[x, y] - 1) / blockIndex.GetLength(0)) * blockSize, blockSize, blockSize); dc.DrawImage(bmp, rect, rect, GraphicsUnit.Pixel); ShowBmp(rect); Thread.Sleep(10 * delay); } } } catch (Exception ex) { ShowError(ex.Message); } finally { OnDrawCompleted(this, EventArgs.Empty); } } #endregion #region 对角闭幕 // 原理:每次绘制所有图像内容,然后将不可见的区域生成闭合GraphicsPath并用背景色填充该区域 private void Animator15() { const int stepCount = 4; // y轴的增量像素,应能被高度整除 try { OnDrawStarted(this, EventArgs.Empty); ClearBackground(); // 左上角坐标p0(x0, y0)从左到右,p1(x1, y1)从上到下 // 右下角坐标p2(x2, y2)从右到左,p3(x3, y3)从下到上 // 这四个点与左下角点和右上角点构成不可见区域 PointF p0 = new Point(0, 0); PointF p1 = new Point(0, 0); PointF p2 = new Point(bmp.Width - 1, bmp.Height - 1); PointF p3 = new Point(bmp.Width - 1, bmp.Height - 1); // 表示不可见区域的闭合路径 GraphicsPath path = new GraphicsPath(); // 以y轴stepCount个像素为增量,也可以使用x轴为增量,一般使用较短的那个轴 for (int y = 0; y < bmp.Height; y += stepCount) { p0.X = y * Convert.ToSingle(bmp.Width) / Convert.ToSingle(bmp.Height); // 以浮点数计算,保证精度 p1.Y = y; p2.X = bmp.Width - 1 - p0.X; p3.Y = bmp.Height - 1 - p1.Y; path.Reset(); path.AddPolygon(new PointF[] { p0, new PointF(bmp.Width, 0), p3, p2, new PointF(0, bmp.Height), p1 }); dc.DrawImage(bmp, 0, 0); // 绘制全部图像 dc.FillPath(new SolidBrush(Color.FromKnownColor(KnownColor.ButtonFace)), path); // 填充不可见区域 ShowBmp(path.GetBounds()); Thread.Sleep(10 * delay); } // 由于最后一次绘制的不可见区域并不需要,在这里使全部区域可见 dc.DrawImage(bmp, 0, 0); ShowBmp(); } catch (Exception ex) { ShowError(ex.Message); } finally { OnDrawCompleted(this, EventArgs.Empty); } } #endregion #region 垂直百叶(改进版) // 原理:在图像的垂直方向分为高度相等的若干条,然后从上到下计算每次需要显示的区域 private void Animator16() { const float lineHeight = 50; // 百叶高度 try { OnDrawStarted(this, EventArgs.Empty); ClearBackground(); GraphicsPath path = new GraphicsPath(); TextureBrush textureBrush = new TextureBrush(bmp); for (int i = 0; i < lineHeight; i++) // 每条百叶逐行像素显示 { for (int j = 0; j < Math.Ceiling(bmp.Height / lineHeight); j++) { RectangleF rect = new RectangleF(0, lineHeight * j + i, bmp.Width, 1); path.AddRectangle(rect); } dc.FillPath(textureBrush, path); ShowBmp(); Thread.Sleep(10 * delay); } } catch (Exception ex) { ShowError(ex.Message); } finally { OnDrawCompleted(this, EventArgs.Empty); } } #endregion #region 压缩竖条(改进版) // 原理:在图像的水平方向分为宽度相等的若干条,然后逐一加宽每条竖条的宽度,并在其中显示该条图像的全部内容 private void Animator17() { const float lineWidth = 100; // 分条宽度 const int stepCount = 4; // 每次加宽的步进像素,应能被lineWidth整除 try { OnDrawStarted(this, EventArgs.Empty); ClearBackground(); for (int i = 0; i < Math.Ceiling(bmp.Width / lineWidth); i++) { for (int j = stepCount; j <= lineWidth; j += stepCount) // 每条宽度逐渐增加,以产生缩放效果 { RectangleF sourRect = new RectangleF(lineWidth * i, 0, lineWidth, bmp.Height); RectangleF destRect = new RectangleF(lineWidth * i, 0, j, bmp.Height); dc.DrawImage(bmp, destRect, sourRect, GraphicsUnit.Pixel); ShowBmp(destRect); Thread.Sleep(10 * delay); } } } catch (Exception ex) { ShowError(ex.Message); } finally { OnDrawCompleted(this, EventArgs.Empty); } } #endregion #region 水平拉入(改进版) // 原理:由于内存位图与设备无关,故不能使用在水平方向逐渐改变图像分辨率(每英寸点数)的办法 // 而改为使用在水平方向拉伸显示,并逐步缩小 private void Animator18() { try { OnDrawStarted(this, EventArgs.Empty); //ClearBackground(); for (float i = 1; i <= dc.DpiX; i++) { RectangleF destRect = new RectangleF(0, 0, bmp.Width * dc.DpiX / i, bmp.Height); RectangleF sourRect = new RectangleF(0, 0, bmp.Width, bmp.Height); dc.DrawImage(bmp, destRect, sourRect, GraphicsUnit.Pixel); ShowBmp(); Thread.Sleep(10 * delay); } } catch (Exception ex) { ShowError(ex.Message); } finally { OnDrawCompleted(this, EventArgs.Empty); } } #endregion #region 三色对接(改进版) // 原理:使用ImageAttributes类和颜色转换矩阵处理图像,首先R和B分别从左右向中心移动,相遇后继续移动,且G从两侧向中间移动,直到相遇 private void Animator19() { const int stepCount = 4; // 各个区域每次增加的像素量 try { OnDrawStarted(this, EventArgs.Empty); ClearBackground(); // 建立三个时间段所需的5个不同颜色转换后的位图 Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); // 位图的全部矩形区域 // 红色分量位图 ColorMatrix matrix = new ColorMatrix(); matrix.Matrix00 = 1f; // R matrix.Matrix11 = 0f; // G matrix.Matrix22 = 0f; // B ImageAttributes attributes = new ImageAttributes(); attributes.SetColorMatrix(matrix); // 使用R分量转换矩阵 Bitmap redBmp = new Bitmap(bmp.Width, bmp.Height); Graphics.FromImage(redBmp).DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes); // 蓝色分量位图 matrix.Matrix00 = 0f; // R matrix.Matrix11 = 0f; // G matrix.Matrix22 = 1f; // B attributes.SetColorMatrix(matrix); // 使用B分量转换矩阵 Bitmap blueBmp = new Bitmap(bmp.Width, bmp.Height); Graphics.FromImage(blueBmp).DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes); // 红蓝分量位图 matrix.Matrix00 = 1f; // R matrix.Matrix11 = 0f; // G matrix.Matrix22 = 1f; // B attributes.SetColorMatrix(matrix); // 使用B分量转换矩阵 Bitmap redBlueBmp = new Bitmap(bmp.Width, bmp.Height); Graphics.FromImage(redBlueBmp).DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes); // 红绿分量位图 matrix.Matrix00 = 1f; // R matrix.Matrix11 = 1f; // G matrix.Matrix22 = 0f; // B attributes.SetColorMatrix(matrix); // 使用B分量转换矩阵 Bitmap redGreenBmp = new Bitmap(bmp.Width, bmp.Height); Graphics.FromImage(redGreenBmp).DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes); // 蓝绿分量位图 matrix.Matrix00 = 0f; // R matrix.Matrix11 = 1f; // G matrix.Matrix22 = 1f; // B attributes.SetColorMatrix(matrix); // 使用B分量转换矩阵 Bitmap blueGreenBmp = new Bitmap(bmp.Width, bmp.Height); Graphics.FromImage(blueGreenBmp).DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes); // 第1段:1/2时间(设从左到右时间为1),R和B分别从左右向中间移动,在1/2处相遇 for (int x = 0; x < bmp.Width / 2; x += stepCount) { Rectangle rectR = new Rectangle(x, 0, stepCount, bmp.Height); // R的区域,从左到右 dc.DrawImage(redBmp, rectR, rectR, GraphicsUnit.Pixel); Rectangle rectB = new Rectangle(bmp.Width - x - stepCount, 0, stepCount, bmp.Height); // B的区域,从右到左 dc.DrawImage(blueBmp, rectB, rectB, GraphicsUnit.Pixel); ShowBmp(Rectangle.Union(rectR, rectB)); Thread.Sleep(10 * delay); } // 第2段:1/4时间,R和B从中间分别向右、左移动,G从左右向中间移动,在1/4和3/4处相遇 ColorMatrix matrixGLeft = new ColorMatrix(); // 处理从左到右的G ColorMatrix matrixGRight = new ColorMatrix(); // 处理从右到左的G for (int x = 0; x < bmp.Width / 4; x += stepCount) { Rectangle rectBR = new Rectangle(bmp.Width / 2 - x - stepCount, 0, 2 * (x + stepCount), bmp.Height); // B和R的区域(位于中心) dc.DrawImage(redBlueBmp, rectBR, rectBR, GraphicsUnit.Pixel); Rectangle rectGLeft = new Rectangle(x, 0, stepCount, bmp.Height); // 左侧G的区域,从左到右 dc.DrawImage(redGreenBmp, rectGLeft, rectGLeft, GraphicsUnit.Pixel); Rectangle rectGRight = new Rectangle(bmp.Width - x - stepCount, 0, stepCount, bmp.Height); // 右侧G的区域,从右到左 dc.DrawImage(blueGreenBmp, rectGRight, rectGRight, GraphicsUnit.Pixel); ShowBmp(Rectangle.Union(Rectangle.Union(rectBR, rectGLeft), rectGRight)); Thread.Sleep(10 * delay); } // 第3段:1/4时间,显示全色,在1/4处同时向左右两侧扩展(即每次左右各扩展stepCount像素),3/4处与1/4处相同 for (int x = 0; x < bmp.Width / 4; x += stepCount) { Rectangle rect1_4 = new Rectangle(bmp.Width / 4 - x - stepCount, 0, 2 * (x + stepCount), bmp.Height); // 1/4处的区域 dc.DrawImage(bmp, rect1_4, rect1_4, GraphicsUnit.Pixel); Rectangle rect3_4 = new Rectangle(bmp.Width / 4 * 3 - x - stepCount, 0, 2 * (x + stepCount), bmp.Height); // 3/4处的区域 dc.DrawImage(bmp, rect3_4, rect3_4, GraphicsUnit.Pixel); ShowBmp(Rectangle.Union(rect1_4, rect3_4)); Thread.Sleep(10 * delay); } } catch (Exception ex) { ShowError(ex.Message); } finally { OnDrawCompleted(this, EventArgs.Empty); } } #endregion #region 对角滑动(改进版) // 原理:在水平方向从右到左,在垂直方向从下到上移动图像 private void Animator20() { const int movePixel = 4; // 每次移动的像素,应能被图像高度整除 try { OnDrawStarted(this, EventArgs.Empty); ClearBackground(); RectangleF sourRect = new RectangleF(0, 0, bmp.Width, bmp.Height); for (int y = bmp.Height; y >= 0; y -= movePixel) // 从下到上移动图像 { // 按比例计算水平方向移动的量 RectangleF destRect = new RectangleF(y * Convert.ToSingle(bmp.Width) / bmp.Height, y, bmp.Width, bmp.Height); dc.DrawImage(bmp, destRect, sourRect, GraphicsUnit.Pixel); ShowBmp(destRect); Thread.Sleep(10 * delay); } } catch (Exception ex) { ShowError(ex.Message); } finally { OnDrawCompleted(this, EventArgs.Empty); } } #endregion
源程序没有必要解释了,当初编写的时候我就加了非常详细的注释,只要你又一定的.NET基础,应该完全可以读懂!
这里是本文的最后一部分:http://mengliao.blog.51cto.com/876134/473214
相关文章推荐
- 30种图像动画特效算法(C#多线程版)(下)
- 30种图像动画特效算法(C#多线程版)(中)
- 30种图像动画特效算法(C#多线程版)(下)
- 30种图像动画特效算法(C#多线程版)(上) 推荐
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十)斜度α地图的构造及算法
- PS图像特效算法——百叶窗
- CSS3实现超酷的图像动画变换特效
- [转]灰度图像的腐蚀算法和细化算法(C#代码)
- PS图像特效算法——镜像渐隐
- Win8 Metro(C#)数字图像处理--2.65形态学轮廓提取算法
- 九尾之火---算法生成的动画图像
- 基于L0范数平滑的图像漫画特效生成算法
- 解析C#彩色图像灰度化算法的实现代码详解
- 图像相似度算法的C#实现及测评
- Win8 Metro(C#)数字图像处理--2.60部分彩色保留算法
- C#界面设计之图像去雾算法
- 九尾之火---算法生成的动画图像
- 一个简单的统计图像主颜色的算法(C#源代码)
- 图像处理算法之图像暗角特效
- PS 图像特效算法— —渐变