如何裁剪和保存 RenderTargetBitmap UWP

How to crop and save a RenderTargetBitmap UWP

我有一个 ItemsControl,其中包含一个 Canvas(800x800px) 和一个 Rectangles 在特定坐标处的集合。 我可以将 ItemsControl 保存为 RenderTargetBitmap 这很好,但我需要在指定的 X、Y、W、H 处裁剪它,然后保存它,我似乎无法弄清楚如何要做。

我试过使用 Canvas.Clip 剪裁 Canvas,然后保存它,但这会使我的 Rectangles 移出它们指定的坐标(CollageX、CollageY),所以Canvas 需要 为 800x800 像素。

编辑: 或者有什么方法可以 Clip a canvas 而不影响其子元素的 X 和 Y 位置?

这是我当前的代码。

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>

保存前不要剪辑:保存时剪辑。

BitmapEncoder 有一个 BitmapTransform 属性,您可以使用它来控制它的编码方式,包括缩放、翻转、旋转和 裁剪

好的,所以我不确定这是否有帮助,但是查找如何裁剪图像的人肯定会喜欢这个答案,因为它非常干净和快速。

private async void GetCanvasBitmapRegion(Rect RegionToCopy)
        {
            try
            {
                CanvasDevice Cdevice = CanvasDevice.GetSharedDevice();



                var croppedwidth = (int)RegionToCopy.Width;
                var croppedheight = (int)RegionToCopy.Height;

                //create a new empty image that has the same size as the desired crop region
                var softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, croppedwidth, croppedheight,
                    BitmapAlphaMode.Premultiplied);

                //based on this empty software bitmap we create a new CanvasBitmap
                var croppedimage = CanvasBitmap.CreateFromSoftwareBitmap(Cdevice, softwareBitmap);

                // this is the image we want to crop from, CanvasBitmap has lots of static initializers that like CanvasBitmap.LoadAsync 
                //or CanvasBitmap.CreateFromBytes
                CanvasBitmap initialimage = _image;

                if (initialimage != null)
                {

                    //this function does the cropped region copy.
                    croppedimage.CopyPixelsFromBitmap(_image, 0, 0, (int)RegionToCopy.Left, (int)RegionToCopy.Top, (int)RegionToCopy.Width, (int)RegionToCopy.Height);


                   //you can now do whatever you like with croppedimage, including using its .SaveAsync or replace the old one with it.
                }

            }
            catch (Exception Ex)
            {

            }
        }