C# WPF图片的绑定及图片转数据流
对图片的操作类
1.图片处理
public class 图片处理
{
/// <summary>
/// 数据流转控件图片
/// </summary>
/// <param name="数据流"></param>
/// <returns>返回WPF Imgae控件数据源</returns>
public static BitmapImage? 数据流转控件图片(byte[]? 数据流)
{
if (null != 数据流 && 数据流.Length > 0)
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = new MemoryStream(数据流);
bitmapImage.EndInit();
return bitmapImage;
}
else
{
return null;
}
}
/// <summary>
/// 图片转Base64字符串
/// </summary>
/// <param name="图片">Image控件图片源</param>
/// <returns>Base64字符串</returns>
public static string 图片转Base64字符串(BitmapImage 图片)
{
byte[] data;
JpegBitmapEncoder encoder = new();
encoder.Frames.Add(BitmapFrame.Create(图片));
using (MemoryStream ms = new())
{
encoder.Save(ms);
data = ms.ToArray();
}
string 临时字符串 = Convert.ToBase64String(data);
return 临时字符串;
}
/// <summary>
/// 图片转数据流
/// </summary>
/// <param name="图片"></param>
/// <returns></returns>
public static byte[] 图片转数据流(BitmapImage 图片)
{
byte[] bytearray = new byte[0];
try
{
Stream smarket = 图片.StreamSource; ;
if (smarket != null && smarket.Length > 0)
{
//设置当前位置
smarket.Position = 0;
using (BinaryReader br = new BinaryReader(smarket))
{
bytearray = br.ReadBytes((int)smarket.Length);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return bytearray;
}
}
2.图像处理
/// <summary>
/// 图像处理
/// </summary>
public class 图像处理
{
/// <summary>
/// 图片转数据流
/// </summary>
/// <param name="图片">图片</param>
/// <returns>byte[]</returns>
private static byte[] 图片转数据流(Bitmap 图片)
{
var format = 图片.RawFormat;
using var ms = new MemoryStream();
if (format.Equals(ImageFormat.Jpeg))
{
图片.Save(ms, ImageFormat.Jpeg);
}
else if (format.Equals(ImageFormat.Png))
{
图片.Save(ms, ImageFormat.Png);
}
else if (format.Equals(ImageFormat.Bmp))
{
图片.Save(ms, ImageFormat.Bmp);
}
else if (format.Equals(ImageFormat.Gif))
{
图片.Save(ms, ImageFormat.Gif);
}
else if (format.Equals(ImageFormat.Icon))
{
图片.Save(ms, ImageFormat.Icon);
}
else
{
图片.Save(ms, ImageFormat.Jpeg);
}
var buffer = new byte[ms.Length];
ms.Seek(0, SeekOrigin.Begin);
ms.Read(buffer, 0, buffer.Length);
ms.Close();
return buffer;
}
/// <summary>
/// base64编码的文本转为100*128的图片
/// </summary>
/// <param name="图片字符串">图片base64编码</param>
/// <returns>图片</returns>
public static byte[] Base64转数据流(string 图片字符串, int newWidth = 100, int newHeight = 128)
{
try
{
if (string.IsNullOrEmpty(图片字符串)) return new byte[0];
var arr = Convert.FromBase64String(图片字符串);
var ms = new MemoryStream(arr);
var bmp = new Bitmap(Image.FromStream(ms, true));
ms.Close();
return 图片转数据流(bmp);
}
catch (Exception)
{
return new byte[0];
}
}
/// <summary>
/// 按100宽/128高缩放,有一个满足就停止缩放,这样另外一边就会比100或者128大。
/// 后续再进行宽100高128进行裁剪
/// 生成100*128的头像图片
/// </summary>
/// <param name="图片"></param>
/// <returns></returns>
public static Bitmap 缩放(Bitmap 图片, int newWidth = 100, int newHeight = 128)
{
double 高比 = 图片.Height / (double)newHeight;
double 宽比 = 图片.Width / (double)newWidth;
if (高比 >= 宽比)
{
newHeight = 图片.Height * newWidth / 图片.Width;
}
else
{
newWidth = 图片.Width * newHeight / 图片.Height;
}
//创建一张新的空图片
Bitmap newImage = new Bitmap(newWidth, newHeight);
//创建一张画布
Graphics g = Graphics.FromImage(newImage);
//在 新 画布上画上 图片
g.DrawImage(图片, new Rectangle(0, 0, newImage.Width, newImage.Height), new Rectangle(0, 0, 图片.Width, 图片.Height), GraphicsUnit.Pixel);
return 裁剪(newImage, newWidth, newHeight);
}
/// <summary>
/// 处理后的图片裁剪出宽100高128的图片
/// </summary>
/// <param name="图片">待处理的图片</param>
/// <returns></returns>
private static Bitmap 裁剪(Bitmap 图片, int newWidth = 100, int newHeight = 128)
{
//创建矩形对象表示原图上裁剪的矩形区域,这里相当于划定原图上坐标为(0, 0)处,100x128大小的矩形区域为裁剪区域
//前两位为X和Y的起始位置,后面两位裁剪后的宽度和高度
Rectangle cropRegion = new Rectangle(0, 0, newWidth, newHeight);
if (图片.Width == newWidth)
{
cropRegion = new Rectangle(0, (图片.Height - newHeight) / 2, newWidth, newHeight);
}
else if (图片.Height == newHeight)
{
cropRegion = new Rectangle((图片.Width - newWidth) / 2, 0, newWidth, newHeight);
}
//else { }
//创建空白画布,大小为裁剪区域大小
Bitmap result = new Bitmap(cropRegion.Width, cropRegion.Height);
//创建Graphics对象,并指定要在result(目标图片画布)上绘制图像
Graphics graphics = Graphics.FromImage(result);
//使用Graphics对象把原图指定区域图像裁剪下来并填充进刚刚创建的空白画布
graphics.DrawImage(图片, new Rectangle(0, 0, cropRegion.Width, cropRegion.Height), cropRegion, GraphicsUnit.Pixel);
return result;
}
/// <summary>
/// 从文件中读取图片
/// </summary>
/// <param name="文件名称">带路径的图片文件名</param>
/// <returns></returns>
public static Bitmap 读取(string 文件名称)
{
//从文件加载原图
Image originImage = Image.FromFile(文件名称);
return new Bitmap(originImage);
}
}
3.数据流转为图片的转换器
public class Base64转图片 : IValueConverter
{
//从数据库 读取 图片记录
/// <summary>
/// Convert
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string? c = value.ToString();
if (value == null)
throw new ArgumentNullException("value can not be null");
return 图片处理.数据流转控件图片(图像处理.Base64转数据流(c![(c!.IndexOf(",") + 1)..^0], 40, 40))!;
}
//目标属性传给源属性时,调用此方法ConvertBack
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null!;
}
}
页面绑定
<Window.Resources>
<local:Base64转图片 x:Key="Base64转图片"/>
</Window.Resources>
<!--图片展示-->
<Image
x:Name="控件构成图片"
Stretch="UniformToFill"
Source="{Binding 控件构成图片, Converter={StaticResource Base64转图片}}"/>
新增图片
/// <summary>
/// 新增图片按钮_点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 新增图片按钮_点击事件(object sender, RoutedEventArgs e)
{
//打开文件路径
OpenFileDialog fileDlg = new()
{
//设置只能打开一个文件路径
Multiselect = false,
//可上传的图片类型
Filter = "图片(*.jpg,*.png,*.gif,*.BMP)|*.jpg;*.png;*.gif;*.BMP",
};
//为true,显示打开文件对话框
if (fileDlg.ShowDialog() == true)
{
try
{
//创建新 图片数据流
byte[] 图片数据流 = new byte[0];
//使用文件流FileStream写入文件
//初始化文件流
using (FileStream fileStream = new FileStream(fileDlg.FileName, FileMode.Open))
{
//读写文件数据流
BinaryReader reader = new BinaryReader(fileStream);
//初始化字节数组,用来暂存读取到的字节
图片数据流 = new byte[fileStream.Length];
//读取流中数据,写入到字节数组中
图片数据流 = reader.ReadBytes((int)fileStream.Length);
//将字节数组 转化成 数据流 并展示
//数据中心类.获取实例().控件构成图片 = 获取图片类.ByteArrayToBitmapImage(图片数据流).ToString();
控件构成图片.Source = 获取图片类.ByteArrayToBitmapImage(图片数据流);
数据中心类.获取实例().控件构成图片 = 图片处理.图片转Base64字符串((BitmapImage)控件构成图片.Source);
}
//新增图片按钮隐藏
新增图片按钮.Visibility = Visibility.Collapsed;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}