Silverlight Image:如何反转或否定图像颜色?

时间:2010-10-06 15:50:52

标签: silverlight image-manipulation

问题是如何反转Silverlight Image元素的颜色。

有一张以JPG作为来源的图片。在按钮上单击我需要反转颜色。听起来很简单,对。取每个像素,然后将其值修改为255 - 像素值。但是当我尝试使用Image源加载WritableBitmap时,我获得了禁止像素访问的安全异常。 这是我的代码:

            if (MainLeftImage.Source != null)
            {
                WriteableBitmap bitmap = new WriteableBitmap((BitmapSource)MainLeftImage.Source);
                byte[] pixels = new byte[bitmap.Pixels.Length];

                int size = pixels.Count();
                for (int i = 0; i < size; i++)
                    pixels[i] = (byte)(255 - pixels[i]);

                bitmap.Invalidate();//redraw and then plug it back on

                MainLeftImage.Source = bitmap;
            }
        }
        catch (Exception ex)
        {
        }

看起来WritableBitmap不是解决方案,对吧? 任何帮助赞赏。谢谢你们。

3 个答案:

答案 0 :(得分:3)

最简单的反转图像的方法是应用像素着色器效果。我相信WPF Pixel Shader Effects Library中有一个反转颜色像素着色器。

您遇到安全例外的原因是WriteableBitmap阻止像素访问跨域内容。要理解为什么这很重要,您可以在this answer中看到我对客户端访问策略文件的必要性的解释。要理解图像的要点,只需在示例中将“secretaccountdetails.html”替换为“myPrivatePhoto.jpg”。

如果您真的想使用WriteableBitmap访问Image的像素,请执行以下操作之一:
1.确保图像源与应用程序在同一域中提供 或
2.确保从中提供映像的服务器提供适当的client access policy并将映像文件下载为Stream。使用BitmapSource.SetSource(Stream)设置Image的来源,而不是将其设置为图像的URL。

在上述两种情况下,您都可以访问WriteableBitmap中图像的像素。

答案 1 :(得分:0)

是的,这似乎是对WritableBitmap的一个非常愚蠢的限制。我不确定他们试图阻止那种情况。我相信,只要您访问跨域内容,就会抛出特定的异常,如果JPEG来自完全托管Silverlight应用程序的服务器,它可能会有效。见这里:

http://forums.silverlight.net/forums/t/118030.aspx

但我真的不确定所有可能的原因。

一种选择是使用FJCore库将JPEG图像解码为位图,在解码的位图上翻转像素,然后将生成的位图直接加载到图像中。

http://code.google.com/p/fjcore/

答案 2 :(得分:0)

您需要像提出的其他答案一样解决跨域访问问题。 但是你的算法也有失败。 WriteableBitmap.Pixels数组将每个像素存储为整数值。 int的4个字节表示像素(ARGB)的alpha,red,green和blue分量。你应该像这样实现它:

 int[] pixels = bitmap.Pixels;
 int size = pixels.Length;
 for (int i = 0; i < size; i++)
 {
        // Extract color components
        var c = pixels[i];
        var a = 0x000000FF & (c >> 24);
        var r = 0x000000FF & (c >> 16);
        var g = 0x000000FF & (c >> 8);
        var b = 0x000000FF & (c);

        // Invert
        r = 0x000000FF & (0xFF - r);
        g = 0x000000FF & (0xFF - g);
        b = 0x000000FF & (0xFF - b);

        // Set result color
        pixels[i] = (a << 24) | (r << 16) | (g << 8) | b;
 }

正如其他人提议的那样,您可以使用像素着色器效果。但是你必须在Image控件中显示图片才能将着色器应用到它。之后,您可以将结果呈现为WriteableBitmap。

var wb = new WriteableBitmap(myImageUiElement, null);