原图
处理后效果
【思路】
取原图像某一位置一定范围内像素的平均颜色,绘制成一个圆点,循环全图即可实现。
为了实现更为复杂一些的上图效果,做成了鼠标经过后拆分圆形尺寸。
主窗口源代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace FragmentationDemo
{
public partial class Fragmentation : Form
{
public Fragmentation()
{
InitializeComponent();
}
/// <summary>
/// 最大碎片尺寸
/// </summary>
int max_Size = 160;
/// <summary>
/// 最小碎片尺寸
/// </summary>
int min_Size = 2;
/// <summary>
/// 文件名
/// </summary>
string bmpFile;
/// <summary>
/// 支持的格式
/// </summary>
static string[] File_Formart = { "jpg", "jpeg", "bmp","png","gif" };
/// <summary>
/// 图像
/// </summary>
Bitmap bmp;
/// <summary>
/// 碎片集合
/// </summary>
List<Pic> picture;
/// <summary>
/// 动画标志
/// </summary>
bool isAnima = false;
/// <summary>
/// 初始化窗口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Fragmentation_Load(object sender, EventArgs e)
{
this.ClientSize = new Size(800, 480);
this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
this.KeyPreview = true;
this.CenterToScreen();
}
/// <summary>
/// 重写重绘方法
/// </summary>
/// <param name="e"></param>
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.FillRectangle(Brushes.White, this.ClientRectangle);
if (bmp == null)
{
using (SolidBrush sBrush = new SolidBrush(Color.Red))
{
g.DrawString("请将需要处理的图像拖放至此", new Font("The New Roman", 22f, FontStyle.Bold), sBrush, 175, 225);
g.DrawString("操作提示按[A]自动演示,按[R]恢复图像初始状态.", new Font("The New Roman", 14f, FontStyle.Regular), sBrush, 175, 265);
}
return;
}
// 绘制图像
foreach (Pic p in picture)
{
g.FillEllipse(new SolidBrush(p.c), new Rectangle(p.x, p.y, p.size, p.size));
}
}
/// <summary>
/// 鼠标移动处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Fragmentation_MouseMove(object sender, MouseEventArgs e)
{
if (isAnima) return;
Create(e.X, e.Y);
}
/// <summary>
/// 按键事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Fragmentation_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.A:
// 自动逐层展开
for (int num = max_Size; num > min_Size; num /= 2)
{
for (int j = 1; j < this.ClientSize.Height - num; j += num)
{
for (int i = 1; i < this.ClientSize.Width - num; i += num)
{
Application.DoEvents();
Create(i, j);
}
}
}
break;
case Keys.R:
OpenFile(bmpFile);
break;
}
}
/// <summary>
/// 打开区域
/// </summary>
/// <param name="xx"></param>
/// <param name="yy"></param>
private void Create(int xx, int yy)
{
try
{
if (picture == null)
{
return;
}
foreach (Pic p in picture)
{
int x = p.x + p.size / 2;
int y = p.y + p.size / 2;
int size = p.size / 2;
int len = (int)Math.Sqrt(Math.Pow((x - xx), 2) + Math.Pow((y - yy), 2));
if (len < p.size / 2 && len >= min_Size)
{
// 动画放速度
double speed = 0.8;
Graphics g = Graphics.FromHwnd(this.Handle);
isAnima = true;
for (double r = p.size; r >= min_Size-1; r *= speed)
{
g.FillRectangle(Brushes.White, new Rectangle(p.x, p.y, p.size, p.size));
g.FillEllipse(new SolidBrush(p.c), p.x + (int)(p.size - r) / 2, p.y + (int)(p.size - r) / 2, (int)r, (int)r);
Thread.Sleep(5);
Application.DoEvents();
}
Pic p1 = new Pic();
p1.x = p.x;
p1.y = p.y;
p1.size = p.size / 2;
p1.c = GetColor(p.x, p.y, p.size / 2);
Pic p2 = new Pic();
p2.x = p.x + p.size / 2;
p2.y = p.y;
p2.size = p.size / 2;
p2.c = GetColor(p.x + p.size / 2, p.y, p.size / 2);
Pic p3 = new Pic();
p3.x = p.x;
p3.y = p.y + p.size / 2;
p3.size = p.size / 2;
p3.c = GetColor(p.x, p.y + p.size / 2, p.size / 2);
Pic p4 = new Pic();
p4.x = p.x + p.size / 2;
p4.y = p.y + p.size / 2;
p4.size = p.size / 2;
p4.c = GetColor(p.x + p.size / 2, p.y + p.size / 2, p.size / 2);
g.FillRectangle(Brushes.White, new Rectangle(p.x, p.y, p.size, p.size));
for (double r = min_Size; r <= p.size / 2 + 1; r /= speed)
{
//g.FillRectangle(Brushes.White, new Rectangle(p.x, p.y, p.size, p.size));
g.FillEllipse(new SolidBrush(p1.c), new Rectangle(p1.x + (int)(p.size / 2 - r)/2, p1.y + (int)(p.size / 2 - r)/2, (int)r, (int)r));
g.FillEllipse(new SolidBrush(p2.c), new Rectangle(p2.x + (int)(p.size / 2 - r)/2, p2.y + (int)(p.size / 2 - r)/2, (int)r, (int)r));
g.FillEllipse(new SolidBrush(p3.c), new Rectangle(p3.x + (int)(p.size / 2 - r)/2, p3.y + (int)(p.size / 2 - r)/2, (int)r, (int)r));
g.FillEllipse(new SolidBrush(p4.c), new Rectangle(p4.x + (int)(p.size / 2 - r)/2, p4.y + (int)(p.size / 2 - r)/2, (int)r, (int)r));
Thread.Sleep(5);
Application.DoEvents();
}
picture.Remove(p);
picture.Add(p1);
picture.Add(p2);
picture.Add(p3);
picture.Add(p4);
isAnima = false;
break;
}
}
}
catch
{
}
}
/// <summary>
/// 加载文件
/// </summary>
/// <param name="FileName"></param>
private void OpenFile(string FileName)
{
try
{
bmp = new Bitmap(Bitmap.FromFile(FileName), new Size(800, 480));
picture = new List<Pic>();
// 初始化数组
for (int i = 0; i < 800; i += max_Size)
{
for (int j = 0; j < 480; j += max_Size)
{
Pic p = new Pic();
p.x = i;
p.y = j;
p.size = max_Size;
p.c = GetColor(i, j, max_Size);
picture.Add(p);
}
}
this.Invalidate(this.ClientRectangle, true);
}
catch
{
}
}
#region 图像处理函数
/// <summary>
/// 获取某一点某一尺寸的颜色
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="size"></param>
/// <returns></returns>
private Color GetColor(int x, int y, int size)
{
Color c;
Bitmap b = BitmapCut(bmp, x, y, size, size);
Bitmap bb = new Bitmap(b, new Size(1, 1));
return bb.GetPixel(0, 0);
}
/// <summary>
/// 图像切割函数
/// </summary>
/// <param name="b">图像源</param>
/// <param name="StartX">起点x</param>
/// <param name="StartY">起点y</param>
/// <param name="iWidth">宽度</param>
/// <param name="iHeight">高度</param>
/// <returns></returns>
private Bitmap BitmapCut(Bitmap b, int StartX, int StartY, int iWidth, int iHeight)
{
if (b == null)
{
return null;
}
int w = b.Width;
int h = b.Height;
if (StartX >= w || StartY >= h)
{
return null;
}
if (StartX + iWidth > w)
{
iWidth = w - StartX;
}
if (StartY + iHeight > h)
{
iHeight = h - StartY;
}
try
{
Bitmap bmpOut = new Bitmap(iWidth, iHeight, PixelFormat.Format32bppArgb);//ARGB取色以实现透明度
Graphics g = Graphics.FromImage(bmpOut);
g.DrawImage(b, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(StartX, StartY, iWidth, iHeight), GraphicsUnit.Pixel);
//元件边框
//g.DrawRectangle(Pens.Black, new Rectangle(new Point(0, 0), new Size(iWidth - 3, iHeight - 3)));
g.Dispose();
return bmpOut;
}
catch
{
return null;
}
}
#endregion
#region 拖放打开文件
/// <summary>
/// 拖放打开文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Fragmentation_DragDrop(object sender, DragEventArgs e)
{
string fileName = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
string[] fileFormart = fileName.Split('.');
if (FindFormartStr(fileFormart[fileFormart.Length - 1].ToLower()) > -1)
{
bmpFile = fileName;
OpenFile(bmpFile);
}
else
{
MessageBox.Show("该文件格式不支持!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 拖放文件进入
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Fragmentation_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Link;
else e.Effect = DragDropEffects.None;
}
/// <summary>
/// 查找指定格式
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private int FindFormartStr(string str)
{
for (int i = 0; i < File_Formart.Length; i++)
{
if (File_Formart[i] == str)
{
return i;
}
}
return -1;
}
#endregion
}
/// <summary>
/// 碎片类
/// </summary>
public class Pic
{
public int x;
public int y;
public int size;
public Color c;
}
}