標籤:style blog http color io 使用 ar strong for
7.2.3 使用RenderTargetBitmap類產生圖片
RenderTargetBitmap類可以將可視化對象轉換為位元影像,也就是說它可以將任意的UIElement以位元影像的形式呈現。那麼我們在實際的編程中通常會利用RenderTargetBitmap類來對UI介面進行操作,比如把程式的介面或者某個控制項的外觀產生一張圖片。
使用RenderTargetBitmap類產生圖片一般有兩種用途,一種是直接把產生的圖片在當前的頁面上進行展示,還有一種用途是把產生的圖片當作檔案儲存體起來,或者通過某種分享方式把圖片檔案分享出去。那麼第二種用途的編程實現肯定是在第一種的編程實現的基礎上來實現的,所以我們首先看一下第一種情況的實現,如何把在當前的介面上展示。
使用RenderTargetBitmap類產生圖片的操作主要是依賴於RenderTargetBitmap類的RenderAsync方法。RenderAsync方法有兩個重載:RenderAsync(UIElement) 和 RenderAsync(UIElement, Int32, Int32),可在後者處指定要與源視覺化樹狀結構的自然大小不同的所需映像源尺寸,沒有設定則是按照元素的原始大小產生圖片。RenderAsync方法被設計為非同步方法呼叫,因此無法保證與UI源進行精確的架構同步,但大多數情況下都足夠及時。由於 RenderTargetBitmap是ImageSource的子類,因此,可以將其用作Image元素或 ImageBrush畫筆的映像源。
下面給出產生程式的樣本:通過點擊螢幕來產生當前程式介面的,並把用Image控制項展示出來,每次的點擊都產生一個最新的並進行展示。
代碼清單7-9:產生程式(原始碼:第7章\Examples_7_9)
MainPage.xaml檔案主要代碼------------------------------------------------------------------------------------------------------------------ <!--註冊PointerReleased 事件用於捕獲螢幕的單擊操作,並在時間處理常式中產生圖片--> <Grid x:Name="root" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" PointerReleased="Grid_PointerReleased"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,35,0,28"> <TextBlock Text="我的應用程式" FontSize="20" /> <TextBlock Text="點擊截屏" FontSize="60" /> </StackPanel> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" > <!--該圖片控制項用於展示圖片效果--> <Image x:Name="img" /> </Grid> </Grid>
MainPage.xaml.cs檔案主要代碼------------------------------------------------------------------------------------------------------------------ // 指標釋放的事件處理常式 private async void Grid_PointerReleased(object sender, PointerRoutedEventArgs e) { // 建立一個RenderTargetBitmap對象,對介面中的Grid控制項root產生圖片 RenderTargetBitmap bitmap = new RenderTargetBitmap(); await bitmap.RenderAsync(root); // 把圖片展現出來 img.Source = bitmap; }
7.2.4 儲存產生的圖片檔案
在上文我們講解了如何把程式介面出來放到Image控制項上展示,那麼我們接下來將繼續介紹如何把出來的圖片儲存到程式儲存裡面。在我們調用RenderAsync方法的時候會初始化RenderTargetBitmap類的對象,但是RenderTargetBitmap類的對象本身並不能作為圖片來進行儲存,要產生圖片檔案需要擷取到圖片的位元據。如果你想要擷取 DataTransferManager 操作(例如共用協定交換)的映像,或想要使用 Windows.Graphics.Imaging API 將效果應用到映像上或對映像進行轉碼,那麼就需要用到像素資料。如果你想訪問RenderTargetBitmap的Pixels資料,你需要在用RenderAsync這個方法將UIElement定義為 RenderTargetBitmap後,再調用RenderTargetBitmap的GetPixelsAsync方法來獲得其Pixels資料。該方法返回的是一個IBuffer類型,裡面儲存的是二進位的位元影像數。這個IBuffer可以轉換為一個Byte數組,數組裡面的資料是以BGRA8格式儲存的。
以下程式碼範例如何從一個RenderTargetBitmap對象中獲得以byte數群組類型儲存的像素數。需要特別注意的是IBuffer執行個體調用的ToArray方法是一個擴充方法,你需要在你的項目中加入System.Runtime.InteropServices.WindowsRuntime這個命名空間。
var bitmap = new RenderTargetBitmap();
await bitmap.RenderAsync(elementToRender);
IBuffer pixelBuffer = await bitmap.GetPixelsAsync();
byte[] pixels = pixelBuffer.ToArray();
那麼在擷取到了映像的位元據之後,如果要把二進位的資料產生圖片檔案,需要使用到BitmapEncoder類。BitmapEncoder類包含建立、編輯和儲存映像的各種方法。建立圖片檔案首先需要調用BitmapEncoder類CreateAsync方法,來使用檔案的流來建立一個BitmapEncoder對象,然後再使用BitmapEncoder類的SetPixelData設定映像有關幀的像素資料。SetPixelData的方法參數如下:
SetPixelData(BitmapPixelFormat pixelFormat, BitmapAlphaMode alphaMode, uint width, uint height, double dpiX, double dpiY, byte[] pixels)
其中,pixelFormat表示像素資料的像素格式;alphaMode表示像素資料的alpha模式;width表示像素資料的寬度(以像素為單位);height表示像素資料的高度(以像素為單位);dpiX表示像素資料的水平解析度(以DPI為單位);dpiY表示像素資料的垂直解析度(以DPI為單位);pixels表示像素資料。此方法是同步的,因為直到調用 FlushAsync、GoToNextFrameAsync 或 GoToNextFrameAsync(IIterable(IKeyValuePair)) 才會提交資料。此方法將所有像素資料視為sRGB 色彩空間中的像素資料。
下面給出儲存檔案的樣本:先使用RenderTargetBitmap類產生程式介面的,然後再將的位元據產生圖片檔案儲存體到程式儲存中。
代碼清單7-10:儲存檔案(原始碼:第7章\Examples_7_10)
MainPage.xaml檔案主要代碼------------------------------------------------------------------------------------------------------------------ <Grid x:Name="root" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> ……省略若干代碼 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel> <Button x:Name="bt_save" Content="儲存產生的圖片" Click="bt_save_Click"></Button> <Button x:Name="bt_show" Content="展示儲存的圖片" Click="bt_show_Click"></Button> <ScrollViewer BorderBrush="Red" BorderThickness="2" Height="350"> <Image x:Name="img" /> </ScrollViewer> </StackPanel> </Grid> </Grid>
MainPage.xaml.cs檔案主要代碼------------------------------------------------------------------------------------------------------------------ // 按鈕事件產生圖片並儲存到程式的儲存裡面 private async void bt_save_Click(object sender, RoutedEventArgs e) { // 產生RenderTargetBitmap對象 RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(); await renderTargetBitmap.RenderAsync(root); // 擷取映像的位元據 var pixelBuffer = await renderTargetBitmap.GetPixelsAsync(); // 建立程式檔案儲存體 IStorageFolder applicationFolder = ApplicationData.Current.LocalFolder; IStorageFile saveFile = await applicationFolder.CreateFileAsync("snapshot.png", CreationCollisionOption.OpenIfExists); // 把圖片的位元據寫入檔案儲存體 using (var fileStream = await saveFile.OpenAsync(FileAccessMode.ReadWrite)) { var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, fileStream); encoder.SetPixelData( BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)renderTargetBitmap.PixelWidth, (uint)renderTargetBitmap.PixelHeight, DisplayInformation.GetForCurrentView().LogicalDpi, DisplayInformation.GetForCurrentView().LogicalDpi, pixelBuffer.ToArray()); await encoder.FlushAsync(); } } // 展示程式儲存圖片的按鈕事件 private void bt_show_Click(object sender, RoutedEventArgs e) { // “ms-appdata:///local”表示是程式儲存的根目錄 BitmapImage bitmapImage = new BitmapImage(new Uri("ms-appdata:///local/snapshot.png", UriKind.Absolute)); img.Source = bitmapImage; }
本文來源於《深入淺出Windows Phone 8.1 應用開發》
原始碼下載:http://vdisk.weibo.com/s/zt_pyrfNHb99O
歡迎關注我的微博@WP林政 公眾號:wp開發(號:wpkaifa)
WP8.1技術交流群:372552293
[深入淺出WP8.1(Runtime)]產生圖片和儲存產生的圖片檔案