将画布转换为BitMapImage并裁剪为路径
本文关键字:BitMapImage 裁剪 路径 转换 布转换 | 更新日期: 2023-09-27 18:33:17
我在Windows Phone 8应用程序中有一个UserControl,用户在其中绘制此Usercontrol。我想将其转换为图像,一个例子可能是位图。
我发现这是"在Android中将画布转换为位图图像",但是对于Windows Phone 8,我需要它。
用户控件位于画布中。最佳方法是如果我只将包含信息的用户控件转换为图像。但如果这不能做到,那么画布。如果它必须是画布,是否可以将用户控件周围的背景设置为不可见,因为不需要此信息。
编辑也许这个链接可以帮助某人。如何在不创建窗口的情况下将 WPF 用户控件呈现为位图
完成后,我将发布我的解决方案,我还将研究将位图转换回用户控件,如果有人对此进行了研究,请告知我。
编辑 2
有人使用过这个库吗http://writeablebitmapex.codeplex.com/应该很轻,可以看到有一个功能裁剪图像。所以也许这正是我所需要的。
编辑 3所以我一直在研究这个问题,终于找到了我想要的东西,看 http://www.kunal-chowdhury.com/2012/12/how-to-crop-image-based-on-shape-or-path.html
但我似乎无法做到这一点。有人对此有想法吗?
溶液我使用可写位图来捕获 ui 元素,并使用媒体流将其保存到隔离存储中。然后我可以重新加载它并将图像用作图像源,从而将元素裁剪为所需的形状。
允许您使用RendeTargetBitmap
、DrawingVisual
和VisualBrush
使用纯 WPF 代码来执行此操作。
使用 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 实现相同的效果。
这是我的示例 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;
}
}
}
请注意,在黑色网格上绘制的圆保持其不透明度 - 仅绘制圆。
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));
}
}
为了满足您的需要,有一个名为WriteableBitmapEx的第三方库,它具有许多其他功能,您可能需要 future.so 只需从NugetPackageManager安装此库,然后您可以在UI上制作任何控件的可写位图,然后将其转换为任何图像。 我有一个示例,其中我将按钮转换为可写位图,然后将其保存到手机中的媒体库(照片(。是简单的代码,但请确保您已安装 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);
}
您必须直接使用此代码。 希望对您有所帮助
解决方案 我使用可写位图来捕获 ui 元素,并使用媒体流将其保存到隔离存储中。然后我可以重新加载它并将图像用作图像源,从而将元素裁剪为所需的形状。