WPF实现将图像转化成粒子效果
程序员文章站
2022-05-28 14:30:22
...
实现效果如下:
这里的处理逻辑首先是将图像进行马赛克处理,然后对于每一个需要填充的粒子按照颜色的深浅度计算粒子大小,最后按照坐标进行填充。
1、粒子类
public class Particle
{
public Point Position;//位置
public double Size;//尺寸
}
2、图像处理类
public class MosaicHelper
{
/// <summary>
/// 马赛克处理
/// </summary>
/// <param name="bitmap"></param>
/// <param name="effectWidth"> 影响范围 每一个格子数 </param>
public static List<Particle> AdjustTobMosaic(System.Drawing.Bitmap bitmap, int effectWidth)
{
List<Particle> particleList = new List<Particle>();
for (int heightOfffset = 0; heightOfffset < bitmap.Height; heightOfffset += effectWidth)
{
for (int widthOffset = 0; widthOffset < bitmap.Width; widthOffset += effectWidth)
{
int avgR = 0, avgG = 0, avgB = 0;
int blurPixelCount = 0;
for (int x = widthOffset; (x < widthOffset + effectWidth && x < bitmap.Width); x++)
{
for (int y = heightOfffset; (y < heightOfffset + effectWidth && y < bitmap.Height); y++)
{
System.Drawing.Color pixel = bitmap.GetPixel(x, y);
avgR += pixel.R;
avgG += pixel.G;
avgB += pixel.B;
blurPixelCount++;
}
}
avgR = avgR / blurPixelCount;
avgG = avgG / blurPixelCount;
avgB = avgB / blurPixelCount;
for (int x = widthOffset; (x < widthOffset + effectWidth && x < bitmap.Width); x += effectWidth)
{
for (int y = heightOfffset; (y < heightOfffset + effectWidth && y < bitmap.Height); y += effectWidth)
{
particleList.Add(new Particle { Position = new Point(x, y), Size = CalculateSize(avgR, avgG, avgB, effectWidth) });
}
}
}
}
return particleList;
}
/// <summary>
/// 计算粒子大小
/// </summary>
public static double CalculateSize(int avgR, int avgG, int avgB, int effectWidth)
{
return (255 -(avgR * 0.299 + avgG * 0.587 + avgB * 0.114)) / 255 * effectWidth;
}
}
3、主窗体xaml
<Window x:Class="NewMosaicDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:NewMosaicDemo"
mc:Ignorable="d"
Title="MainWindow" SizeToContent="WidthAndHeight" Background="#f0f0f0" WindowStartupLocation="CenterScreen">
<Grid Margin="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Canvas x:Name="mainCanvas" Grid.Column="1" Background="White" MinWidth="500" MinHeight="400" Margin="20,0,0,0"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ClipToBounds="True">
</Canvas>
<GroupBox Grid.Column="0" Header="操作区">
<StackPanel Orientation="Vertical">
<Button x:Name="btnChooseImg" Content="选择图片" VerticalAlignment="Center" HorizontalAlignment="Center" Height="26" Width="80" Margin="10" Click="btnChooseImg_Click"></Button>
<Image x:Name="showImage" Width="200" Height="200" Stretch="Uniform"></Image>
<StackPanel Margin="18">
<StackPanel Orientation="Horizontal">
<TextBlock Text="5" Margin="2,0,0,0"/>
<TextBlock Text="10" Margin="50,0,0,0"/>
<TextBlock Text="15" Margin="50,0,0,0"/>
<TextBlock Text="20" Margin="50,0,0,0"/>
</StackPanel>
<Slider x:Name="particleSizeSlider" Minimum="5" Maximum="20" TickFrequency="5" IsSnapToTickEnabled="True" TickPlacement="TopLeft" ValueChanged="particleSizeSlider_ValueChanged"></Slider>
</StackPanel>
</StackPanel>
</GroupBox>
</Grid>
</Window>
交互逻辑
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private System.Drawing.Bitmap map;//待处理的图源
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// 选择图片
/// </summary>
private void btnChooseImg_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Title = "选择图片";
openFileDialog.Filter = "图片(*.jpg,*.png,*.bmp)|*.jpg;*.png;*.bmp"; ;
openFileDialog.FileName = string.Empty;
openFileDialog.Multiselect = false;
openFileDialog.InitialDirectory = @"C:\Image";
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.showImage.Source = ImageHelper.LoadBitmapImageByPath(openFileDialog.FileName);
System.Drawing.Image img = System.Drawing.Image.FromFile(openFileDialog.FileName);
map = new System.Drawing.Bitmap(img);
HandleImage(Convert.ToInt32(this.particleSizeSlider.Value));
}
}
private void particleSizeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!this.particleSizeSlider.IsLoaded) return;
HandleImage(Convert.ToInt32(this.particleSizeSlider.Value));
}
/// <summary>
/// 处理图片
/// </summary>
private void HandleImage(int effectWidth)
{
if (map == null) return;
this.mainCanvas.Children.Clear();
List<Particle> particleList = MosaicHelper.AdjustTobMosaic(map, effectWidth);
foreach (var pd in particleList)
{
var ep = new Ellipse
{
Width = pd.Size,
Height = pd.Size,
Fill = new SolidColorBrush(Colors.Black),
};
Canvas.SetTop(ep, pd.Position.Y);
Canvas.SetLeft(ep, pd.Position.X);
this.mainCanvas.Children.Add(ep);
}
}
}
上一篇: 3D游戏编程8--简单的粒子系统
下一篇: WPF实现响应鼠标位置粒子背景动画特效
推荐阅读