C# 如何在windows 10 uwp中有效地使用WriteableBitmap.setpixel()?

C# 如何在windows 10 uwp中有效地使用WriteableBitmap.setpixel()?,c#,winrt-xaml,windows-10,uwp,writablebitmap,C#,Winrt Xaml,Windows 10,Uwp,Writablebitmap,我有一个场景 选择图像文件,然后使用位图解码器转换 将source设置为WriteableBitmap,并将image.source设置为 可写位图 现在,当用户点击图像时,我得到坐标,然后 要用颜色标记该像素周围的整个区域吗 特定颜色(如“paint”中的填充选项) 我使用的代码是 private void setPixelColors(int xCord, int yCord, int newColor) { Color color = bit.GetPixel(xCord,

我有一个场景

  • 选择图像文件,然后使用位图解码器转换 将source设置为WriteableBitmap,并将image.source设置为 可写位图
  • 现在,当用户点击图像时,我得到坐标,然后 要用颜色标记该像素周围的整个区域吗 特定颜色(如“paint”中的填充选项)
我使用的代码是

 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);
 }
private void setPixelColors(int xCord、int yCord、int newColor)
{
Color Color=bit.GetPixel(xCord,yCord);

如果(color.R首先,我看不出如何检查xCord或yCord是否超出位图边界和要填充的区域。您知道要预先填充的抽头区域的形状吗?例如,如果它有一个椭圆形,是否更容易调用FillEllipse?或者如果是矩形-FillRect

第二,我相信递归算法效率很低。当然,它会拒绝已经处理过的像素,不会进行无用的SetPixel调用,但它会进行许多错误检查,因为它仍然会获取像素,对其进行分析,并生成复活调用

试着可视化它。如果你有一个位图10x10,并且你在中间(5;5),甚至在第一个像素被设置之前(它是10的像素;5),你将有5个递归调用,并且它们中的每一个产生另外4个调用等等。并且每个调用将访问位图,取像素和花费处理器时间。 作为一个小小的改进,请尝试将SetPixel调用置于递归调用之前:

bit.SetPixel(xCord, yCord, newColor);
setPixelColors(xCord + 1, yCord, newColor);
setPixelColors(xCord, yCord + 1, newColor);
setPixelColors(xCord - 1, yCord, newColor);
setPixelColors(xCord, yCord - 1, newColor);

但我认为你必须改变整个想法。当使用位图时,递归算法不是最好的主意。

首先,我看不出你如何检查xCord或yCord是否超出位图边界和要填充的区域。你知道要提前填充的抽头区域的形状吗?例如,如果它有一个椭圆形状,调用FillEllipse不是更容易吗?或者如果是矩形-FillRect

第二,我相信递归算法效率很低。当然,它会拒绝已经处理过的像素,不会进行无用的SetPixel调用,但它会进行许多错误检查,因为它仍然会获取像素,对其进行分析,并生成复活调用

试着可视化它。如果你有一个位图10x10,并且你在中间(5;5),甚至在第一个像素被设置之前(它是10的像素;5),你将有5个递归调用,并且它们中的每一个产生另外4个调用等等。并且每个调用将访问位图,取像素和花费处理器时间。 作为一个小小的改进,请尝试将SetPixel调用置于递归调用之前:

bit.SetPixel(xCord, yCord, newColor);
setPixelColors(xCord + 1, yCord, newColor);
setPixelColors(xCord, yCord + 1, newColor);
setPixelColors(xCord - 1, yCord, newColor);
setPixelColors(xCord, yCord - 1, newColor);

但是我认为你必须改变整个想法。使用位图时,递归算法不是最好的主意。

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

WriteableBitmapEx将在多个调用之间共享BitmapContext(如果您先获取BitmapContext并保留实时引用)。这将大大加快仅读取一次PixelBuffer、进行所有更改,然后仅写回一次

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

这里有一个示例代码,它将给出关于

比如:

 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);
 }
private void setPixelColors(int xCord、int yCord、int newColor)
{
使用(bit.GetBitmapContext())
{
_SetPixelColor(xCord、yCord、newColor);
}
}
私有void_setPixelColors(int xCord、int yCord、int newColor)
{
Color Color=bit.GetPixel(xCord,yCord);

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

WriteableBitmapEx将在多个调用之间共享BitmapContext(如果您先获取BitmapContext并保留实时引用)。这将大大加快仅读取一次PixelBuffer、进行所有更改,然后仅写回一次

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

这里有一个示例代码,它将给出关于

比如:

 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);
 }
private void setPixelColors(int xCord、int yCord、int newColor)
{
使用(bit.GetBitmapContext())
{
_SetPixelColor(xCord、yCord、newColor);
}
}
私有void_setPixelColors(int xCord、int yCord、int newColor)
{
Color Color=bit.GetPixel(xCord,yCord);

如果(color.R)是太慢,还是浪费太多内存,还是…?一种可能的优化方法是使用哈希表映射您已经访问过的坐标,这样您就可以跳过整个GetPixel调用,如果坐标是您已经访问过的坐标,则立即返回。太慢了。但是您不认为第一个if条件已经解决了吗这一部分。位的实际类型是什么?UWP中的WriteableBitmap没有SetPixel方法。它属于Windows.UI.Xaml.Media.Imaging类型