簡體   English   中英

將Canvas轉換為BitMapImage並裁剪為路徑

[英]Convert Canvas to BitMapImage & crop to path

我在Windows Phone 8應用程序中有一個UserControl,用戶在其中繪制該UserControl。 我想將其轉換為圖像,例如位圖。

我已經找到了“ 在Android中將畫布轉換為位圖圖像 ”的功能,但Windows Phone 8需要它。

用戶控件位於畫布中。 最佳的情況是,如果我僅將帶有信息的用戶控件轉換為圖像。 但是,如果這不能完成,那么畫布。 如果必須是Canvas,是否可以將用戶控件周圍的背景設置為不可見,因為不需要此信息。

編輯也許此鏈接可以幫助某人。 如何在不創建窗口的情況下將WPF UserControl渲染為位圖

我將在完成后發布我的解決方案,還將考慮將位圖轉換回usercontrol,如果有人對此進行了研究,請告知我。

編輯2

有沒有人使用這個庫http://writeablebitmapex.codeplex.com/應該很輕巧,可以看到有一個功能裁剪圖像。 所以也許這正是我所需要的。

編輯3因此,我一直在進行更多研究,最終找到了我想要的東西,請參閱http://www.kunal-chowdhury.com/2012/12/how-to-crop-image-based-on-形狀或-path.html

但是我似乎無法正常工作。 有人對此有想法嗎?

解決方案我使用writeablebitmap捕獲ui元素,並使用mediastream將其保存到獨立存儲中。 然后,我可以重新加載它並將圖像用作圖像源,從而將元素裁剪為所需的形狀。

這使您可以使用純WPF代碼做RendeTargetBitmapDrawingVisualVisualBrush

使用VisualBrush獲取WPF區域的System.Drawing.Bitmap

作為答案發布,因為我必須使用視覺畫筆而不是窗口來尋找解決方案。

這是重要的代碼,被人偷走了:

public BitmapSource ConvertToBitmapSource(UIElement element)
{
    var target = new RenderTargetBitmap((int)(element.RenderSize.Width), (int)(element.RenderSize.Height), 96, 96, PixelFormats.Pbgra32);
    var brush = new VisualBrush(element);

    var visual = new DrawingVisual();
    var drawingContext = visual.RenderOpen();


    drawingContext.DrawRectangle(brush, null, new Rect(new Point(0, 0),
        new Point(element.RenderSize.Width, element.RenderSize.Height)));

    drawingContext.Close();

    target.Render(visual);

    return target;
}   

如果要在此處包括一些額外的蒙版,請在繪制時按下不透明蒙版。

drawingContext.PushOpacityMask(brush);

但是,您不必這樣做,因為通過XAML使用目標元素上的opacity mask屬性可以實現相同的效果。

這是我的示例XAML

<Window x:Class="UIToBitmap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Ellipse x:Name="circle" Height="100" Width="100" Fill="Blue"/>
        <Grid Background="Black">
            <Image x:Name="Image" Height="100"></Image>
        </Grid>
    </StackPanel>
</Window>

以及后面的代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace UIToBitmap
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.Loaded += MainWindow_Loaded;
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            var source = ConvertToBitmapSource(circle);
            Image.Source = source;
        }

        public BitmapSource ConvertToBitmapSource(UIElement element)
        {
            var target = new RenderTargetBitmap((int)(element.RenderSize.Width), (int)(element.RenderSize.Height), 96, 96, PixelFormats.Pbgra32);
            var brush = new VisualBrush(element);

            var visual = new DrawingVisual();
            var drawingContext = visual.RenderOpen();


            drawingContext.DrawRectangle(brush, null, new Rect(new Point(0, 0),
                new Point(element.RenderSize.Width, element.RenderSize.Height)));

            drawingContext.PushOpacityMask(brush);

            drawingContext.Close();

            target.Render(visual);

            return target;
        } 
    }
}

請注意,在黑色網格上繪制的圓保留了其不透明度-僅繪制了該圓。

根據您的需要,有一個名為WriteableBitmapEx的第三方庫,它具有將來可能需要的許多其他功能。因此,只需從NugetPackageManager安裝此庫,然后您就可以在UI上制作任何控件的writeableBitmap,然后將其轉換為任何圖像。 我有一個示例,其中我已將按鈕轉換為writeablebitmap,然后將其保存到phone.media中。(這里是簡單的代碼)但請確保已安裝WriteableBitmapEx。

這里btn是xaml中定義的按鈕。

private void btn_Click_1(object sender, RoutedEventArgs e)
    {

        BitmapImage img = new BitmapImage();

        imagebitmap = new WriteableBitmap(btn, null);

        imagebitmap.SaveToMediaLibrary("hello", false);

    }

您必須直接使用此代碼。 希望對你有幫助

public static class SBA
{       
    public static WriteableBitmap SaveAsWriteableBitmap(Canvas surface)
    {
        if (surface == null) return null;

        // Save current canvas transform
        Transform transform = surface.LayoutTransform;
        // reset current transform (in case it is scaled or rotated)
        surface.LayoutTransform = null;

        // Get the size of canvas
        Size size = new Size(surface.ActualWidth, surface.ActualHeight);
        // Measure and arrange the surface
        // VERY IMPORTANT
        surface.Measure(size);
        surface.Arrange(new Rect(size));

        // Get the size of canvas
        size = new Size(surface.ActualWidth, surface.ActualHeight);
        // Measure and arrange the surface
        // VERY IMPORTANT
        surface.Measure(size);
        surface.Arrange(new Rect(size));

        // Create a render bitmap and push the surface to it
        RenderTargetBitmap renderBitmap = new RenderTargetBitmap(
          (int)size.Width,
          (int)size.Height,
          96d,
          96d,
          PixelFormats.Pbgra32);
        renderBitmap.Render(surface);

        //Restore previously saved layout
        surface.LayoutTransform = transform;

        //create and return a new WriteableBitmap using the RenderTargetBitmap
        return new WriteableBitmap(renderBitmap);
    }

    public static BitmapImage WriteableBitmapToBitmapImage(WriteableBitmap wbm)
    {
        BitmapImage bmImage = new BitmapImage();
        using (MemoryStream stream = new MemoryStream())
        {
            PngBitmapEncoder encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(wbm));
            encoder.Save(stream);
            bmImage.BeginInit();
            bmImage.CacheOption = BitmapCacheOption.OnLoad;
            bmImage.StreamSource = stream;
            bmImage.EndInit();
            bmImage.Freeze();
        }
        return bmImage;
    }

    public static BitmapImage CanvasToBitmap(Canvas c)
    {
        return WriteableBitmapToBitmapImage(SaveAsWriteableBitmap(c));
    }

}

解決方案我使用writeablebitmap捕獲ui元素,並使用mediastream將其保存到獨立存儲中。 然后,我可以重新加載它並將圖像用作圖像源,從而將元素裁剪為所需的形狀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM