从 C# WPF 应用程序中读取 MS Access 数据库中的图像 [重复]
Posted
技术标签:
【中文标题】从 C# WPF 应用程序中读取 MS Access 数据库中的图像 [重复]【英文标题】:Read Image from MS Access Database from C# WPF Application [duplicate] 【发布时间】:2018-04-17 14:43:51 【问题描述】:我的问题是:
这样我就可以连接到 MS Access 数据库并从中读取数据。 存储数据表中的数据。 无法将 byte[] 数据转换为我的 WPF 的可显示图像 应用 我正在尝试检索 jpeg 或 png 图像这是我的数据库连接代码(成功代码):
public static void getTableItems(DataTable dt, int bodySectionNo)
// gets the oledbconnection object to open and access
var con = GetConnection();
try
con.Open(); // opens db connection
// creates the sql query for db items change bodysection = # for different bodySections
OleDbCommand command = new OleDbCommand("SELECT itemNo, itemName, NSN, bodySection, Image.FileName, Image.FileData, Image.FileType FROM tblItems WHERE bodySection = " + bodySectionNo + ";", con);
OleDbDataAdapter oleAdapter = new OleDbDataAdapter(command); // executes the command and retrieves the data from the db
oleAdapter.Fill(dt); // fills the datatable with the query results
catch(Exception e)
// writes to console any errors for this connection
Console.WriteLine("ERROR: getTableItemsForHead, " + e.Message);
finally
con.Close(); // closes db connection
在我的 MainWindow.xaml.cs 文件中,我尝试读取数据表、存储数据,然后将数据传递到一个元素中以供主窗口显示。 这是我的 MainWindow.xaml.cs 代码(不成功的代码):
private void populateComboBox(DataTable dt, ComboBox cb)
foreach (DataRow row in dt.Rows)
WrapPanel wp = new WrapPanel();
TextBlock txtItemName = new TextBlock();
TextBlock txtNSN = new TextBlock();
Image img = new Image();
// creates a textbox and adds it to wrappanel
txtItemName.Text = Convert.ToString(row["itemName"]) + " ";
wp.Children.Add(txtItemName);
// creates a textbox and adds it to wrappanel
txtNSN.Text = Convert.ToString(row["NSN"]) + " ";
wp.Children.Add(txtNSN);
// stores image properties from datatable
var fileName = row["Image.FileName"];
var fileData = (byte[])row["Image.FileData"];
var fileType = row["Image.FileType"];
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CreateOptions = BitmapCreateOptions.None;
bi.CacheOption = BitmapCacheOption.Default;
bi.StreamSource = new MemoryStream(fileData);
bi.EndInit();
img.Source = bi;
wp.Children.Add(img);
cb.Items.Add(wp);
我尝试了多种不同的方法将 byte[] 转换为位图、位图图像、位图源、图像、图像源等。我找不到 sn-p 来解决这个“没有适合完成此操作的图像组件被找到” 它打破了 bi.EndInit();线。
System.NotSupportedException 未被用户代码处理 HResult=-2146233067 消息=没有适合的成像组件 完成这个操作被发现。来源=PresentationCore 堆栈跟踪: 在 System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri, Stream 流, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable, Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream, SafeFileHandle & safeFilehandle) 在 System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream 流, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy, 布尔值 insertInDecoderCache) 在 System.Windows.Media.Imaging.BitmapImage.FinalizeCreation() 在 System.Windows.Media.Imaging.BitmapImage.EndInit() 在 CWEDA_take_1.SecondWindow.populateComboBox(DataTable dt, ComboBox cb) 在 P:\All Documents\BBMD 18\CWEDA EH\CWEDA Design 1\CWEDA 取 1\SecondWindow.xaml.cs:line 286 在 P:\All Documents\BBMD 18\CWEDA EH\CWEDA Design 1\CWEDA take 1\SecondWindow.xaml.cs:line 36 中的 CWEDA_take_1.SecondWindow..ctor() 内部异常: 错误代码=-2003292336 H结果=-2003292336 Message=找不到组件。 (来自 HRESULT 的异常:0x88982F50) 内部异常:
编辑:字节[]中的文件数据
编辑:解决方案!!我之前想通了,但忘记上传我的解决方案:
我必须首先通过搜索标题块来确定图像类型。
// Converts byte array from database to image source
public static BitmapImage convertByteSource(byte[] oleFieldBytes)
if (oleFieldBytes == null || oleFieldBytes.Length == 0) return null;
const string BITMAP_ID_BLOCK = "BM";
const string JPG_ID_BLOCK = "\u00FF\u00D8\u00FF";
const string PNG_ID_BLOCK = "\u0089PNG\r\n\u001a\n";
byte[] imageBytes;
// Get a UTF7 Encoded string version
Encoding u8 = Encoding.UTF7;
string strTemp = u8.GetString(oleFieldBytes);
// Get the first 300 characters from the string
string strVTemp = strTemp.Substring(0, 300);
// Search for the block
int iPos = -1;
if (strVTemp.IndexOf(BITMAP_ID_BLOCK) != -1)
iPos = strVTemp.IndexOf(BITMAP_ID_BLOCK);
else if (strVTemp.IndexOf(JPG_ID_BLOCK) != -1)
iPos = strVTemp.IndexOf(JPG_ID_BLOCK);
else if (strVTemp.IndexOf(PNG_ID_BLOCK) != -1)
iPos = strVTemp.IndexOf(PNG_ID_BLOCK);
else
throw new Exception("Unable to determine header size for the OLE Object");
// From the position above get the new image
if (iPos == -1)
throw new Exception("Unable to determine header size for the OLE Object");
//Array.Copy(
imageBytes = new byte[oleFieldBytes.LongLength - iPos];
MemoryStream ms = new MemoryStream();
ms.Write(oleFieldBytes, iPos, oleFieldBytes.Length - iPos);
imageBytes = ms.ToArray();
ms.Close();
// creates new bitmapimage
BitmapImage bi = new BitmapImage();
bi.BeginInit();// inits bitmapimage
bi.CreateOptions = BitmapCreateOptions.None;
bi.CacheOption = BitmapCacheOption.Default;
bi.StreamSource = new MemoryStream(imageBytes);
bi.EndInit();
return bi;
【问题讨论】:
这里的问题是实际图像缓冲区之前 20 字节的(未知)标头。虽然可以安全地跳过它,但仍然值得一看:blogs.msdn.microsoft.com/pranab/2008/07/15/… 【参考方案1】:此页面中的代码看起来与您那里的代码有些不同:http://csharphelper.com/blog/2015/07/display-images-in-an-access-database-in-wpf-and-c/
以防万一这可行并且将来链接断开。代码确实:
if (reader.IsDBNull(6))
imgCover.Source = null;
else
imgCover.Source =
BytesToImage((byte[])reader.GetValue(6));
那个方法:
// Convert a byte array into a BitmapImage.
private static BitmapImage BytesToImage(byte[] bytes)
var bm = new BitmapImage();
using (MemoryStream stream = new MemoryStream(bytes))
stream.Position = 0;
bm.BeginInit();
bm.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
bm.CacheOption = BitmapCacheOption.OnLoad;
bm.UriSource = null;
bm.StreamSource = stream;
bm.EndInit();
return bm;
【讨论】:
虽然stream.Position = 0
是多余的,但bm.CreateOptions = BitmapCreateOptions.PreservePixelFormat
只有在你真的想要的时候才有意义。通常你不会。除此之外,当您想在 EndInit 之后立即关闭流时,设置 bm.CacheOption = BitmapCacheOption.OnLoad
很重要。在问题中并非如此。虽然是很好的做法,但对于 MemoryStream 来说并不是绝对必要的。现在,剩下的答案是什么?
我仍然遇到同样的错误,不过感谢您的尝试。以上是关于从 C# WPF 应用程序中读取 MS Access 数据库中的图像 [重复]的主要内容,如果未能解决你的问题,请参考以下文章