我有一个场景
- 选择一个图像文件,然后使用 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/