我想将WPF BitmapImage存储到XML。 (我知道这通常不推荐,但对于我的情况,它是有意义的,因为我想将我的所有资源嵌入到单个XML文件中,除了我有其他数据)。
所以这是我的扩展方法:
public static string ToBase64(this BitmapImage image, string format)
{
return Convert.ToBase64String(Encode(image, format));
}
public static Stream FromBase64(this string content)
{
var bytes = Convert.FromBase64String(content);
var stream = new MemoryStream();
stream.Write(bytes, 0, bytes.Length);
return stream;
}
private static byte[] Encode(BitmapImage bitmapImage, string format)
{
byte[] data = null;
BitmapEncoder encoder = null;
switch (format.ToUpper())
{
case "PNG": encoder = new PngBitmapEncoder();
break;
case "GIF": encoder = new GifBitmapEncoder();
break;
case "BMP": encoder = new BmpBitmapEncoder();
break;
case "JPG": encoder = new JpegBitmapEncoder();
break;
}
if (encoder != null)
{
encoder.Frames.Add(BitmapFrame.Create(bitmapImage));
using (var ms = new MemoryStream())
{
encoder.Save(ms);
ms.Seek(0, SeekOrigin.Begin);
data = ms.ToArray();
}
}
return data;
}
public static BitmapImage ToBitmapImage(this Stream stream)
{
try
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
return bitmap;
}
catch (Exception ex)
{
}
return null;
}
这是我的XML逻辑:
public async void LoadImage(Guid imageSourceGuid)
{
var sourceElement = await GetImageSource(imageSourceGuid);
if (sourceElement != null)
{
var data = sourceElement.Element("Value").Value;
Format = sourceElement.Attribute("Format").Value.ToUpper();
if (string.IsNullOrEmpty(data) == false)
{
using (var stream = data.FromBase64())
{
SetImage(stream.ToBitmapImage());
}
}
}
}
private void SetImage(BitmapImage bitmap)
{
this.ImageShape.Source = bitmap;
}
public async Task<XElement> GetImageSource(Guid id)
{
XElement result = null;
await Task.Run(() =>
{
var settings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment, IgnoreWhitespace = true, IgnoreComments = true, Async = true };
using (var reader = XmlReader.Create(FilePath, settings))
{
while (reader.Read())
{
if (reader.IsStartElement() && reader.Name == "ImageSource")
{
var att = reader.GetAttribute("Id");
if (att != null && Guid.Parse(att) == id)
{
result = XNode.ReadFrom(reader) as XElement;
break;
}
}
}
}
});
return result;
}
我的XML文件如下:
<?xml version="1.0" encoding="utf-8"?>
<ImageSources>
<ImageSource Id="1b1e4ebc-484c-4f63-bbed-bf33430f85f2" Format="JPG" OriginalWidth="534" OriginalHeight="338">
<Value><![CDATA[....]]<Value>
</ImageSource>
</ImageSources>
...
但是当我尝试使用先前保存的XML数据中的 ToBitmapImage 方法创建 BitmapImage 时,我得到“图像无法解码。图像标题可能已损坏。“例外。
这仅适用于 JPG 文件我根本没有 PNG 文件的问题。
答案 0 :(得分:2)
使用FromBase64
方法编写后,您应该回放MemoryStream:
public static Stream FromBase64(this string content)
{
var bytes = Convert.FromBase64String(content);
var stream = new MemoryStream();
stream.Write(bytes, 0, bytes.Length);
stream.Seek(0, SeekOrigin.Begin); // here
return stream;
}
或者直接从字节数组构建它:
public static Stream FromBase64(this string content)
{
return new MemoryStream(Convert.FromBase64String(content));
}
Afaik,JpegBitmapDecoder
是WPF中唯一受源流实际BitmapDecoder
影响的Position
。