如何在AvaloniaUI中逐像素绘制位图?

3
我正在尝试编写一个绘图应用程序,允许用户在画布上选择两个点,并在这些点之间逐像素绘制一条线。在WinForms中,这将是一个简单的解决方案-创建一个画布,获取其位图,使用SetPixel方法在位图上绘制,并替换画布位图。我想知道是否有一种类似的方法可以在AvaloniaUI中实现?据我所知,它在幕后使用SkiaSharp。然而,渲染SKCanvasAvalonia.Controls.Canvas上的解决方案似乎很困难。虽然SKBitmap也具有SetPixel方法。问题不在于如何绘制线条-而在于如何在AvaloniaUI中的位图上设置单个像素,并将此位图设置为Avalonia.Controls.Canvas。 以下是我找到的一些链接:

P.S. 尽管官方文档示例中的逐个大小为 1x1 的矩形绘制(https://docs.avaloniaui.net/docs/controls/canvas)听起来很诱人,但大学也不允许这样做。

P.P.S.我并不是要求任何人替我完成作业-如果你担心这一点,请将其视为框架比较问题,而不是“请替我做这个”的问题。我已经找到并链接了可以使用的解决方案-只是我觉得应该有更简单的方法来实现我所需的结果。这就是我提出这个问题的原因-以防我错过了什么。
进行绝地教士的事情:这不是某个学生试图将他的工作推卸给其他人。你可以继续你的事情。

2
@LeeTaylor - 我可以使用SetPixel方法。不幸的是,在任何本地AvaloniaUI位图中都没有这样的方法。它在SkBitmapSystem.Drawing.Bitmap上,但是在不同位图类型之间进行转换似乎不是一个简洁的解决方案(我链接的示例展示了如何实现这一点)。关于绘制线条:这不是我的问题的一部分 - 您描述的所有内容实际上都是任务的一部分 - 使用SetPixel实现正确的线条绘制、抗锯齿和线条粗细修改算法。我知道如何做。 - Kiryl Volkau
1
@KirylVolkau 或许你可以使用 writeableBitmap?https://stackoverflow.com/questions/63209683/artifacts-on-avalonia-writeablebitmap-bitmapcontext - Lee Taylor
1
@LeeTaylor 哦,是的,谢谢。这也是我看过的解决方案之一,忘了引用它。这个解决方案使用 unsafe 代码进行像素复制,并需要三个额外的扩展方法。这确实是一个选项 - 不过,我认为框架应该有一些东西可以直接使用,而不需要用户重新发明轮子。我仍然希望我在文档中错过了什么,或者有一个大师知道“方法”。我还将在原始问题中添加此引用,并解释为什么这不是我要找的内容。 - Kiryl Volkau
1
既然你说你被任意限制只能使用名为SetPixel或一个一个设置像素的函数,那么这实际上似乎是一个关于如何从SkBitmapSystem.Drawing.Image转换为Avalonia图像的问题,因为后者不提供这样的方法。同时,你声称已经找到了解决方案,但似乎有困难使用它们 - 我建议通过指出你找到的代码并遇到的问题来集中精力解决这个问题,否则问题就太不清楚和无法回答了。 - Ray
@Ray,我理解你的观点,这个问题确实不太清楚 - 我认为我已经找到了主要答案:似乎无法在Avalonia位图上设置像素,唯一的解决方案是实际上在其他位图类型之间进行转换。虽然我真的不喜欢它。但是!这似乎是为开源项目做出贡献的绝佳机会。非常感谢大家(特别是清除了一些有争议的评论的管理员),现在关闭这个问题。 - Kiryl Volkau
1
@KirylVolkau 没问题。我认为 writeableBitmap 是一个值得探索的好方向。 - Lee Taylor
2个回答

0

更新:您可以在图像控件上交换位图:https://docs.avaloniaui.net/docs/controls/image

原始问题(虽然表述不清,是我的错)旨在澄清是否有一种方法可以在Avalonia位图上执行SetPixel操作。不幸的是,目前似乎没有这样的选项:因此唯一的方法是创建自定义绘图上下文或控件或在不同位图类型之间进行转换(例如来自SkiaSharpSystem.Drawing.BitmapSkBitmap)到Avalonia.WriteableBitmap。所有这些解决方案都在原始问题中提到。


0
您可以创建一个SKBitmap并根据需要进行绘制,然后使用以下方法将其转换为Avalonia Bitmap。
public Avalonia.Media.Imaging.Bitmap SKBitmapToAvaloniaBitmap(SKBitmap skBitmap)
{
    SKData data = skBitmap.Encode(SKEncodedImageFormat.Png, 100);
    using (Stream stream = data.AsStream())
    {
        return new Avalonia.Media.Imaging.Bitmap(stream);
    }
}


生成的位图可以使用绑定在 Image xaml 组件中显示。请注意,我使用了 PNG 编码格式而不是 BMP。我发现使用 `SKEncodedImageFormat.Bmp` 会导致返回 null 数据。这可能与 Windows 上的底层本机 BMP 编解码器不可用有关。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接