2013-09-30 29 views
2

我在Windows Phone 8應用程序中有一個用戶控件,用戶在此用戶控件上進行繪製。我想將其轉換爲圖像,例如可以是位圖。將畫布轉換爲BitMapImage&裁剪爲路徑

我發現這個「converting a canvas into bitmap image in android」,但我需要它的Windows Phone 8

用戶控件放置在畫布。如果我僅將帶有信息的用戶控件轉換爲圖像,最佳方案就是如此。但是,如果不能完成那麼畫布。如果必須是Canvas,是否可以將用戶控件周圍的背景設置爲不可見,因爲不需要此信息。

編輯 也許這個鏈接可以幫助別人。 How to render a WPF UserControl to a bitmap without creating a window

我會後我的解決方案,當它完成,我也將考慮轉換爲位圖回用戶控件,如果有人看着這個請告訴我這件事。

EDIT 2

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

編輯3 所以我一直在尋找更多的這個,終於找到的東西,這正是我想要的,看http://www.kunal-chowdhury.com/2012/12/how-to-crop-image-based-on-shape-or-path.html

但我似乎無法得到這個工作。有沒有人有這個想法?

解決方案 我使用writeablebitmap來捕獲ui元素,並使用mediastream將其保存到isolationstorage。然後我可以重新加載它並將圖像用作圖像源,從而將元素剪裁成希望的形狀。

+0

它可能捕獲您的用戶控件的內容在一個WriteableBitmap內。從那裏,您可以直接使用內置API將其保存爲JPEG,或者使用ImageTools庫將其保存爲其他格式。 –

+0

所以我必須設置一個屬性爲usercontrol這個工作或? – JTIM

回答

1

您的需求,還有第三個叫WriteableBitmapEx有很多其他的功能,你可能需要在future.so距離安裝這個庫NugetPackageManager,然後你可以做任何控制的WriteableBitmap的黨庫在用戶界面上,然後將其轉換爲任何圖像。我有一個示例,其中我已經將一個按鈕轉換爲writeablebitmap,然後將其保存到手機中的medialibrary(照片)。其中有簡單的代碼,但請確保已安裝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); 

    } 

,你必須直接使用此代碼。希望它可以幫助你

+0

謝謝,是的,每一個幫助表示讚賞。 我會看看圖書館。但是你有沒有製作非矩形元素的經驗?如果是的話,控制不會填滿的區域會發生什麼? – JTIM

+0

JTIM我已經檢查了它與應用它在一個圓形的邊框按鈕,實際上它只轉換控制人爲的區域,如果你認爲你可以使用三角形尺寸的圖像然後它是不可能的,因爲圖像將永遠是矩形(我認爲是這樣)..所以只是探討是否它不會幫助你..如果有東西更新在這裏 – loop

+0

當然我會,我即將探索這個領域與我的應用程序的更新。因此需要一些關於最佳實踐的信息。現在我有一個地方開始。只是想知道如果你有經驗:) – JTIM

3

這允許你用純WPF代碼使用RendeTargetBitmap,DrawingVisualVisualBrush

Get System.Drawing.Bitmap of a WPF Area using VisualBrush

發佈作爲一個答案,因爲我不得不做一些狩獵使用可視化筆刷,而不是一個窗口的解決方案。

這裏是重要的代碼,可怕被盜:

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; 
     } 
    } 
} 

注意,對黑色網格繪製的圓保留其不透明度 - 只有繪製圓。

+0

Ooof。不知道這個解決方案將工作在silverlight – Gusdor

+0

我的問題是,你轉換整個空間,你有沒有調查,你不是在一個正方形感興趣,但三角形。因此,在左邊的區域你想要透明/隱形? – JTIM

+0

@JTIM問題是將UI元素(畫布)轉換爲圖像而不打開窗口。這成功了。我會編輯一些額外的內容。 – Gusdor

-1

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

1
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)); 
    } 

}