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)

  1. MainPage.xaml文件主要代码
  2. ------------------------------------------------------------------------------------------------------------------
  3. <!--注册PointerReleased 事件用于捕获屏幕的单击操作,并在时间处理程序中生成图片-->
  4. <Grid x:Name="root" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
  5. PointerReleased="Grid_PointerReleased">
  6. <Grid.RowDefinitions>
  7. <RowDefinition Height="Auto"/>
  8. <RowDefinition Height="*"/>
  9. </Grid.RowDefinitions>
  10. <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,35,0,28">
  11. <TextBlock Text="我的应用程序" FontSize="20" />
  12. <TextBlock Text="点击截屏" FontSize="60" />
  13. </StackPanel>
  14. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" >
  15. <!--该图片控件用于展示截图图片效果-->
  16. <Image x:Name="img" />
  17. </Grid>
  18. </Grid>
  1. MainPage.xaml.cs文件主要代码
  2. ------------------------------------------------------------------------------------------------------------------
  3. // 指针释放的事件处理程序
  4. private async void Grid_PointerReleased(object sender, PointerRoutedEventArgs e)
  5. {
  6. // 创建一个RenderTargetBitmap对象,对界面中的Grid控件root生成图片
  7. RenderTargetBitmap bitmap = new RenderTargetBitmap();
  8. await bitmap.RenderAsync(root);
  9. // 把图片展现出来
  10. img.Source = bitmap;
  11. }

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表示像素数据的水平分辨率(以每英寸点数为单位);dpiY表示像素数据的垂直分辨率(以每英寸点数为单位);pixels表示像素数据。此方法是同步的,因为直到调用 FlushAsync、GoToNextFrameAsync 或 GoToNextFrameAsync(IIterable(IKeyValuePair)) 才会提交数据。此方法将所有像素数据视为sRGB 颜色空间中的像素数据。

下面给出保存截图文件的示例:先使用RenderTargetBitmap类生成程序界面的截图,然后再将截图的二进制数据生成图片文件存储到程序存储中。     代码清单7-10保存截图文件(源代码:第7章\Examples_7_10)

  1. MainPage.xaml文件主要代码
  2. ------------------------------------------------------------------------------------------------------------------
  3. <Grid x:Name="root" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  4. ……省略若干代码
  5. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  6. <StackPanel>
  7. <Button x:Name="bt_save" Content="存储生成的图片" Click="bt_save_Click"></Button>
  8. <Button x:Name="bt_show" Content="展示存储的图片" Click="bt_show_Click"></Button>
  9. <ScrollViewer BorderBrush="Red" BorderThickness="2" Height="350">
  10. <Image x:Name="img" />
  11. </ScrollViewer>
  12. </StackPanel>
  13. </Grid>
  14. </Grid>
  1. MainPage.xaml.cs文件主要代码
  2. ------------------------------------------------------------------------------------------------------------------
  3. // 按钮事件生成图片并保存到程序的存储里面
  4. private async void bt_save_Click(object sender, RoutedEventArgs e)
  5. {
  6. // 生成RenderTargetBitmap对象
  7. RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
  8. await renderTargetBitmap.RenderAsync(root);
  9. // 获取图像的二进制数据
  10. var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
  11. // 创建程序文件存储
  12. IStorageFolder applicationFolder = ApplicationData.Current.LocalFolder;
  13. IStorageFile saveFile = await applicationFolder.CreateFileAsync("snapshot.png", CreationCollisionOption.OpenIfExists);
  14. // 把图片的二进制数据写入文件存储
  15. using (var fileStream = await saveFile.OpenAsync(FileAccessMode.ReadWrite))
  16. {
  17. var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, fileStream);
  18. encoder.SetPixelData(
  19. BitmapPixelFormat.Bgra8,
  20. BitmapAlphaMode.Ignore,
  21. (uint)renderTargetBitmap.PixelWidth,
  22. (uint)renderTargetBitmap.PixelHeight,
  23. DisplayInformation.GetForCurrentView().LogicalDpi,
  24. DisplayInformation.GetForCurrentView().LogicalDpi,
  25. pixelBuffer.ToArray());
  26. await encoder.FlushAsync();
  27. }
  28. }
  29. // 展示程序存储图片的按钮事件
  30. private void bt_show_Click(object sender, RoutedEventArgs e)
  31. {
  32. // “ms-appdata:///local”表示是程序存储的根目录
  33. BitmapImage bitmapImage = new BitmapImage(new Uri("ms-appdata:///local/snapshot.png", UriKind.Absolute));
  34. img.Source = bitmapImage;
  35. }

