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表示像素数据的水平分辨率(以每英寸点数为单位);dpiY表示像素数据的垂直分辨率(以每英寸点数为单位);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 应用开发》

WP8.1 Runtime文章列表:http://www.cnblogs.com/linzheng/p/3998037.html

源代码下载:http://vdisk.weibo.com/s/zt_pyrfNHb99O

欢迎关注我的微博@WP林政   微信公众号:wp开发(号:wpkaifa)

WP8.1技术交流群:372552293

[深入浅出WP8.1(Runtime)]生成图片和存储生成的图片文件的更多相关文章

  1. 如何在mysql中存储音乐和图片文件

    如何在mysql中存储音乐和图片文件? 果你想把二进制的数据,比如说图片文件和HTML文件,直接保存在你的MySQL数据库,那么这篇文章就是为你而写的! 我将告诉你怎样通过HTML表单来储存这些文件, ...

  2. [深入浅出WP8.1(Runtime)]Windows Phone 8.1和Silverlight 8.1的区别

    1.2.2 Windows Phone 8.1应用程序模型 Windows Phone 8.1支持多种开发语言来开发应用程序,包括C#.VB.JavaScript和C++,那么本书的代码主要是采用C# ...

  3. [深入浅出WP8.1(Runtime)]网络编程之HttpClient类

    12.2 网络编程之HttpClient类 除了可以使用HttpWebRequest类来实现HTTP网络请求之外,我们还可以使用HttpClient类来实现.对于基本的请求操作,HttpClient类 ...

  4. [深入浅出WP8.1(Runtime)]应用文件的URI方案

    6.2.4 应用文件的URI方案 在上文我们获取文件的方式都是通过应用程序的三个跟目录的文件夹对象来获取文件夹对象和文件对象,那么我们这一小节来讲解一种新的获取文件对象的方式,这种方式就是通过Uri地 ...

  5. [深入浅出WP8.1(Runtime)]文本块(TextBlock)

    4.3 文本块(TextBlock) 文本块(TextBlock)控件是用于显示少量文本的轻量控件,可以通过TextBlock呈现只读的文本,你可以把TextBlock控件理解为一种纯文本的展示控件. ...

  6. [深入浅出WP8.1(Runtime)]Socket编程之UDP协议

    13.3 Socket编程之UDP协议 UDP协议和TCP协议都是Socket编程的协议,但是与TCP协议不同,UDP协议并不提供超时重传,出错重传等功能,也就是说其是不可靠的协议.UDP适用于一次只 ...

  7. [深入浅出WP8.1(Runtime)]数据绑定的基础

    11.1 数据绑定的基础 数据绑定是一种XAML界面和后台数据通信的方式,因为界面和后台数据的通信的场景有多种,并且数据于数据之间也存在着不一样的关联关系,所以数据绑定的实现技巧和方式也是多种多样的. ...

  8. [深入浅出WP8.1(Runtime)]应用实例——移动截图

    10.2应用实例——移动截图 移动截图例子是实现一个把一张图片的某个部分截取出来的功能,并且用户可以选定截取的图片区间.那个该例子会使用ManipulationDelta事件来实现对截取区间的选择.然 ...

  9. [深入浅出WP8.1(Runtime)]Toast通知

    9.1 Toast通知 Toast通知是在屏幕最顶上弹出来的临时通知,是Windows Phone通用的弹出式短暂的通知,默认的系统消息都是采用Toast通知的形式,比如当你手机收到短信的时候,在手机 ...

随机推荐

  1. jQuery – 8.事件和事件参数

        事件 (*)JQuery中的事件绑定:$("#btn").bind("click",function(){}),每次都这么调用太麻烦,所以jQuery可 ...

  2. OCJP(1Z0-851) 模拟题分析(一)11

    Exam : 1Z0-851 Java Standard Edition 6 Programmer Certified Professional Exam 以下分析全都是我自己分析或者参考网上的,定有 ...

  3. Visual Studio 2015的Web扩展包

    过去几年,Visual Studio扩展功能生态系统得到了蓬勃发展,社区贡献出了大量优秀的扩展,其中也包括大量针对Web开发的扩展.但是很多时候,感觉寻找.安装.更新好 几个扩展,总显得比较麻烦.如果 ...

  4. shell test 數值 字符串 文件比較

    數值比較 描述 n1 –eq n2 等於 n1 –gt  n2 大於 n1 –ge n2 大於等於 n1 –lt  n2 小於 n1 –le n2 小於等於 n1 –ne n2 不等於   字符串比較 ...

  5. .NET NLog 详解(二)

    Git是个很好的源码管理系统,你可以瞬间切换为任何历史版本.为了更好的解析NLog这个组件,我们将时钟倒拨回2004年.(注意:NLog v0.9 has been released 是在2005-0 ...

  6. Win10 UI线程

    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => UpdateButtonOrientation());

  7. Sizeof运算符小结

    以下内容援引自<C Primer Plus>中文版第五版Page95 Sizeof运算符以字节为单位返回其操作数的大小.(在C中,1个字节被定义为char类型所占用空间的大小.在过去,1个 ...

  8. ssh 免密码登陆

    远程ssh登陆服务器或者其他机器时或者scp时,需要输入密码,感觉很麻烦,于是研究如何免密码登陆. step1:Client端生成公钥和密钥 执行命令 ssh-keygen 进入目录~/.ssh里面, ...

  9. 安装.net Framework 3.5 SP1非常慢的解决方案

    解决方案:1.msiexec /unregserver回车,在输入命令:msiexec /regserver msiexec /unregserver是停止installer服务,而msiexec / ...

  10. Linux之find命令用于统计信息

    1. 计算当前目录中的文件数: [root@localhost tmp]# find . -type f | wc -l 2. 查找/etc目录中最新的和最旧的文件,以文件时间排序并按年-月-日的格式 ...