C# winform 处理图片的特效用进度条来显示完成进度,请教高手

xywu_lili 2015-09-29 05:30:44

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace TuPianJinDuTiao
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
pictureBox1.ImageLocation = @"C:\Documents and Settings\Administrator\桌面\mnn.jpg";
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
}

public class ImageClass
{
/// <summary>马赛克效果</summary>
/// <param name="bmp">Bitmap 对象</param>
/// <param name="picBox">PictureBox 对象</param>
public static void MaSaiKe(Bitmap MyBitmap, PictureBox picBox)
{ //以马赛克效果显示图像
try
{
int dw = MyBitmap.Width / 50;
int dh = MyBitmap.Height / 50;
Graphics g = picBox.CreateGraphics();
g.Clear(Color.Gray);
Point[] MyPoint = new Point[2500];
for (int x = 0; x < 50; x++)
for (int y = 0; y < 50; y++)
{
MyPoint[x * 50 + y].X = x * dw;
MyPoint[x * 50 + y].Y = y * dh;
}
Bitmap bitmap = new Bitmap(MyBitmap.Width, MyBitmap.Height);
for (int i = 0; i < 10000; i++)
{
System.Random MyRandom = new Random();
int iPos = MyRandom.Next(2500);
for (int m = 0; m < dw; m++)
for (int n = 0; n < dh; n++)
{
bitmap.SetPixel(MyPoint[iPos].X + m, MyPoint[iPos].Y + n, MyBitmap.GetPixel(MyPoint[iPos].X + m, MyPoint[iPos].Y + n));
}
picBox.Refresh();
picBox.Image = bitmap;
}
for (int i = 0; i < 2500; i++)
for (int m = 0; m < dw; m++)
for (int n = 0; n < dh; n++)
{
bitmap.SetPixel(MyPoint[i].X + m, MyPoint[i].Y + n, MyBitmap.GetPixel(MyPoint[i].X + m, MyPoint[i].Y + n));
}
picBox.Refresh();
picBox.Image = bitmap;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "信息提示");
}
}
}

private void btnMaSaiKe_Click(object sender, EventArgs e)
{
ImageClass.MaSaiKe(new System.Drawing.Bitmap(this.pictureBox1.Image), pictureBox1);
}

}
}
该程序实现了把一张图片加入马赛克的特效。现在的问题是,图片的马赛克效果处理过程有点慢,如何加入一个进度条来显示图像的完成进度?要求有具体的实现代码。
...全文
527 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
crystal_lz 2015-09-30
  • 打赏
  • 举报
回复
你是代码 慢 Get/SetPixel 慢的要死 给你一个我以前写的处理马赛克的函数

/// <summary>
/// 获取图像的马赛克图像
/// </summary>
/// <param name="imgSrc">原始图像</param>
/// <param name="width">马赛克宽度</param>
/// <returns>马赛克图像</returns>
public static Image Mosaic(Image imgSrc, int width) {
	Bitmap bmp = new Bitmap(imgSrc);
	BitmapData bmpData = bmp.LockBits(new Rectangle(Point.Empty, bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
	byte[] byColorInfoSrc = new byte[bmpData.Height * bmpData.Stride];
	Marshal.Copy(bmpData.Scan0, byColorInfoSrc, 0, byColorInfoSrc.Length);
	int indexB = 0;//指定宽度正方形内的 r,g,b 的总和
	int indexG = 0;
	int indexR = 0;
	int rCount = 0;//像素点个数
	for (int x = 0, lenx = bmp.Width; x < lenx; x += width) {
		for (int y = 0, leny = bmp.Height; y < leny; y += width) {
			int r = 0, g = 0, b = 0; rCount = 0;
			for (int tempx = x, lentx = x + width <= lenx ? x + width : lenx; tempx < lentx; tempx++) {
				for (int tempy = y, lenty = y + width <= leny ? y + width : leny; tempy < lenty; tempy++) {
					indexB = tempy * bmpData.Stride + tempx * 3;
					indexG = indexB + 1;
					indexR = indexB + 2;

					b += byColorInfoSrc[indexB];
					g += byColorInfoSrc[indexG];
					r += byColorInfoSrc[indexR];
					rCount++;
				}
			}//计算rgb总合
			for (int tempx = x, lentx = x + width <= lenx ? x + width : lenx; tempx < lentx; tempx++) {
				for (int tempy = y, lenty = y + width <= leny ? y + width : leny; tempy < lenty; tempy++) {
					indexB = tempy * bmpData.Stride + tempx * 3;
					indexG = indexB + 1;
					indexR = indexB + 2;

					byColorInfoSrc[indexB] = (byte)(b / (rCount));
					byColorInfoSrc[indexG] = (byte)(g / (rCount));
					byColorInfoSrc[indexR] = (byte)(r / (rCount));
				}
			}//设置像素为平均值
		}
	}
	Marshal.Copy(byColorInfoSrc, 0, bmpData.Scan0, byColorInfoSrc.Length);
	bmp.UnlockBits(bmpData);
	return bmp;
}
我在虚拟机里面 马赛克宽度 设置为 100 获取全屏图像处理 也不到 100 毫秒 1600 * 900 分辨率
_lee_chong 2015-09-30
  • 打赏
  • 举报
回复
第一,像这种操作的进度,需要自己根据算法情况,有循环的用循环标识,没循环的根据实际操作耗时来分配进度比例 第二,你就一张图片的马赛克,那是直接就秒掉了,还用得着进度条? 你的代码需要优化,不说其他的,就你那10000次循环就够呛,而且还每次都picBox.Refresh(); 1L的一眼看过去都比你的循环少了多少倍;不过还可以更快,1L现在的流程是: data -> copy 到 byte[] -> 操作byte[] -> copy 回 data;其中两次托管非托管内存copy操作是很占用cpu的, 建议将图形数据处理放到c/c++层(图形处理可使用gpu并行编程加速处理),这样直接将非托管的data指针传过去处理,省去这两次copy; ------------------ 另外,楼主现在代码出了马赛克逻辑本身外,其他一些地方也有不足之处,虽然建议完全抛弃,不过最好也将你自己写的代码实际意义先搞清楚,有的代码挺莫名奇妙的; g.Clear(Color.Gray);?picbox用image呈现不需要clear和Graphics picBox.Refresh();?如上同理, 大小循环嵌套?我在写图形处理时都是力求减少循环;假设分辨率1000那就是1000/50*10000 ............作死....
shuzhongxiao 2015-09-30
  • 打赏
  • 举报
回复
1、架一个进度条控件,将图片处理放在线程中处理 2、在图片处理代码中使用委托方式更新进度条进度
xian_wwq 2015-09-30
  • 打赏
  • 举报
回复
把耗时操作放入线程,使用委托方式来同步刷进度条 或者用backgroundworker控件
a472544436 2015-09-30
  • 打赏
  • 举报
回复
你的进度条有个屁用,用异步去完成。backgroundworker

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