2016-11-23 21 views
0

私はWindows 10 Mobile上で動作するWindows 10 UWPアプリケーションを持っています。私が必要とするのは、ユーザーから署名を取得することです。これまでは、XAMLでInkCanvasを使用していて、コードを自分のコードに接続しています。WCFコールを使用してInkCanvas署名を送信する

このボタンをクリックすると、InkCanvasで署名が取得され、WCF呼び出しによってサーバーに送信されます。サーバーとWCFサービスは既に存在します。これは、base64の直列化された文字列として署名イメージを取り込みます。

イメージまたはバイト配列を取得したら、base64を取得する方法を知っています。しかし、読んでいるうちに記事やサンプルがWPFやWindows 8.1用に書かれていて、Windows 10 UWPで動作しないことが判明しました。また、私はそれが動作することがわかっている例のうち、私の唯一のオプションは、GIFとしてファイルに署名を保存することです。

私は私が私にInkStrokeの読み取り専用のリストを返します。この

var strokeCollection = cvsSignature.InkPresenter.StrokeContainer.GetStrokes(); 

ようGetStrokes()を呼び出すことができることがわかります。私はそのリストを繰り返し、バイト配列を作ることができると思いますか?どうすればいい?これは効率的ではないようですね?

それ以外の場合は、ストリームをファイルストリームからメモリストリームに変更できると思っていましたが、これは不可能であるか、または何か不足しています。私はこの

using (var inkMemStream = new MemoryStream()) 
{ 
    await cvsSignature.InkPresenter.StrokeContainer.SaveAsync(inkMemStream); 
} 

しかし、私は、私は

感謝をWindows.Storage.Streams.IOutputStreamするSystem.IO.MemoryStreamから変換することはできません例外を取得アプローチのこのタイプのをしようとしています!

答えて

1

InkCanvasをファイルやGIFに保存したくない場合、メモリ内で操作する方法がありました。私は実際に以下の3つの選択肢があります。これについては、正確な名前を検索してNuGetにあるWin2D.uwpへの参照を追加する必要があります。これはMicrosoftによって提供されます。

  1. バイト配列にInkCanvasを変換します

    private byte[] ConvertInkCanvasToByteArray() 
    { 
        //First, we need to get all of the strokes in the canvas 
        var canvasStrokes = myCanvas.InkPresenter.StrokeContainer.GetStrokes(); 
    
        //Just as a check, make sure to only do work if there are actually strokes (ie not empty) 
        if (canvasStrokes.Count > 0) 
        { 
         var width = (int)myCanvas.ActualWidth; 
         var height = (int)myCanvas.ActualHeight; 
         var device = CanvasDevice.GetSharedDevice(); 
         //Create a new renderTarget with the same width and height as myCanvas at 96dpi 
         var renderTarget = new CanvasRenderTarget(device, width, 
          height, 96); 
    
         using (var ds = renderTarget.CreateDrawingSession()) 
         { 
          //This will clear the renderTarget with a clean slate of a white background. 
          ds.Clear(Windows.UI.Colors.White); 
          //Here is where we actually take the strokes from the canvas and draw them on the render target. 
          ds.DrawInk(myCanvas.InkPresenter.StrokeContainer.GetStrokes()); 
         } 
         //Finally, this will return the render target as a byte array. 
         return renderTarget.GetPixelBytes(); 
        } 
        else 
        { 
         return null; 
        } 
    } 
    
  2. あなたが必要とするすべての作業が完了し、各画素のバイト配列である場合。ただし、イメージを生成する場合は、WriteableBitmapを使用してイメージを生成します。これを行うために呼び出すことができる同期メソッドと非同期メソッドがあります。

    private WriteableBitmap GetSignatureBitmapFull() 
    { 
        var bytes = ConvertInkCanvasToByteArray(); 
    
        if (bytes != null) 
        { 
         var width = (int)cvsSignature.ActualWidth; 
         var height = (int)cvsSignature.ActualHeight; 
    
         var bmp = new WriteableBitmap(width, height); 
         using (var stream = bmp.PixelBuffer.AsStream()) 
         { 
          stream.Write(bytes, 0, bytes.Length); 
          return bmp; 
         } 
        } 
        else 
         return null; 
    } 
    
    private async Task<WriteableBitmap> GetSignatureBitmapFullAsync() 
    { 
        var bytes = ConvertInkCanvasToByteArray(); 
    
        if (bytes != null) 
        { 
         var width = (int)cvsSignature.ActualWidth; 
         var height = (int)cvsSignature.ActualHeight; 
    
         var bmp = new WriteableBitmap(width, height); 
         using (var stream = bmp.PixelBuffer.AsStream()) 
         { 
          await stream.WriteAsync(bytes, 0, bytes.Length); 
          return bmp; 
         } 
        } 
        else 
         return null; 
    } 
    
  3. 最後に、ここで私はあなたがそれをしたい場合は、ビットマップ上の作物を行うことができるように使用しています非同期方法があります。この方法の重要な点は、この方法でピクセルバイトを配列として最初に取得する必要がないことに気づくことです。あなただけのキャンバスからストロークを取得し、それをメモリストリームこれは、Windows 10ユニバーサルにInkCanvasを使用するときに、いくつかの選択肢を提供するのに役立つ

    private async Task<WriteableBitmap> GetSignatureBitmapCropped() 
    { 
        try 
        { 
         var canvasStrokes = cvsSignature.InkPresenter.StrokeContainer.GetStrokes(); 
    
         if (canvasStrokes.Count > 0) 
         { 
          var bounds = cvsSignature.InkPresenter.StrokeContainer.BoundingRect; 
          var xOffset = (uint)Math.Round(bounds.X); 
          var yOffset = (uint)Math.Round(bounds.Y); 
          var pixelWidth = (int)Math.Round(bounds.Width); 
          var pixelHeight = (int)Math.Round(bounds.Height); 
    
          using (var memStream = new InMemoryRandomAccessStream()) 
          { 
           await cvsSignature.InkPresenter.StrokeContainer.SaveAsync(memStream); 
    
           var decoder = await BitmapDecoder.CreateAsync(memStream); 
    
           var transform = new BitmapTransform(); 
           var newBounds = new BitmapBounds(); 
           newBounds.X = 0; 
           newBounds.Y = 0; 
           newBounds.Width = (uint)pixelWidth; 
           newBounds.Height = (uint)pixelHeight; 
           transform.Bounds = newBounds; 
    
           var pdp = await decoder.GetPixelDataAsync(
            BitmapPixelFormat.Bgra8, 
            BitmapAlphaMode.Straight, 
            transform, 
            ExifOrientationMode.IgnoreExifOrientation, 
            ColorManagementMode.DoNotColorManage); 
    
           var pixels = pdp.DetachPixelData(); 
    
           var cropBmp = new WriteableBitmap(pixelWidth, pixelHeight); 
    
           using (var stream = cropBmp.PixelBuffer.AsStream()) 
           { 
            await stream.WriteAsync(pixels, 0, pixels.Length); 
           } 
           return cropBmp; 
          } 
         } 
         else 
         { 
          return null; 
         } 
        } 
        catch (Exception ex) 
        { 
         return null; 
        } 
    } 
    

