WPF字节数组到ImageSource,而不使用MemoryStream
本文关键字:MemoryStream ImageSource 字节 字节数 数组 WPF | 更新日期: 2023-09-27 18:28:05
我有一个应用程序,它可以动态创建WPF图像控件,以显示SQL Server数据库表中的图像。显示控件的面板经常被更换。我使用MemoryStream允许控件访问从数据库加载的字节数组。我无法关闭这些流,只要图像控件已显示并且仍显示图像即可。我担心的是,这些流将一直处于打开状态,直到垃圾回收器能够处理Image控件并希望关闭这些流。我最终可能只会确保在更换面板之前关闭流或处理图像控件,但我想知道是否存在打开这些流的问题,以及是否有办法解决这一问题。
这是我正在使用的代码。
public class ImageToSql
{
private static OpenFileDialog _openFileDialog = new OpenFileDialog();
static ImageToSql()
{
_openFileDialog = new OpenFileDialog();
_openFileDialog.AddExtension = true;
_openFileDialog.CheckFileExists = true;
_openFileDialog.DefaultExt = ".jpg";
_openFileDialog.Filter = "JPEG files (*.jpg)|*.jpg|All files (*.*)|*.*";
_openFileDialog.FilterIndex = 1;
_openFileDialog.Multiselect = false;
}
public static BitmapImage LoadImageFromFile(string caption)
{
BitmapImage bi = new BitmapImage();
_openFileDialog.Title = caption;
if (_openFileDialog.ShowDialog() == true)
{
bi.BeginInit();
bi.StreamSource = File.OpenRead(_openFileDialog.FileName);
bi.EndInit();
}
return bi;
}
public static int StoreImage(string connectionString, string sql, string imageParameterName, BitmapImage bitmapImage)
{
SqlConnection conn = new SqlConnection(connectionString);
try
{
conn.Open();
sql += ";SELECT @@IDENTITY";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
byte[] data = new byte[bitmapImage.StreamSource.Length];
bitmapImage.StreamSource.Seek(0, SeekOrigin.Begin);
bitmapImage.StreamSource.Read(data, 0, data.Length);
cmd.Parameters.Add(imageParameterName, System.Data.SqlDbType.VarBinary, -1).Value = data;
object obj = cmd.ExecuteScalar();
return Int32.Parse(obj.ToString());
}
}
finally
{
conn.Close();
}
}
public static BitmapImage RetrieveImage(string connectionString, string sql, string imageIDParameterName, int imageID)
{
BitmapImage bi = new BitmapImage();
SqlConnection conn = new SqlConnection(connectionString);
try
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(imageIDParameterName, System.Data.SqlDbType.Int).Value = imageID;
byte[] data = (byte[])cmd.ExecuteScalar();
MemoryStream ms = new MemoryStream(data);
ms.Seek(0, SeekOrigin.Begin);
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
}
}
finally
{
conn.Close();
}
return bi;
}
}
以下是如何调用此代码。"_fileImage"answers"_sqlImage"是我的测试窗口上的图像控件。有一次,我在"LoadImageFromFile"中使用流从磁盘读取文件,并认为我能够关闭该流,同时仍在image控件中显示图像。所以,MemoryStream似乎在某种程度上很特别。
BitmapImage bi = ImageToSql.LoadImageFromFile("Select Image to Save");
_fileImage.Source = bi;
int imageID = ImageToSql.StoreImage(connString,
"INSERT INTO PV_Image (Description, Image) VALUES ('Some Image', @pImage)",
"@pImage", bi);
_sqlImage.Source = ImageToSql.RetrieveImage(connString,
"SELECT Image FROM PV_Image WHERE ImageID = @pImageID",
"@pImageID", imageID);
一旦使用内存流,就可以使用以下使用模式处理它:
using (Stream stream = new MemoryStream(data))
{
BitmapImage image = new BitmapImage():
stream.Position = 0;
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = stream;
image.EndInit();
image.Freeze();
return image;
}