2016-05-12 33 views
7

Mam InkCanvas w mojej aplikacji UWP i chciałbym wyświetlić obraz (najlepiej jako część płótna, ale poza tym nakładam go w jakiś sposób (ideą jest to, że mam można zapisać zmieniony obraz z powrotem do pliku obrazu) WPF wydaje się umożliwienie InkCanvas mieć dzieci, ale w UWP, które nie wydają się być możliwe próbowałem następujące:..Wyświetlanie obrazu tła na płótnie atramentowym UWP

 <InkCanvas x:Name="drawInkCanvas"> 
      <Image Source="{Binding DrawingImage}"/> 

     </InkCanvas> 

ale nie działa; ja również próbowałem:

 <Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"> 
      <InkCanvas x:Name="drawInkCanvas" Opacity=".5"/> 
      <Image Source="{Binding DrawingImage}" Opacity=".5"/> 

     </Canvas> 

które, aby być uczciwym, nie miałem bardzo wysoki h opes dla; tak czy inaczej, chociaż robi, rodzaj pracy, sprawia, że ​​zarówno obraz, jak i InkCanvas wyglądają źle i, oczywiście, nie pozwala mi zapisać wynikowego obrazu.

Idealnie byłoby, gdyby był obraz tła lub coś podobnego. Czy jest coś, co mogę wykorzystać, aby to osiągnąć; Podchodzę do opinii, że być może będę musiał zastąpić InkCanvas standardowym płótnem, a następnie ponownie napisać całą funkcjonalność InkCanvas!

+0

Wygląda na to, że 'InkCanvas' nie obsługuje wyświetlania obrazu. Możesz umieścić obraz pod InkCanvas takimi jak: ''. –

Odpowiedz

8

Więc masz kilka problemów:

  1. Jak narysować używając InkCanvas nad Image kontroli.
  2. Jak zapisać wyniki w pliku.

Użyję prostej aplikacji UWP w tym przykładzie, która zakłada, że ​​masz plik "sample.jpg" w folderze Zasoby, a w manifeście masz funkcję "Biblioteki obrazów".

Aby rozwiązać pierwszy problem, wystarczy umieścić zarówno InkCanvas i Image w tym samym pojemniku (jak Grid), ale należy pamiętać, że kolejność ma znaczenie:

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <Grid> 
     <Image Source="/Assets/sample.jpg"></Image> 
     <InkCanvas x:Name="ink"></InkCanvas> 
    </Grid> 
    <Button Content="Save" 
      Width="100" 
      Height="25" 
      HorizontalAlignment="Center" 
      VerticalAlignment="Center" Click="BtnSave_Click"/> 
</StackPanel> 

Jeśli umieścisz InkCanvas pierwszy (jak to zrobiłeś w przykładzie zapytania) - to nie zadziała. Jednak jeśli położysz InkCanvas na końcu - wszystko działa dobrze i możesz narysować swój obraz.

Teraz, aby rozwiązać drugi problem, musisz użyć Win2D (instaluj pakiet nuget Win2D.uwp), ponieważ standard RenderTargetBitmap nie wyrenderuje zawartości InkCanvas. Najpierw narysuj oryginalny obraz (pobierz obraz bezpośrednio z oryginalnego źródła, np. Z oryginalnego pliku), a następnie narysuj nad nim zawartość płótna. Pełny kod MainPage (jeśli dodasz xaml powyżej będziesz miał pełną roboczą próbkę):

public sealed partial class MainPage : Page { 
    public MainPage() { 
     this.InitializeComponent(); 
     // just set some properties of ink canvas, not directly relevant to your question 
     ink.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch; 
     var attr = new InkDrawingAttributes(); 
     attr.Color = Colors.Red; 
     attr.IgnorePressure = true; 
     attr.PenTip = PenTipShape.Circle; 
     attr.Size = new Size(4, 10); 
     ink.InkPresenter.UpdateDefaultDrawingAttributes(attr); 
    } 

    private async void BtnSave_Click(object sender, RoutedEventArgs e) { 
     // grab output file 
     StorageFolder storageFolder = KnownFolders.SavedPictures; 
     var file = await storageFolder.CreateFileAsync("output.jpg", CreationCollisionOption.ReplaceExisting); 

     CanvasDevice device = CanvasDevice.GetSharedDevice(); 
     CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, (int) ink.ActualWidth, (int) ink.ActualHeight, 96); 

     // grab your input file from Assets folder 
     StorageFolder appInstalledFolder = Windows.ApplicationModel.Package.Current.InstalledLocation; 
     StorageFolder assets = await appInstalledFolder.GetFolderAsync("Assets"); 
     var inputFile = await assets.GetFileAsync("sample.jpg");    
     using (var ds = renderTarget.CreateDrawingSession()) { 
      ds.Clear(Colors.White);     
      var image = await CanvasBitmap.LoadAsync(device, inputFile.Path); 
      // draw your image first 
      ds.DrawImage(image); 
      // then draw contents of your ink canvas over it 
      ds.DrawInk(ink.InkPresenter.StrokeContainer.GetStrokes()); 
     } 

     // save results 
     using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite)) { 
      await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Jpeg, 1f); 
     } 
    } 
} 
+0

To działa - wielkie dzięki. Robi jednak dziwne rzeczy z szerokością i wysokością; ale myślę, że to po prostu gra z liczbami i pozycjami. –

+0

Uwaga: zajmuje ona szerokość i wysokość od faktycznego rozmiaru płótna. Zamiast tego możesz użyć oryginalnych rozmiarów obrazu. – Evk