希望に直接保存されます。

0

私の唯一の選択肢は、GIFとしてファイルに署名を保存することです。

GIFだけではありません。 official sampleGIFと表示されますが、InkStokesコレクションはJPGPNGに保存することもできます。コードのように、次のとおりです。

var savePicker = new Windows.Storage.Pickers.FileSavePicker(); 
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary; 
savePicker.FileTypeChoices.Add("Gif,JPG,PNG", new System.Collections.Generic.List<string> { ".jpg" ,".gif",".png"}); 
Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync(); 

しかし、このタイプのアプローチと私は見ての通り

をWindows.Storage.Streams.IOutputStreamするSystem.IO.MemoryStreamから変換することはできません例外を取得System.IO.MemoryStreamからWindows.Storage.Streams.IOutputStreamに直接変換することはできません。保存したばかりの画像ファイルをImageSourceとして読み込む必要があります。 base64を取得する方法を知っていたら、イメージまたはバイト配列のいずれかを取得します。だから私たちが必要とするのは、イメージファイルからバイト配列またはイメージを取得することだけです。

using (IRandomAccessStream streamforread = await file.OpenAsync(FileAccessMode.Read) 
{ 
    var bitmap = new BitmapImage(); 
    bitmap.SetSource(streamforread); 
} 

if (inkCanvas.InkPresenter.StrokeContainer.GetStrokes().Count > 0) 
{ 
    var savePicker = new Windows.Storage.Pickers.FileSavePicker(); 
    savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary; 
    savePicker.FileTypeChoices.Add("Gif,JPG,PNG", new System.Collections.Generic.List<string> { ".jpg", ".gif", ".png" }); 
    Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync(); 
    if (null != file) 
    { 
     using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite)) 
     { 
      await inkCanvas.InkPresenter.StrokeContainer.SaveAsync(stream); 
     } 
     using (IRandomAccessStream streamforread = await file.OpenAsync(FileAccessMode.Read)) 
     { 
      WriteableBitmap inkimagesource = new WriteableBitmap(50, 50); 
      inkimagesource.SetSource(streamforread); 
      byte[] imageBuffer = inkimagesource.PixelBuffer.ToArray(); 
      MemoryStream ms = new MemoryStream(imageBuffer); 
     } 
    } 
} 

を次のように

だけで次のようにコードを読んで、ファイルを変更する必要がイメージソースとしてファイルを読むバイト配列としてイメージファイルと、メモリストリームを読みます

私はそのリストを繰り返して、バイト配列を作ることができると思いますか?どうすればいい?これは効率的ではないようですね?

現在、APIはInkStrokeのコレクションをバイト配列として直接ビルドすることはできません。 SaveAsync()メソッドはすでにInkStrokeコレクションをストリームに保存するのに役立ちます。上記のコードを使用してストリームを使用できます。

+0

詳細な例をありがとうございます。私はこれをさらに調べます。しかし、コメントとして、私はファイルに保存してからファイルから読み込んで、やりたいことをする必要があるという事実を頭に入れてはいけません。これは、最初にファイルに保存する必要がないアプリケーションでは不慣れな、貧弱でコストのかかる方法です。私は、InkCanvasクラスがメモリに直接保存する機能を除外していることに驚いています。 –

関連する問題