2017-09-14 13 views
2

私はGoogleマップの上にテキストを表示したいアプリケーションを作成しました。私はカスタムマーカーを使用することを選択しましたが、それらは画像でしかないので、私はSkiaSharpを利用して自分のテキストから画像を作成することにしました。私が作成SkiaSharpで作成したImageSourceでアーティファクトを取り除くにはどうすればいいですか

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

どのようにこれらのアーティファクトを取り除くことができます。スキアを間違って使用していますか?

+1

あなたの質問に関連コードを投稿してください。単に外部ソースにリンクして、コードを掘り下げる時間がかかると期待してください。また、「視覚的な成果物」について具体的に質問している場合は、問題を示すイメージを含めて、本当に良いアイデアになります。 – Jason

答えて

1

私はSkiaSharp GitHubの上のマシューLeibowitzから、次の答えを得た:

チャンスはあなたが最初にキャンバス/ビットマップをクリアしていないです。

bitmap.Erase(SKColors.Transparent)またはcanvas.Clear(SKColors.Transparent)(任意の色を使用できます)のいずれかを実行できます。

この理由はパフォーマンスです。新しいビットマップを作成するとき、コンピュータはあなたが望む背景色を知る方法がありません。したがって、透明にして白を欲しかった場合、ピクセルをクリアするために2回の描画操作が行われます(これは大きな画像では非常に高価になる可能性があります)。

ビットマップの割り当て中にメモリが提供されますが、実際のデータは変更されません。以前に何かが存在していた場合は、このデータは色付きのピクセルとして表示されます。

+0

これは新しく改良された行動だと私は思います。私が過去に見たことは、既に明確であると思われたため、新しいSkiaサーフェス上で明確な操作が無視されたことでした。新しいサーフェスに対してclearを呼び出すことが適切に機能する場合は、カバーの下でビヘイビアを修正する必要があります。これは素晴らしいことです。 –

1

SkiaSharpに渡されたメモリがゼロになっていないため、前に見ました。しかし、最適化として、Skiaは、渡されたメモリブロックが事前にゼロになっていると仮定します。その結果、最初の操作がクリアであれば、その操作は無視されます。これは、状態が既にクリーンであると考えられるためです。この問題を解決するには、SkiaSharpに渡されたメモリを手動でゼロにすることができます。

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

編集:btw、これはSkiaSharpのバグだと思われます。あなたのためのバッファを作成するサンプル/ apisおそらくそれをゼロにする必要があります。プラットフォームによっては、メモリの割り当てが異なるように再現するのが難しい場合があります。多かれ少なかれあなたの手の届かない記憶を提供する可能性があります。

関連する問題