none
BitmapFrame 或BitmapDecoder解码PNG图片发生错误导致在XAML中不能显示 RRS feed

  • 问题

  •  <dxg:GridColumn FieldName="Member" IsSmart="True" ReadOnly="True" HorizontalHeaderContentAlignment="Center">
     <dxg:GridColumn.DisplayTemplate>
     <ControlTemplate>
     <StackPanel Orientation="Horizontal">
     <Image Name="PART_Editor" Height="18" Width="18" HorizontalAlignment="Left" Source="{Binding Path = RowData.Row.Level, ConverterParameter=GridControl, Converter={StaticResource myMemberConverter}, Mode=OneWay}" Stretch="Fill" VerticalAlignment="Top"/>
     <TextBlock Text="{Binding Path=RowData.Row.Member}" />
     </StackPanel>
     </ControlTemplate>
     </dxg:GridColumn.DisplayTemplate>
     </dxg:GridColumn>

    using System;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Media.Imaging;
    
    namespace Sundial.WPF.Controls
    {
       [ValueConversion(typeof(Logger.Levels), typeof(Image))]
        public class MemberToImageConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                Image image = new Image();
                if (parameter.ToString() == "GridControl")
                {
                    //BitmapFrame bf =  BitmapFrame.Create(new Uri("pack://application:,,,/Sundial.WPF.Controls.Vi;component/Logger/Images/Debug.18x18.png", UriKind.RelativeOrAbsolute));
                    Uri myUri = new Uri("pack://application:,,,/Sundial.WPF.Controls.Vi;component/Logger/Images/Debug.18x18.png", UriKind.RelativeOrAbsolute);
                    var decoder = PngBitmapDecoder.Create(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                    var bitmapFrame = decoder.Frames[0];
    
                    //if ((Logger.Levels)Enum.Parse(typeof(Logger.Levels), value.ToString()) == Logger.Levels.WARN)
                    // bi = new BitmapImage(new Uri("Vi/Logger/Images/Warn.18x18.png", UriKind.RelativeOrAbsolute));
    
                    //if ((Logger.Levels)Enum.Parse(typeof(Logger.Levels), value.ToString()) == Logger.Levels.INFO)
                    //bi = new BitmapImage(new Uri("pack://application:,,,/Sundial.WPF.Controls.Vi;component/Logger/Images/Info.18x18.png", UriKind.RelativeOrAbsolute));
                    //if ((Logger.Levels)Enum.Parse(typeof(Logger.Levels), value.ToString()) == Logger.Levels.FATAL)
                    // bi = new BitmapImage(new Uri("pack://application:,,,/Sundial.WPF.Controls.Vi;component/Logger/Images/Fatal.18x18.png", UriKind.RelativeOrAbsolute));
                    //if ((Logger.Levels)Enum.Parse(typeof(Logger.Levels), value.ToString()) == Logger.Levels.ERROR)
                    // bi = new BitmapImage(new Uri("pack://application:,,,/Sundial.WPF.Controls.Vi;component/Logger/Images/Error.18x18.png", UriKind.RelativeOrAbsolute));
    
                    image.Source = bitmapFrame;
    
                }
    
                return image;
            }
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotSupportedException();
            }
        }
    }
    调试时报错:bitmapFrame->Metadata {System.Windows.Media.Imaging.BitmapMetadata} System.Windows.Media.ImageMetadata ->+  InnerException {"位图编解码器不支持位图属性。 (异常来自 HRESULT:0x88982F41)"} System.Exception {System.Runtime.InteropServices.COMException},png图标不能正常显示。
    2017年5月4日 5:56

答案

