问题是如何反转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不是解决方案,对吧? 任何帮助赞赏。谢谢你们。
答案 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图像解码为位图,在解码的位图上翻转像素,然后将生成的位图直接加载到图像中。
答案 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);