首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何处理用ImageSource创建的SkiaSharp中的工件

如何处理用ImageSource创建的SkiaSharp中的工件
EN

Stack Overflow用户
提问于 2017-09-14 18:20:03
回答 2查看 858关注 0票数 2

我创建了一个应用程序,我想在谷歌地图上显示文本。我选择使用自定义标记,但它们只能是图像,所以我决定使用SkiaSharp从文本中创建一个图像。

代码语言:javascript
运行
复制
private static ImageSource CreateImageSource(string text)
    {
        int numberSize = 20;
        int margin = 5;
        SKBitmap bitmap = new SKBitmap(30, numberSize + margin * 2, SKImageInfo.PlatformColorType, SKAlphaType.Premul);
        SKCanvas canvas = new SKCanvas(bitmap);

        SKPaint paint = new SKPaint
        {
            Style = SKPaintStyle.StrokeAndFill,
            TextSize = numberSize,
            Color = SKColors.Red,
            StrokeWidth = 1,
        };

        canvas.DrawText(text.ToString(), 0, numberSize, paint);
        SKImage skImage = SKImage.FromBitmap(bitmap);
        SKData data = skImage.Encode(SKEncodedImageFormat.Png, 100);
        return ImageSource.FromStream(data.AsStream);
    }

然而,我创建的图像在结果图像的顶部有丑陋的工件,我的感觉是,如果我创建多个图像,它们会变得更糟。

我构建了一个示例应用程序,它显示了用于绘制文本的工件和代码。它可以在这里找到:https://github.com/hot33331/SkiaSharpExample

我怎么才能把这些文物处理掉。我是不是用错了?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-16 18:36:37

我从马修·莱博维茨在“SkiaSharp GitHub”上得到了以下答案:

很可能你没有先清除画布/位图。

您可以使用bitmap.Erase(SKColors.Transparent)或canvas.Clear(SKColors.Transparent) (您可以使用任何颜色)。

其原因在于性能。当创建一个新的位图时,计算机无法知道你想要什么背景颜色。因此,如果它是透明的,并且您想要白色,那么就会有两个绘制操作来清除像素(对于大型图像来说,这可能非常昂贵)。

在分配位图期间,提供内存,但实际数据不受影响。如果前面有任何内容(将有),则此数据将显示为彩色像素。

票数 3
EN

Stack Overflow用户

发布于 2017-09-15 00:23:33

当我以前看到这一点时,这是因为传递给SkiaSharp的内存不是零的。不过,作为优化,Skia假设传递给它的内存块是预零的。结果,如果第一个操作是清楚的,它将忽略该操作,因为它认为状态已经是干净的。要解决此问题,可以手动将传递给SkiaSharp的内存调零。

代码语言:javascript
运行
复制
public static SKSurface CreateSurface(int width, int height)
    {
        // create a block of unmanaged native memory for use as the Skia bitmap buffer.
        // unfortunately, this may not be zeroed in some circumstances.
        IntPtr buff = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(width * height * 4);

        byte[] empty = new byte[width * height * 4];

        // copy in zeroed memory.
        // maybe there's a more sanctioned way to do this.
        System.Runtime.InteropServices.Marshal.Copy(empty, 0, buff, width * height * 4);

        // create the actual SkiaSharp surface.
        var colorSpace = CGColorSpace.CreateDeviceRGB();
        var bContext = new CGBitmapContext(buff, width, height, 8, width * 4, colorSpace, (CGImageAlphaInfo)bitmapInfo);
        var surface = SKSurface.Create(width, height, SKColorType.Rgba8888, SKAlphaType.Premul, bitmap.Data, width * 4);

        return surface;
    }

编辑:顺便说一句,我认为这是SkiaSharp中的一个bug。为您创建缓冲区的示例/apis可能会将其归零。根据平台的不同,由于内存分配程序的行为不同,因此很难复制。或多或少有可能为你提供未触及的记忆。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46225886

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档