全部回复

  • Hi,

    根据你的代码和描述,你的代码抛出一个FileFormatException : bitmapStream不是PNG编码图像。

    请检查:

    1. 图像的格式是否是PNG格式

    2. 检查Uri是否正确,检查是否读取到了图像

    建议使用try...catch语句块来捕获异常,另外建议使用PngBitmapDecoder构造函数来读取。

    因为这可能是一个bug。 请参考下面的bug提交的链接:

    PngBitmapDecoder.Create fails silently on non-seekable input stream

    https://connect.microsoft.com/VisualStudio/feedback/details/471472/pngbitmapdecoder-create-fails-silently-on-non-seekable-input-stream

    希望有帮助!

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年5月4日 7:09
    版主
  • 我做回复,但论坛老是提示:Body text cannot contain images or links until we are able to verify your account.的信息,问题是贴不了图片,请协助解决。
    2017年5月5日 1:44
  • 你好,

    >> Body text cannot contain images or links until we are able to verify your account

    如果你的账号不能上传图片和链接,请在下面的帖子进行回复,微软会对你的账户进行验证。

    Verify Your Account 38

    https://social.microsoft.com/Forums/en-US/054fddac-7164-4412-a077-f57ba5dd9e5d/verify-your-account-38?forum=reportabug

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年5月5日 3:12
    版主
  • Bob,您好!

      我做了个小实验,xaml中直接调用png图片,结果是能正常显示,代码如下:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApplication1"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <local:MemberToImageConverter x:Key="myMemberConverter">
            </local:MemberToImageConverter>
        </Window.Resources>
        <Grid>
            <Image x:Name="image"  Height="18" Width="18" HorizontalAlignment="Left"  Margin="105,90,0,0" VerticalAlignment="Top" Source="pack://application:,,,/WpfApplication1;component/Images/Debug.18x18.png" Stretch="Fill"/>
    
        </Grid>
    </Window>


    但如果通过MemberToImageConverter 类,采用BitmapImage或PngBitmapDecoder类则还是不能正常显示,我猜测框架可能存在bug。我的实验代码如下:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApplication1"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <local:MemberToImageConverter x:Key="myMemberConverter">
            </local:MemberToImageConverter>
        </Window.Resources>
        <Grid>
            <Image x:Name="image"  Height="18" Width="18" HorizontalAlignment="Left"  Margin="105,90,0,0" VerticalAlignment="Top" Source="{Binding Converter={StaticResource myMemberConverter}, Mode=OneWay}" Stretch="Fill"/>
    
        </Grid>
    </Window>
    using System;
    using System.IO;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Media.Imaging;
    
    namespace WpfApplication1
    {
        public class MemberToImageConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                Image image = new Image();
                image.Margin = new Thickness(5);
                string path = @"D:\Debug.18x18.png";
                    try
                    {
                    //BitmapFrame bf =  BitmapFrame.Create(new Uri("pack://application:,,,/Sundial.WPF.Controls.Vi;component/Logger/Images/Debug.18x18.png", UriKind.RelativeOrAbsolute));
                    //Uri myUri = new Uri("pack://application:,,,/WpfApplication1;component/Images/Debug.18x18.png", UriKind.RelativeOrAbsolute);
                    //var decoder = new PngBitmapDecoder(new Uri(@"D:\Debug.18x18.png", UriKind.RelativeOrAbsolute), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                    //var bitmapFrame = decoder.Frames[0];
                    using (BinaryReader loader = new BinaryReader(File.Open(path, FileMode.Open)))
                    {
                        FileInfo fd = new FileInfo(path);
                        int Length = (int)fd.Length;
                        byte[] buf = new byte[Length];
                        buf = loader.ReadBytes((int)fd.Length);
                        loader.Dispose();
                        loader.Close();
    
                        //开始加载图像  
                        BitmapImage bim = new BitmapImage();
                        bim.BeginInit();
                        bim.StreamSource = new MemoryStream(buf);
                        bim.EndInit();
                        image.Source = bim;
                        GC.Collect(); //强制回收资源 
                    }
    
                    //if ((Logger.Levels)Enum.Parse(typeof(Logger.Levels), value.ToString()) == Logger.Levels.WARN)
                    // bi = new BitmapImage(new Uri("Vi /Logger/Images/Warn.18x18.png", UriKind.RelativeOrAbsolute));
    
                    //if ((Logger.Levels)Enum.Parse(typeof(Logger.Levels), value.ToString()) == Logger.Levels.INFO)
                    //bi = new BitmapImage(new Uri("pack://application:,,,/Sundial.WPF.Controls.Vi;component/Logger/Images/Info.18x18.png", UriKind.RelativeOrAbsolute));
                    //if ((Logger.Levels)Enum.Parse(typeof(Logger.Levels), value.ToString()) == Logger.Levels.FATAL)
                    // bi = new BitmapImage(new Uri("pack://application:,,,/Sundial.WPF.Controls.Vi;component/Logger/Images/Fatal.18x18.png", UriKind.RelativeOrAbsolute));
                    //if ((Logger.Levels)Enum.Parse(typeof(Logger.Levels), value.ToString()) == Logger.Levels.ERROR)
                    // bi = new BitmapImage(new Uri("pack://application:,,,/Sundial.WPF.Controls.Vi;component/Logger/Images/Error.18x18.png", UriKind.RelativeOrAbsolute));
    
                   // image.Source = bi;
                    }
                    catch(Exception e)
                    {
                        MessageBoxResult result = MessageBox.Show(
                            "The Error: " + e.ToString(),
                            "Error",
                            MessageBoxButton.OK,
                            MessageBoxImage.Error,
                            MessageBoxResult.None,
                            MessageBoxOptions.DefaultDesktopOnly);
                    }
    
    
                return image;
            }
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotSupportedException();
            }
        }
    }
        
    


    2017年5月5日 8:14
  • Hi,

    根据我的理解,IValueConverter值转换不能直接转换Image控件,你需要转换Image的Source源,返回BitmapImage对象。

    你可以直接使用ImageSourceConverter转换器来根据路径来返回BitmapImage。如下代码所示:

    string path = @"C:\Content_Image.png";
    return (new ImageSourceConverter()).ConvertFromString(path);

    如果我有任何的误解,请给我反馈。

    Best Regards,

    Bob



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年5月5日 9:22
    版主
  • Bob:

           您好,我试了一下,结果未能显示。

     是否按照老的办法采用var decoder = new PngBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);

    能正常显示,我用的4.5.2的框架,不知框架是否有问题。

    2017年5月8日 6:55