WPF 基础(十三)Bitmap、BitmapImage、Image的区别。BitmapImage、Bitmap、byte[]之间的相互转化。Bitmap存储图片到本地。

一、简介

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等格式的图片。

        

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 

        /// 
        /// byte[]转为BitmapImage
        /// 
        /// 
        /// 
        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;
        }
 
        /// 
        /// BitmapImage转为byte[]
        /// 
        /// 
        /// 
        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、

 

你可能感兴趣的:(----------,【基础】)