如何在 Windows 10 uwp 中有效地使用 WriteableBitmap.setpixel()? [英] How to use WriteableBitmap.setpixel() efficiently in windows 10 uwp?

查看:20
本文介绍了如何在 Windows 10 uwp 中有效地使用 WriteableBitmap.setpixel()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个场景

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

我使用的代码是

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

这行得通,但效率极低.我想知道有没有更好的方法来做到这一点.

This works but is terribly ineffecient. I'd like to know is there a better method to do this.

使用库 WriteableBitmapEx.

Using the library WriteableBitmapEx.

推荐答案

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

The GetPixel and SetPixel extension methods are very expensive for multiple iterative changes, since they extract the BitmapContext (the WriteableBitmap's PixelBuffer), make the change, and then writes back the updated PixelBuffer when the call is done with the BitmapContext.

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

WriteableBitmapEx will share the BitmapContext between multiple calls if you get it first and keep a live reference. This will be significantly faster to read out the PixelBuffer only once, make all of the changes, and then write it back only once.

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

To do this, use WriteableBitmapEx's BitmapContext object (reachable via the GetBitmapContext extension method) to extract the PixelBuffer then call Get and SetPixel as often as needed on the bitmap context. When done with it, Dispose the BitmapContext to save it back into the WriteableBitmap's PixelBuffer (it'll generally be easier to auto-Dispose the BitmapContext via a using statement).

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

类似于:

 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 一个简单的方法是保持与此处基本相同的结构,但不是递归处理每个新像素,而是明确处理要编辑的像素堆栈.如果你知道你的目标是小区域,那么它本身可能就足够快了.为了支持更大的,您可能需要进一步优化.

This should get the overall speed reasonable, but (as Alex suggests) you should look into non-recursive flood fill algorithms, especially if you have large bitmaps. The recursive algorithm will overflow the stack for large fills. There are a few fairly easy options on Wikipedia: https://en.wikipedia.org/wiki/Flood_fill#Alternative_implementations A simple one is to keep basically the same structure you have here but instead of recursing to handle each new pixel, explicitly handle the stack of to-be-edited pixels. If you know you are targeting small areas then that will probably be fast enough on its own. To support larger ones you may want to optimize further.

这篇关于如何在 Windows 10 uwp 中有效地使用 WriteableBitmap.setpixel()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