2016-11-03 62 views
0

我想將WPF BitmapImage存儲到XML。 (我知道這通常不推薦,但對我來說,這是有意義的,因爲我想將我的資源嵌入到除了其他數據之外的單個XML文件中)。使用JpegBitmapEncoder將WPF BitmapImage轉換爲Base64並從Base64轉換爲加載JPG文件失敗

所以,這裏是我的擴展方法:

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> 
... 

但是,當我嘗試創建一個位圖圖像使用ToBitmapIm年齡方法從我以前保存的XML數據我得到「圖像無法解碼。圖像頭可能都被破壞。」異常。

這僅發生於JPG文件我沒有問題與PNG文件。

回答

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影響的BitmapDecoderPosition

+0

謝謝@Clemens。這是問題所在。你節省了我的一天:) – Ali

+1

您可能也有興趣:http://stackoverflow.com/a/16243638/1136211 – Clemens