一、简介
1、Bitmap(Bitmap类、.bmp格式)
1.1、Bitmap是什么类型文件?
参考:https://blog.csdn.net/wander_wang/article/details/38661653
BMP(全称Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。BMP文件的图像深度可选lbit、4bit、8bit及24bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。
2、BitmapImage是什么?
3、Image与BitmapImage、Bitmap有什么关系?
Image控件,常常用来加载图片,加载的方式有很多种类型。比如直接加载.png.jpeg等格式的图片、加载Bitmap、加载BitmapImage。
1、Image控件直接加载.png .jpeg等格式的图片。
<Image x:Name="image" HorizontalAlignment="Left" Height="415" Margin="227,141,0,0" VerticalAlignment="Top" Width="670" Source ="faf.jpeg"/>
2、Image控件加载BitmapImage(提供了绑定或不绑定的方法)
https://blog.csdn.net/xpj8888/article/details/83540743
3、Image控件加载Bitmap
摄像头采集数据的每一帧,或者直接截取的屏幕位图(截屏)等等,那就不能采用以上集中方式了。为了能够将内存中的Bitmap位图显示在Image控件中,需要将Bitmap转换为ImageSource类型或BitmapImage的类型。这篇博客,将Bitmap转换为ImageSource类型或BitmapImage的类型。然后将ImageSource类型或BitmapImage类型显示在Image上即可。
Bitmap类,最后还是转成了BitmapImage或ImageSource才能显示。
3.1、Bitmap转ImageSource或BitmapImage
https://blog.csdn.net/jiuzaizuotian2014/article/details/81279423
3.2、Bitmap转字节,字节转BitmapImage
https://blog.csdn.net/u013139930/article/details/51785687
二、BitmapImage对象和byte[]之间的互转
参考了https://blog.csdn.net/gooapple/article/details/50616821
/// <summary>
/// byte[]转为BitmapImage
/// </summary>
/// <param name="byteArray"></param>
/// <returns></returns>
public static BitmapImage ToImage(byte[] byteArray)
{
BitmapImage bmp = null;
try
{
bmp = new BitmapImage();
bmp.BeginInit();
bmp.StreamSource = new MemoryStream(byteArray);
bmp.EndInit();
}
catch
{
bmp = null;
}
return bmp;
}
/// <summary>
/// BitmapImage转为byte[]
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
public static byte[] ToByteArray(BitmapImage bmp)
{
byte[] ByteArray = null;
try
{
Stream stream = bmp.StreamSource;
if (stream != null && stream.Length > 0)
{
stream.Position = 0;
using (BinaryReader br = new BinaryReader(stream))
{
ByteArray = br.ReadBytes((int)stream.Length);
}
}
}
catch
{
return null;
}
return ByteArray;
}
三、 BitmapImage和Bitmap互换
若ConvertBitmapToBitmapImage出错,则下面这行改成 bitmap.Save(stream, ImageFormat.Png)。
//将Bitmap对象转换成bitmapImage对象
public BitmapImage ConvertBitmapToBitmapImage(Bitmap bitmap)
{
MemoryStream stream = new MemoryStream();
bitmap.Save(stream, ImageFormat.Bmp);
BitmapImage image = new BitmapImage();
image.BeginInit();
image.StreamSource = stream;
image.EndInit();
return image;
}
//将bitmapImage对象转换成Bitmap对象
public static System.Drawing.Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
using (System.IO.MemoryStream outStream = new System.IO.MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapImage));
enc.Save(outStream);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);
return bitmap;
}
}
四、Bitmap与byte[]相互转化
//byte[] 转换 Bitmap
public static Bitmap BytesToBitmap(byte[] Bytes)
{
MemoryStream stream = null;
try
{
stream = new MemoryStream(Bytes);
return new Bitmap((Image)new Bitmap(stream));
}
catch (ArgumentNullException ex)
{
throw ex;
}
catch (ArgumentException ex)
{
throw ex;
}
finally
{
stream.Close();
}
}
//Bitmap转byte[]
public static byte[] BitmapToBytes(Bitmap Bitmap)
{
MemoryStream ms = null;
try
{
ms = new MemoryStream();
Bitmap.Save(ms, Bitmap.RawFormat);
byte[] byteImage = new Byte[ms.Length];
byteImage = ms.ToArray();
return byteImage;
}
catch (ArgumentNullException ex)
{
throw ex;
}
finally
{
ms.Close();
}
}
}
或者https://blog.csdn.net/chentian1207/article/details/80199869
Bitmap => byte[]
Bitmap b = new Bitmap( "test.bmp ");
MemoryStream ms = new MemoryStream();
b.Save(ms,System.Drawing.Imaging.ImageFormat.Bmp);
byte[] bytes= ms.GetBuffer(); //byte[] bytes= ms.ToArray();
ms.Close();
byte[] => Bitmap
byte[] bytelist=bytes;
MemoryStream ms1 = new MemoryStream(bytelist);
Bitmap bm = (Bitmap)Image.FromStream(ms1);
ms1.Close();
五、BitmapImage或Bitmap存储成图片,保存到本地
BitmapImage一般转成Bitmap后,Bitmap再转成.png/.jpg等等的格式。
bitmap.Save(@"D:\人脸识别+指纹识别\人脸识别\BitImage\XXX", System.Drawing.Imaging.ImageFormat.Jpeg);
六、实际应用
1、不能用的代码,会遇到调用线程无法访问此对象,因为另一个线程拥有该对象,至今我还不清楚(应该不是 Dispatcher.BeginInvoke 更新UI的问题,可能是两个using的问题)。
代码如下:
private void video_NewFrame(object sender, Video.NewFrameEventArgs eventArgs)
{
try
{
BitmapImage bi;
Byte[] Array;
using (var bitmap = (Bitmap)eventArgs.Frame.Clone())
{
bi = bitmap.ToBitmapImage();
//将BitmapImage转成字节
Stream stream = bi.StreamSource;
if (stream != null && stream.Length > 0)
{
using (BinaryReader br = new BinaryReader(stream))
{
Array = br.ReadBytes((int)stream.Length);
}
}
}
bi.Freeze(); // avoid cross thread operations and prevents leaks
Dispatcher.BeginInvoke(new ThreadStart(delegate { videoPlayer.Source = bi; }));
}
catch (Exception exc)
{
MessageBox.Show("Error on _videoSource_NewFrame:\n" + exc.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
StopCamera();
}
}
2、去掉里面的using,正常运行
private void video_NewFrame(object sender, Video.NewFrameEventArgs eventArgs)
{
try
{
BitmapImage bi;
Byte[] Array;
using (var bitmap = (Bitmap)eventArgs.Frame.Clone())
{
bi = bitmap.ToBitmapImage();
//将BitmapImage转成字节
Stream stream = bi.StreamSource;
if (stream != null && stream.Length > 0)
{
BinaryReader br = new BinaryReader(stream);
Array = br.ReadBytes((int)stream.Length);
}
}
bi.Freeze(); // avoid cross thread operations and prevents leaks
Dispatcher.BeginInvoke(new ThreadStart(delegate { videoPlayer.Source = bi; }));
}
catch (Exception exc)
{
MessageBox.Show("Error on _videoSource_NewFrame:\n" + exc.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
StopCamera();
}
}
七、总结
1、直接转成BitmapImage给Image控件加载。
Image控件,一般直接加载BitmapImage。.jpg等格式的图片、Bitmap、byte[]都可以转成字节BitmapImage的形式,以便Image控件加载。
2、