Win2Dを使用したUWPアプリケーションでのグラフィック効果の使用







会う: Win2Dは、DirectX機能をより便利に使用するための使いやすいWindowsランタイムAPIです。 グラフィックはGPUアクセラレーションで描画されます。 Win2Dは、Windows 8.1およびWindows 10の両方で、C#、C ++、およびVB開発者が利用できます。



Win2Dを使用すると、図形、線、テキスト、画像を描画したり、これらすべてにさまざまな効果を追加したりできます。 さらに、ビデオ画像にいくつかの効果を追加できます。



主なライブラリ機能の例を検討することを提案します。



NuGetパッケージマネージャーを使用して、Visual StudioからWin2D.uwpをインストールできます。 このオープンソースプロジェクトのgithubページはこちらです。 英語のドキュメントはこちら: Win2Dのドキュメント



XAMLヘッダーでページを設定した後、次を追加できます。



xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
      
      





ページレイアウトでは、CanvasControlコントロールは次のことを行います。



 <canvas:CanvasControl Width="500" Height="300" x:Name="canv" Draw="CanvasControl_Draw" ClearColor="LightGray"/>
      
      





これは同じCanvas要素ではなく、ページレイアウト要素であり、他の要素をホストとして含めることができます。 CanvasとCanvasControlにはいくつかの類似点がありますが、パフォーマンスは完全に異なります。



CanvasControl要素を描画すると、Drawイベントが発生します。この例では、CanvasControl_Drawイベントハンドラーが割り当てられています。 公式の例では、最初に図(楕円)とテキストを描画することを提案しています。



 void CanvasControl_Draw(CanvasControl sender, CanvasDrawEventArgs args) { args.DrawingSession.DrawEllipse(155, 115, 80, 30, Colors.Black, 3); args.DrawingSession.DrawText("Hello, world!", 100, 100, Colors.Yellow); }
      
      





結果は次のとおりです。







メモリリークを回避するには、常にリソースを正しく破棄する必要があります。 これは通常、ページがアンロードされるときに行われます。



 void Page_Unloaded(object sender, RoutedEventArgs e) { this.canv.RemoveFromVisualTree(); this.canv = null; }
      
      





これまでのところ、異常なことは何もありません。 XAMLシェイプを使用して同じものを描画できます。 ちなみに、通常のXAMLでの描画の例は次の場所にあります。



画像を操作してみましょう。 これははるかに興味深いです。 プロジェクトにmydog.jpgファイルを追加し、プロパティで「コンテンツ」アセンブリのアクションを選択しました(正確には、選択すらしませんでした-デフォルトで選択されました)。



Microsoft.Graphics.Canvas名前空間のCanvasBitmapクラスは、Win2Dの画像を処理します。 cbiという変数をアプリケーションに追加します。



 CanvasBitmap cbi;
      
      





イメージは、CreateResourcesというCanvas要素のイベント中にロードされるため、このイベントをXAMLコードに追加します。



 <canvas:CanvasControl Width="500" Height="300" x:Name="canv" Draw="CanvasControl_Draw" CreateResources="CanvasControl_CreateResources" ClearColor="LightGray"/>
      
      





ダウンロード自体は、次のコードを使用して実行されます。



 cbi = await CanvasBitmap.LoadAsync(sender, "mydog.jpg");
      
      





非同期に発生するため、別のタスクに入れるように勧められています。



 private void CanvasControl_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(CreateResourcesAsync(sender).AsAsyncAction()); } async Task CreateResourcesAsync(CanvasControl sender) { cbi = await CanvasBitmap.LoadAsync(sender, "mydog.jpg"); }
      
      





この場合のTrackAsyncActionでは、CreateResourcesの終了前にCreateResourcesAsyncタスクを完了する必要があります。 Canvasにロードするために残ります:



 private void CanvasControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { args.DrawingSession.DrawImage(cbi); }
      
      









ロードされましたが、写真を表示するだけではあまり面白くありません。 コードを数行追加するだけで、ガウスぼかし効果が得られます



 var blur = new GaussianBlurEffect(); blur.BlurAmount = 1.7f; blur.Source = cbi; args.DrawingSession.DrawImage(blur);
      
      









効果の完全なリストは、ドキュメントのMicrosoft.Graphics.Canvas.Effects名前空間の説明ページで入手できます。 ところで、エフェクトはLumia Imaging SDKを使用して作成することもできます 。 Lumia-imaging-sdkのソースコードもGitHubにあります 。 さらに、 Windows.UI.Composition名前空間を使用していくつかの効果を利用できます。



グラフィックをすぐにではなく、プログラムの実行中に表示することが必要になる場合があります。 ファイルに保存、表示、またはピクセルの配列を取得します。 このオプションは、オフスクリーン描画と呼ばれます。



たとえば、XAML CanvasControl要素をまったく使用せず、単純な画像要素を使用する例です



 <Image x:Name="img" Width="500" Height="300"></Image>
      
      





