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

发布于 2024-09-26 08:13:25 字数 814 浏览 0 评论 0原文

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

有一个以 JPG 为源的图像。单击按钮时我需要反转颜色。听起来很简单,对吧。获取每个像素,然后将其值修改为 255 - 像素值。但是,当我尝试使用图像源加载 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 不是一个解决方案,对吗? 任何帮助表示赞赏。谢谢你们。

The problem is how to invert colors of a Silverlight Image element.

There is an Image with a JPG as a source. On a button click I need to invert the colors. Sounds simple, right. Take each pixel, then modify it's value by 255 - pixel value. But when I tried WritableBitmap loaded with the Image source, I got security exception disallowing pixel access.
Here is my code:

            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)
        {
        }

Looks that WritableBitmap is not a solution, right?
Any help appreciated. Thanks guys.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

二智少女猫性小仙女 2024-10-03 08:13:25

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

您遇到安全异常的原因是 WriteableBitmap 阻止像素访问跨域内容。要了解为什么这很重要,您可以在 这个答案。要了解图像的要点,只需将示例中的“secretaccountdetails.html”替换为“myPrivatePhoto.jpg”即可。

如果您确实想使用 WriteableBitmap 来访问图像的像素,可以:
1. 确保图像源与应用程序来自同一域。

2. 确保提供图像的服务器提供适当的 客户端访问策略并将图像文件下载为流。使用 BitmapSource.SetSource(Stream) 设置图像的来源,而不是将其设置为图像的 URL。

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

Easiest way to invert an image would be to apply a pixel shader effect. I believe that there is an invert colors pixel shader in the WPF Pixel Shader Effects Library.

The reason that you are hitting the Security Exception is that WriteableBitmap prevents pixel access to cross-domain content. To understand why this is important, you can see my explanation of the necessity of client access policy files in this answer. To understand the point for images, just replace "secretaccountdetails.html" with "myPrivatePhoto.jpg" in the example.

If you really want to use a WriteableBitmap to access the pixels of an Image, either:
1. Make sure that the image source is served from the same domain as the application.
or
2. Make sure that the server from which the image is being served provides an appropriate client access policy and download the image file as a Stream. Use BitmapSource.SetSource(Stream) to set the source of the Image instead of setting it to the URL of the image.

In both of the above cases you will be able to access the pixels of an Image in a WriteableBitmap.

盛夏已如深秋| 2024-10-03 08:13:25

是的,这似乎是对 WritableBitmap 的一个非常愚蠢的限制。我不确定他们想阻止什么情况发生。我相信每当您访问跨域内容时都会引发特定的异常,并且如果 JPEG 恰好来自托管 Silverlight 应用程序的同一台服务器,则该异常可能会起作用。请参阅此处:

http://forums.silverlight.net/forums/t/118030.aspx< /a>

但老实说我不确定所有可能的原因。

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

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

Yeah, that seems like a pretty silly restriction on the WritableBitmap. I'm not sure what scenario they're trying to prevent there. I believe that particular exception gets thrown whenever you're accessing cross-domain content, and it might work if the JPEG is coming from exactly the same server that is hosting the Silverlight app. See here:

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

But I'm honestly not sure of all the possible causes.

One option would be to use the FJCore library to decode the JPEG image to a bitmap, do the pixel flipping on the decoded bitmap, and then load the resulting bitmap into an image directly.

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

眼波传意 2024-10-03 08:13:25

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

 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;
 }

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

var wb = new WriteableBitmap(myImageUiElement, null);

You need to solve the cross domain access like the other answers proposed.
But there's also a failure in your algorithm. The WriteableBitmap.Pixels array stores each pixel as integer value. The 4 bytes of the int represent the alpha, red, green and blue component of the pixel (ARGB). You should implement it like this:

 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;
 }

As others proposed, you can use a pixel shader effect instead. But you'll have to show the picture in an Image control in order to apply a shader to it. After that you can render the result into a WriteableBitmap.

var wb = new WriteableBitmap(myImageUiElement, null);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文