[英]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代碼做RendeTargetBitmap
, DrawingVisual
和VisualBrush
。
使用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.