次のように、画像を処理して表示し、彩度効果を追加できます。



 CanvasDevice device = CanvasDevice.GetSharedDevice(); CanvasRenderTarget offscreen = new CanvasRenderTarget(device, 500, 300, 96); cbi = await CanvasBitmap.LoadAsync(device, "mydog.jpg"); using (var ds = offscreen.CreateDrawingSession()) { var satur = new SaturationEffect(); satur.Saturation = 0.2f; satur.Source = cbi; ds.DrawImage(satur); } using (var stream = new InMemoryRandomAccessStream()) { stream.Seek(0); await offscreen.SaveAsync(stream, CanvasBitmapFileFormat.Png); BitmapImage image = new BitmapImage(); image.SetSource(stream); img.Source = image; }
      
      





私はそれがさらに好きです(パフォーマンスの比較については何も言えませんが)







小さな構図を構成し、画像にテキストを課すには、名前空間が必要です。



 using Microsoft.Graphics.Canvas.Text;
      
      





そして同様のスニペット:



 CanvasDevice device = CanvasDevice.GetSharedDevice(); CanvasRenderTarget offscreen = new CanvasRenderTarget(device, 500, 300, 96); cbi = await CanvasBitmap.LoadAsync(device, "mydog.jpg"); using (var ds = offscreen.CreateDrawingSession()) { ds.DrawImage(cbi); var format = new CanvasTextFormat() { FontSize = 32, HorizontalAlignment = CanvasHorizontalAlignment.Left, VerticalAlignment = CanvasVerticalAlignment.Top, WordWrapping = CanvasWordWrapping.Wrap, FontFamily = "Decor", }; using (CanvasTextLayout tl = new CanvasTextLayout(ds, "10  2010", format, 250, 50)) //  250   50 { ds.DrawTextLayout(tl, 10, 10, Color.FromArgb(120, 20, 20, 20)); } format.Dispose(); } using (var stream = new InMemoryRandomAccessStream()) { stream.Seek(0); await offscreen.SaveAsync(stream, CanvasBitmapFileFormat.Png); BitmapImage image = new BitmapImage(); image.SetSource(stream); img.Source = image; }
      
      









ブレンド効果を使用して2つの画像を組み合わせることができます。



 CanvasBitmap cbi; CanvasBitmap cbi2; CanvasDevice device = CanvasDevice.GetSharedDevice(); CanvasRenderTarget offscreen = new CanvasRenderTarget(device, 500, 300, 96); cbi = await CanvasBitmap.LoadAsync(device, "mydog.jpg"); cbi2 = await CanvasBitmap.LoadAsync(device, "present.png"); using (var ds = offscreen.CreateDrawingSession()) { BlendEffect blendEffect = new BlendEffect() { Background = cbi, Foreground = cbi2, Mode = BlendEffectMode.SoftLight }; ds.DrawImage(blendEffect); } using (var stream = new InMemoryRandomAccessStream()) { stream.Seek(0); await offscreen.SaveAsync(stream, CanvasBitmapFileFormat.Png); BitmapImage image = new BitmapImage(); image.SetSource(stream); img.Source = image; }
      
      









いくつかの効果を組み合わせることができます。 多くの効果を組み合わせた次のスニペットを使用して、テキストグローの効果を得ることができます



 var myTextBitmap = new CanvasRenderTarget(sender, 300, 100); using (var ds = myTextBitmap.CreateDrawingSession()) { ds.Clear(Color.FromArgb(0, 0, 0, 0)); ds.DrawText(" !", 0, 0, Colors.White, new CanvasTextFormat { FontSize = 24, FontWeight = Windows.UI.Text.FontWeights.Bold }); } var effectGraph = new CompositeEffect(); effectGraph.Mode = CanvasComposite.Add; effectGraph.Sources.Add(new ColorMatrixEffect { Source = new GaussianBlurEffect { Source = new MorphologyEffect { Source = myTextBitmap, Mode = MorphologyEffectMode.Dilate, Width = 7, Height = 4 }, BlurAmount = 3f }, ColorMatrix = new Matrix5x4 { M11 = 0f, M12 = 0f, M13 = 0f, M14 = 0f, M21 = 0f, M22 = 0f, M23 = 0f, M24 = 0f, M31 = 0f, M32 = 0f, M33 = 0f, M34 = 0f, M41 = 0f, M42 = 1f, M43 = 0f, M44 = 1f, M51 = 1f, M52 = -0.5f, M53 = 0f, M54 = 0f } }); effectGraph.Sources.Add(myTextBitmap); args.DrawingSession.DrawImage(effectGraph,100,100);
      
      









多くの場合Win2Dに関連付けられている興味深いテキスト効果は、テキストの書き込みのアニメーション効果です。







BurningTextExample.xamlおよびBurningTextExample.xaml.csの例への直接リンク私はおそらくここに残します: BurningTextExample.xaml / BurningTextExample.xaml.cs



UWP Community Toolkitの場合と同様に、Win2Dの使用例を含むアプリケーションをダウンロードできます。 このアプリケーションは、 Win2D Example Galleryと呼ばれます 。 アプリケーションのソースコードはgithubにあります。



個人的に、私は何よりも次の写真が好きでした:







結局のところ、DrawLine、DrawEllipse、DrawCircleなどを使用して完全に描画されます。



ライブラリは定期的に更新されるため、新しい美しい効果が期待できます。



All Articles