Base64图像到WPF图像源错误没有合适的成像组件

cmssoen2  于 2023-05-08  发布在  其他
关注(0)|答案(4)|浏览(152)

我试图解码一个Base64图像,并将其放入WPF图像源。但是,我使用的代码有一个错误:
未找到适合完成此操作的成像组件。

我已经仔细检查了我的Base64字符串,事实上,通过使用在线Base64解码器,我知道它不是正确的Base64编码。
我的代码:

byte[] binaryData = Convert.FromBase64String(desc.Icon_Path);
MemoryStream ms = new MemoryStream(binaryData, 0, binaryData.Length);
ms.Write(binaryData, 0, binaryData.Length);
System.Drawing.Image image = System.Drawing.Image.FromStream(ms, true);
icon.Source = ToWpfImage(image);
ms.Dispose();

public BitmapImage ToWpfImage(System.Drawing.Image img)
{
  MemoryStream ms = new MemoryStream();
  img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);

  BitmapImage ix = new BitmapImage();
  ix.BeginInit();
  ix.CacheOption = BitmapCacheOption.OnLoad;
  ix.StreamSource = ms;
  ix.EndInit();
  return ix;
}

我做错了什么?

44u64gxh

44u64gxh1#

考虑到Base64字符串包含一个可以由WPF的BitmapDecoders之一解码的编码图像缓冲区,您不需要比以下代码更多的代码:

public static BitmapSource BitmapFromBase64(string b64string)
{
    var bytes = Convert.FromBase64String(b64string);

    using (var stream = new MemoryStream(bytes))
    {
        return BitmapFrame.Create(stream,
            BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
    }
}
f4t66c6m

f4t66c6m2#

我想你不需要短信了,是吗?如果你这样做,你需要在写操作后设置ms.position = 0。这是因为在写入之后,流位置将在末尾。

yqkkidmi

yqkkidmi3#

来自hereConvert.FromBase64StringLoadImage函数就是您所需要的。请参见下面的示例。

// MainWindow.xaml
<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="400" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <!--Using data binding-->
        <Image Grid.Row="0" Source="{Binding ImageSource}" />
        <!--Using Code behind-->
        <Image Grid.Row="1" x:Name="Icon" />
    </Grid>
</Window>

下面是后面的代码。

// MainWindow.xaml.cs
using System;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();    
        var mainWindowVm = new MainWindowViewModel();
        DataContext = mainWindowVm;

        byte[] buffer = File.ReadAllBytes(@"C:\temp\icon.jpg");
        string base64String = Convert.ToBase64String(buffer, 0, buffer.Length);

        // Option 1
        byte[] binaryData = Convert.FromBase64String(base64String);
        Icon.Source = MainWindowViewModel.LoadImage(binaryData);    
        // Option 2
        mainWindowVm.SetImageSource(Convert.FromBase64String(base64String));    
        // Option 3
        // mainWindowVm.SetImageSource(File.ReadAllBytes(@"C:\temp\icon.jpg"));
    }
}

public class MainWindowViewModel : INotifyPropertyChanged
{
    private ImageSource _imageSource;

    public ImageSource ImageSource
    {
        get { return _imageSource; }
        set
        {
            _imageSource = value;
            OnPropertyChanged("ImageSource");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void SetImageSource(byte[] imageData)
    {
        // You can also call LoadImage from here.
        var image = new BitmapImage();
        image.BeginInit();
        image.StreamSource = new MemoryStream(imageData);
        image.EndInit();    
        ImageSource = image;
    }

    public static BitmapImage LoadImage(byte[] imageData)
    {
        if (imageData == null || imageData.Length == 0) return null;
        var image = new BitmapImage();
        using (var mem = new MemoryStream(imageData))
        {
            mem.Position = 0;
            image.BeginInit();
            image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.UriSource = null;
            image.StreamSource = mem;
            image.EndInit();
        }
        image.Freeze();
        return image;
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}
mbjcgjjk

mbjcgjjk4#

我写了一个转换器,它读取base64部分并返回一个字节数组。WPF Image控件默认情况下可以处理此问题,并将显示该字节串中的图像。

using System.Globalization;
using System.Linq;
using System.Windows.Data;

public class DataUrlToByteArrayConverter : IValueConverter
{
    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
    {
        if ( value is not string s ) return Binding.DoNothing;
        if ( s.StartsWith( "data:" ) && s.Contains( ";base64," ) )
        { // we have a data-url with base64 encoding
            var base64str = s.Split( ";base64," ).Last();
            return System.Convert.FromBase64String( base64str );
        }
        return Binding.DoNothing;
    }

    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
    {
        throw new NotImplementedException();
    }
}

可以在视图中使用它

<Window.Resources>
    <conv:DataUrlToByteArrayConverter x:Key="DataUrlToByteArray" />
</Window.Resources>

<Image Source="{Binding Image, Converter={StaticResource DataUrlToByteArray}}" />

相关问题