c# - 如何在 Windows 10 uwp 中有效地使用 WriteableBitmap.setpixel()?

标签 c# winrt-xaml windows-10 uwp writablebitmap

我有一个场景

  • 选择一个图像文件,然后使用 BitmapDecoder 转换 source 到 WriteableBitmap 并将 image.source 设置为 可写位图。
  • 现在,当用户点击图片时,我会得到坐标,然后 想要为该像素周围的整个区域着色 特定颜色。(如油漆中的填充选项)。

我用过的代码是

 private void setPixelColors(int xCord, int yCord, int newColor)
 {
    Color color = bit.GetPixel(xCord, yCord);
    if (color.R <= 5 && color.G <= 5 && color.B <= 5 || newColor == ConvertColorToInt(color))
    {
        //Debug.WriteLine("The color was black or same returning");
        return;
    }
    setPixelColors(xCord + 1, yCord, newColor);
    setPixelColors(xCord, yCord + 1, newColor);
    setPixelColors(xCord - 1, yCord, newColor);
    setPixelColors(xCord, yCord - 1, newColor);
    //Debug.WriteLine("Setting the color here");
    bit.SetPixel(xCord, yCord, newColor);
 }

这有效但非常低效。我想知道是否有更好的方法来做到这一点。

编辑:使用库 WriteableBitmapEx。

最佳答案

GetPixel 和 SetPixel 扩展方法对于多次迭代更改非常昂贵,因为它们提取 BitmapContext(WriteableBitmap 的 PixelBuffer),进行更改,然后在使用 BitmapContext 完成调用时写回更新的 PixelBuffer。

WriteableBitmapEx 将在多个调用之间共享 BitmapContext 如果您先获取它并保留实时引用。如果只读出 PixelBuffer 一次,进行所有更改,然后仅将其写回一次,速度会快得多。

为此,使用 WriteableBitmapEx 的 BitmapContext对象(可通过 GetBitmapContext 扩展方法访问)提取 PixelBuffer,然后根据需要在位图上下文中调用 Get 和 SetPixel。完成后,处理 BitmapContext 以将其保存回 WriteableBitmap 的 PixelBuffer(通过 using 语句自动处理 BitmapContext 通常会更容易)。

https://github.com/teichgraf/WriteableBitmapEx 的 WriteableBitmapEx GitHub 上有示例代码可以给出总体思路。

类似于:

 private void setPixelColors(int xCord, int yCord, int newColor)
 {
     using (bit.GetBitmapContext())
     {
         _setPixelColors(xCord, yCord, newColor);
     }
 }
 private void _setPixelColors(int xCord, int yCord, int newColor)
 {
    Color color = bit.GetPixel(xCord, yCord);
    if (color.R <= 5 && color.G <= 5 && color.B <= 5 || newColor == ConvertColorToInt(color))
    {
        //Debug.WriteLine("The color was black or same returning");
        return;
    }
    setPixelColors(xCord + 1, yCord, newColor);
    setPixelColors(xCord, yCord + 1, newColor);
    setPixelColors(xCord - 1, yCord, newColor);
    setPixelColors(xCord, yCord - 1, newColor);
    //Debug.WriteLine("Setting the color here");
    bit.SetPixel(xCord, yCord, newColor);
 }

这应该使总体速度合理,但是(正如 Alex 所建议的那样)您应该研究非递归洪水填充算法,尤其是当您有大位图时。递归算法将溢出堆栈以进行大量填充。维基百科上有一些相当简单的选项:https://en.wikipedia.org/wiki/Flood_fill#Alternative_implementations一个简单的方法是保持与此处基本相同的结构,但不是递归处理每个新像素,而是显式处理待编辑像素的堆栈。如果您知道您的目标是小区域,那么它本身可能就足够快了。为了支持更大的,您可能需要进一步优化。

关于c# - 如何在 Windows 10 uwp 中有效地使用 WriteableBitmap.setpixel()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32903841/

相关文章:

c# - 如何动态填充 TreeView (C#)

gridview - 如何在 Windows Phone 8.1 WinRT 中启用 GridView 的左右滚动?

c# - Windows RT 和 C#

windows-8 - ScrollViewer 和处理子元素上的操作事件

c# - Windows 版本在设计中显示出真正的值(value),但在我运行程序时显示出不同的值(value)

docker - windows 10系统安装nvidia-docker的问题

azure - "Join this device to Azure Active Directory"使用 powerShell

c# - 将方法作为参数传递以便稍后可以调用该方法?

c# - 为什么 C# 中的基类允许在不继承接口(interface)契约的情况下实现接口(interface)契约?

c# - 使用 C# 的 Interface<T> 接口(interface)