I have an ItemsControl
which contains a Canvas
(800x800px) and a collection of Rectangles
at certain coordinates.
I can save the ItemsControl
as a RenderTargetBitmap
which is fine, but I need to crop it at a specified X,Y,W,H and then save it which I can't seem to figure out how to do.
I've tried clipping the Canvas
using Canvas.Clip
and then saving it afterwards but that makes my Rectangles
move out of their specified coordinates (CollageX, CollageY), so the Canvas needs to be 800x800px.
EDIT: Or is there some way to Clip
a canvas without it affecting the X and Y positions of its child elements?
Here's what my current code looks like.
C#
private async void SaveDesignBtn_Tapped(object sender, TappedRoutedEventArgs e)
{
//Images
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(MaskArea, (int)PrintW, (int)PrintH);
var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
var pixels = pixelBuffer.ToArray();
var displayInformation = DisplayInformation.GetForCurrentView();
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("Canvas1" + ".png", CreationCollisionOption.ReplaceExisting);
using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, (uint)renderTargetBitmap.PixelWidth, (uint)renderTargetBitmap.PixelHeight, displayInformation.RawDpiX, displayInformation.RawDpiY, pixels);
await encoder.FlushAsync();
}
}
XAML
<ItemsControl Name="MaskArea" ItemsSource="{Binding Path=CollageGrid}" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,0,0,0" Width="800" Height="800">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="CollageArea"
Background="Transparent"
Width="800"
Height="800"
HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,0,0,0">
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="local:CollageGrid">
<Rectangle Name="MaskBounds" Width="{Binding CollageW}" Height="{Binding CollageH}" AllowDrop="True" CanDrag="True"
Drop="Mask_Drop"
DragOver="Mask_DragOver"
ManipulationMode="All" Stroke="Black" StrokeThickness="2" DragEnter="Mask_DragEnter" DragLeave="Mask_DragLeave" Tapped="Tap_Collage"
RenderTransformOrigin="0.5, 0.5"
Canvas.Left="{Binding CollageX}" Canvas.Top="{Binding CollageY}" Fill="Transparent">
<Rectangle.RenderTransform>
<TranslateTransform X="{Binding CollageX}" Y="{Binding CollageY}"/>
</Rectangle.RenderTransform>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Don't clip it before you save: clip it when you save.
The BitmapEncoder has a BitmapTransform property which you can use to control how it is encoded, including scaling, flipping, rotating, and clipping.