So you have couple of problems:
- How to draw using
InkCanvas
over Image
control.
- How to save the results into a file.
I'll use simple UWP app in this example, which assumes that you have "sample.jpg" file in your Assets folder, and you have "Pictures Library" capability in your manifest.
To solve first problem, just put both InkCanvas
and Image
into same container (like Grid
), but remember that order matters:
<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>
If you put InkCanvas
first (like you did in question example) - it won't work. However if put InkCanvas
last - all works fine and you can draw over your image.
Now to solve second problem you need to use Win2D (install nuget Win2D.uwp package), because standard RenderTargetBitmap
won't render InkCanvas
contents. First draw your original image (take image from original source directly, that is from original file for example), then draw contents of your ink canvas over it. Full code of MainPage (if you add xaml above you will have complete working sample):
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);
}
}
}
InkCanvas
does not support display an image. You can put the Image under the InkCanvas like:<ScrollViewer><Grid><Image Source="<path>"></Image><InkCanvas x:Name="MyInkCanvas"></InkCanvas></Grid></ScrollViewer>
. – Alviani