7.2.3 使用RenderTargetBitmap类生成图片的更多相关文章

  1. 【WP8.1开发】RenderTargetBitmap类的特殊用途

    相信,耍过WPF的人都知道RenderTargetBitmap这个玩意儿,这家伙比较有意思,它可以将用户界面上呈现的东西写入到内存的位图对象,从而开发者可以在应用程序中使用它,或者将其保存为图像文件. ...

  2. [深入浅出WP8.1(Runtime)]生成图片和存储生成的图片文件

    7.2.3 使用RenderTargetBitmap类生成图片 RenderTargetBitmap类可以将可视化对象转换为位图,也就是说它可以将任意的UIElement以位图的形式呈现.那么我们在实 ...

  3. 《深入浅出Windows 10通用应用开发》

        <深入浅出Windows 10通用应用开发>采用Windows 10的SDK进行重新改版,整合了<深入浅出Windows Phone 8.1应用开发>和<深入解析 ...

  4. 《深入浅出Windows Phone 8.1 应用开发》基于Runtime框架全新升级版

    <深入浅出Windows Phone 8.1 应用开发>使用WP8.1 Runtime框架最新的API重写了上一本<深入浅出Windows Phone 8应用开发>大部分的的内 ...

  5. JAVA生成图片缩略图、JAVA截取图片局部内容

    package com.ares.image.test; import java.awt.Color; import java.awt.Graphics; import java.awt.Image; ...

  6. PHP编写的图片验证码类文件分享方法

    适用于自定义的验证码类! <?php/* * To change this license header, choose License Headers in Project Propertie ...

  7. WPF图形图像相关类

    BitmapMetadata类: 继承自抽象类ImageMetadata,包含图像的原数据信息,如相机型号.图像修改程序名称.拍照日期.拍照地点等.ImageSoure类包含ImageMetadata ...

  8. Java类的继承与多态特性-入门笔记

    相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...

  9. 导出程序界面(UI)到图片

    无意间看到这个需求,查阅了相关文章,有两篇不错的博客给出了解决方案,地址如下: 1.在WPF程序中将控件所呈现的内容保存成图像 2.随心所欲导出你的 UI 界面到 PDF 文件 主要使用的接口: Si ...

随机推荐

  1. python——初识django的template

    这周听了老师讲关于django的框架问题,第一次比较透彻的了解了mtv框架.也是第一次接触模板的概念,研究了一下,现在就记录下来好嘞... 首先要介绍一点关于django的模板:我们为什么要使用模板呢 ...

  2. Balanced Binary Tree [LeetCode]

    Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary ...

  3. WordPress网站搭建

    . 1.进入 var/www/html中放入里的文件 2.. 安装http php php-sql [root@jw38 yum.repos.d]# systemctl restart httpd.s ...

  4. YY前端课程3

    1. 常用的字符实体(html实体):空格=      <=<       >=>       版权符号=© 2. ID就像身份证号一样,是唯一的,html页面的ID不能重复: ...

  5. 转载C#下RSA算法的实现(适用于支付宝和易宝支付)

    RSA算法代码: using System; using System.Collections.Generic; using System.Text; using System.IO; using S ...

  6. 2016年2月16日开始,每天一篇,记录学习心得,【基本技能篇】>>开篇《如何阅读一本书——心得》

    如何阅读一本书——心得 ——2016年2月12日 要达到阅读的所有目的,就必须在阅读不同书籍的时候,运用适当的不同速度.读的太快或太慢,都一无所获. 四个阅读层次:①基础阅读,具有基本阅读的能力,包括 ...

  7. AJAX(一、基本知识)

    AJAX:Asynchronous ([ə'sɪŋkrənəs; eɪ-])Javascript (['dʒɑ:və,skrɪpt])and XML 异步的Javascript和XMLAJAX不是新的 ...

  8. 一些css知识

    两个"::"和一个":"在css3中主要用来区分伪类和伪元素. 1.设置 placeholder属性: // firefox input::-moz-place ...

  9. python pandas根据首字母选行

    ret2.loc[ret2['INNERCODE'].map(lambda x:x[0]=='6' or x[0]=='3' or x[0]=='0' ),:]和matlab不一样的风格 - -直接用 ...

  10. 使用VC6.0创建和运行C程序的方法

    使用VC6.0可以有快捷的方式创建C程序,对于初学者,建议按照如下方式创建.先创建一个工作区,然后创建工程,最后在工程中创建源文件文件.理解工作区.工程与文件之间的关系.