WPF将内存中的图片保存到数据库中,并从数据库中显示
阅读原文时间:2021年05月04日阅读:1

需求:在WPF程序运行过程中,会用WriteableBitmap对象绘制视频流中每一帧的图像,需要将某一帧图片显示在前端XAML页面,同时将该图片保存到数据库中,并且实现从数据库中取出图片显示。解决步骤如下:


1.前台显示图片

前台控件为image控件,需要指定控件的imagesoure属性,因此需要将WriteableBitmap对象转换为BitmapImage对象

public BitmapImageAndByte ConvertWriteableBitmapoBitmapImage(WriteableBitmap writeableBitmap)
        {
            BitmapImage bitmapImage = new BitmapImage();

            using (MemoryStream stream = new MemoryStream())
            {
                PngBitmapEncoder encoder = new PngBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(writeableBitmap));
                encoder.Save(stream);
                bitmapImage.BeginInit();
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.StreamSource = stream;
                bitmapImage.EndInit();
                bitmapImage.Freeze();
            }
            return bitmapImage;
        }

指定image控件的imageSource属性为该bitmapImage,即可显示图片

相关链接:
WPF图片处理
WriteableBitmap和BitmapImage的相互转换


2.保存图片到数据库

2.1 图片格式转换

图片保存到MySQL数据库需要先将不同格式的图片保存为byte[ ]数组,无论是本地图片还是网络图片,或者是本次需求中内存里的图片,道理是一样的:转换为byte,存入数据库。
数据库中的字段类型可以根据自己要存取图片的大小来决定,tinyblob、blob、mediumblob等等。
数据库类型如下:

根据需求,我需要将WriteableBitmap对象转化为byte数组

public byte[] ConvertWriteableBitmapToByte(WriteableBitmap writeableBitmap)
        {
            byte[] imgByte = null;

            using (MemoryStream stream = new MemoryStream())
            {
                try
                {
                    stream.Position = 0;
                    using (BinaryReader br = new BinaryReader(stream))
                    {
                        imgByte = br.ReadBytes((int)stream.Length);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("convert error:" + ex.ToString());
                }
            }
            return imgByte;
        }

这段代码和第一步中的转换类似,可以根据需要合并在一个函数中。

2.2 将byte[]存入数据库中

    public byte[] PostureByte1 { get; set; }

        public void SaveImgToDatabase()
        {
            String connetStr = "server=localhost;port=3306;user=root;password=1234;database=test;";
            MySqlConnection conn = null;

            try
            {
                conn = new MySqlConnection(connetStr);
                //string sql = "insert into testimages(img) values(‘{0}‘)";
                //sql = string.Format(sql, PostureByte1);
                //MySqlCommand cmd = new MySqlCommand(sql, conn);
                MySqlCommand cmd = new MySqlCommand();
                cmd.CommandText= "insert into testimages(img) values(@img)";
                cmd.Parameters.Add("@img", MySqlDbType.MediumBlob);//数据类型很重要
                cmd.Parameters[0].Value = PostureByte1;//0代表commandText中的第一个参数
                cmd.Connection = conn;//设置数据库连接
                conn.Open();

                var result = cmd.ExecuteNonQuery();
                if (result != -1)
                {
                    Console.WriteLine("插入成功,插入的byte[]长度为:" + PostureByte1.Length);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("插入失败:" + ex.ToString());
            }
            finally
            {
                if (conn!=null)
                {
                    conn.Close();
                }
            }

        }

注意上段代码中注释掉的部分,直接存放byte到数据库中,会丢失数据。这就造成取出取出byte后,无法还原为图片。所以需要在放入数据库时指定数据的类型为MySqlDbType.MediumBlob。
存放结果:

相关链接:
C#读取Mysql blob字段
C#数据库操作


3.显示数据库中的图片

分为两部分,首先从数据库中取出blob数据,也就是byte[],然后将其转换为BitmapImage对象

3.1 从数据库中取出blob数据

public byte[] ShowImgFromDatabase()
        {
            String connetStr = "server=localhost;port=3306;user=root;password=1234;database=test;";
            MySqlConnection conn = null;
            byte[] imgbyte=null;

            try
            {
                conn = new MySqlConnection(connetStr);
                conn.Open();

                string sql = "select * from testimages";
                MySqlCommand cmd = new MySqlCommand(sql, conn);
                MySqlDataReader reader = cmd.ExecuteReader();

                if (reader.Read())//这里只取出了数据库中的一个记录,根据需要自行更改逻辑
                {
                    long len = reader.GetBytes(reader.GetOrdinal("img"), 0, null, 0, 0);//先获取字段的长度
                    imgbyte = new byte[len];//根据获取到的长度初始化一个byte数组
                    len = reader.GetBytes(reader.GetOrdinal("img"), 0, imgbyte, 0, (int)len);//将数据写入数组
                }
                reader.Close();
                return imgbyte;
            }
            catch (Exception ex)
            {
                Console.WriteLine("读取失败:" + ex.ToString());
                return null;
            }
            finally
            {
                if (conn != null)
                {
                    conn.Close();
                }
            }
        }

3.2 将blob类型也就是byte[]转换为BitmapImage

private BitmapImage ConvertByteToBitmapImage(byte[] imgbyte)
        {
            BitmapImage bmp = null; 

            try
            {
                using (var ms = new MemoryStream(imgbyte))
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    bmp = new BitmapImage();
                    bmp.BeginInit();
                    bmp.CacheOption = BitmapCacheOption.OnLoad;
                    bmp.StreamSource = ms;
                    bmp.EndInit();
                    bmp.Freeze();
                }
                return bmp;
            }
            catch (Exception ex)
            {
                Console.WriteLine("转换失败:"+ex.ToString());
                bmp = null;
            }
            return bmp;
        }

获取到BitmapImage后,赋值给对应的image控件,完成显示。

相关链接:
BitmapImage和byte[]相互转换

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章