Silverlight:将BitmapImage转换为WriteableBitmap

7
我可以像这样成功加载以下位图,并在视图上的Image控件中显示它。
var bitmapImage = new BitmapImage
                            {
                                UriSource = 
                                    new Uri("../Images/Test.JPG", UriKind.Relative)
                            };

然而,一旦我添加了这行代码来创建一个可写的 WriteableBitmap,

    var w = new WriteableBitmap(bitmapImage);

我在上面的代码行中遇到了一个运行时错误:"对象引用未设置为对象的实例"。

似乎BitmapImage的创建被延迟了,这可能是原因吗?我该如何解决这个问题?

更新:

我现在正在尝试这样做,但openImage似乎从未被执行过。(即使不尝试将其变成同步,它仍然失败)这里有什么问题?

var image = new BitmapImage();
        image.ImageOpened += (sender, args) => resetEventBitmap.Set();
        image.ImageFailed += (o, eventArgs) =>
                                 {
                                     resetEventBitmap.Set();
                                     throw eventArgs.ErrorException;
                                 };
        image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
        image.UriSource = uri;

        resetEventBitmap.WaitOne();

Thanks,

3个回答

6
参考链接:http://www.blog.ingenuitynow.net/Silverlight+Creating+A+WriteableBitmap+From+A+Uri+Source.aspx 基本上,位图图像有一个依赖属性 "CreateOptions",默认情况下设置为 "DelayCreation"。这会导致位图在渲染之前被延迟,直到它被需要。因此,这会导致我们出现 "对象引用没有设置到对象的实例" 错误。为了解决这个问题,我们需要将位图的创建从可写位图构造函数中分离出来,更改此选项,然后再将其放回去。在 VB.NET 中,代码如下:
    Dim tmpUri As New Uri(yourpath.ToString)
    Dim bmp As New BitmapImage
    bmp.CreateOptions = BitmapCreateOptions.None
    bmp.UriSource = tmpUri
    Dim wb As New WriteableBitmap(bmp)

3
    BitmapImage _classField;

    void LoadImageFunction()
    {
        _classField = new BitmapImage();
        _classField.ImageOpened += new EventHandler<RoutedEventArgs>(bi_ImageOpened);
        _classField.ImageFailed += new EventHandler<ExceptionRoutedEventArgs>(bi_ImageFailed);
        //sorry.. totally forgot about order :)
        _classField.UriSource = new Uri("../some/uri", UriKind.Relative);
    }

    void bi_ImageFailed(object sender, ExceptionRoutedEventArgs e)
    {
        //something has happend
        throw e.ErrorException;
    }

    void bi_ImageOpened(object sender, RoutedEventArgs e)
    {
        //image is loaded.. now we can work with it..
        var w = new WriteableBitmap(_classField);
    }

啊啊啊,这是异步的。:) 非常感谢你的帮助! - Houman
嗨,Ai_boy,不幸的是ImageOpened方法从未触发。我想事件必须在URi设置之前被订阅。但即使如此也不起作用。你有任何想法吗?这对你有效吗?请检查我在主贴中的更新。 - Houman
谢谢你的更新,伙计。我也已经更新了答案。它仍然不喜欢它。根据这个来源:http://forums.silverlight.net/forums/p/165007/450517.aspx 图像是延迟下载的,只有在使用时才会下载。通过停用缓存,应该会有所帮助,但对我来说仍然无法工作。事件从未被触发 :( - Houman
1
我找到了解决方案,仅使用UriSource无法触发加载。最简单的方法是在ViewModel上有一个绑定的图像属性,该属性绑定到View上的已折叠图像。只有这样才会使图像加载。 - Houman

1
img1 = new BitmapImage(new Uri("/PrjName;component/Images/image01.jpg", UriKind.RelativeOrAbsolute));
        img2 = new BitmapImage(new Uri("/PrjName;component/Images/image02.jpg", UriKind.RelativeOrAbsolute));
        img1.CreateOptions = BitmapCreateOptions.None;
        img2.CreateOptions = BitmapCreateOptions.None;
        img1.ImageOpened += new EventHandler<RoutedEventArgs>(img1_ImageOpened);
        img2.ImageOpened += new EventHandler<RoutedEventArgs>(img2_ImageOpened);


    void img2_ImageOpened(object sender, RoutedEventArgs e)
    {
        load2 = true;
    }

    void img1_ImageOpened(object sender, RoutedEventArgs e)
    {
        load1 = true;
    }

    private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
    {
        while (!load1 && !load2)
        { }
        WriteableBitmap x = new WriteableBitmap(img1);
        WriteableBitmap y = new WriteableBitmap(img2);
    }

这应该可以工作。对我来说确实如此。它使事情有点复杂,但这就是它的工作方式!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接