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

时间: 2024-08-26 04:32:55

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

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

相信,耍过WPF的人都知道RenderTargetBitmap这个玩意儿,这家伙比较有意思,它可以将用户界面上呈现的东西写入到内存的位图对象,从而开发者可以在应用程序中使用它,或者将其保存为图像文件. 在Runtime API里面也有这个位图组件,可以将UI元素呈现到位图中,当然,它也不是万能的,首先,要写入到位图中的UI对象必须已经在用户界面上呈现了,也就是说,只要你能看到界面上出现的东东,它才会写入位图对象:其次,要呈现到位图中的UI元素需要位于可视化树中,我简单地总结为:只要是放在Page

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

7.2.3 使用RenderTargetBitmap类生成图片 RenderTargetBitmap类可以将可视化对象转换为位图,也就是说它可以将任意的UIElement以位图的形式呈现.那么我们在实际的编程中通常会利用RenderTargetBitmap类来对UI界面进行截图操作,比如把程序的界面或者某个控件的外观生成一张图片. 使用RenderTargetBitmap类生成图片一般有两种用途,一种是直接把生成的图片在当前的页面上进行展示,还有一种用途是把生成的图片当作文件存储起来,或者通过某

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

<深入浅出Windows Phone 8.1 应用开发>使用WP8.1 Runtime框架最新的API重写了上一本<深入浅出Windows Phone 8应用开发>大部分的的内容,修改了上一本众多网友读者反馈的问题. 全书实例和项目演练的源代码免费下载: http://vdisk.weibo.com/s/zt_pyrfNHb99O 试读章节会在博客园持续更新: [深入浅出WP8.1(Runtime)]Windows Phone 8.1和Silverlight 8.1的区别 [深入浅

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

适用于自定义的验证码类! <?php /* * To change this license header, choose License Headers in Project Properties.* To change this template file, choose Tools | Templates* and open the template in the editor.*/Class Image{ private $img;public $width = 85;public $h

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

package com.ares.image.test; import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Arrays; import javax.imageio.ImageIO; import o

WPF 生成文字图片小笔记: DrawingContext类

在WinForm程序中用Graphics类生成图片文字, 而WPF功能类似的类是System.Windows.Media下的DrawingContext. 虽然在WPF中可以使用Graphics类, 但这会涉及到Bitmap与BitmapSource之间的转换. 虽然不是很麻烦, 但就是很不爽. 而且Graphics是GUI的操作, 明显不适合WPF. 在System.Windows.Media命名空间下, 还有其它与System.Drawing功能相类似的类. 当然, 你在使用DrawingC

uwp开发:截取当前屏幕中需要的图像并保存至应用内存储

在uwp开发中,有时候需要获取当前屏幕中的图像信息,但是又不适合直接截图保存,因为截图会保存整个屏幕的图像,而且,还需要用户会截屏操作.总之不适合获取屏幕中需要的图像信息.注意题目中的“需要的”. 意思是什么呢?就是我们可以获取当前屏幕中任意一个UIElement中的图像.废话不多说,还是以实战场景为例,因为自己最近就遇到了这种情况. 在做<简影UWP>的“电影台词”模块的时候,显示如下: 需求是:是用户点击保存图片,将会把图片和文字一块保存下来,查看的时候,也是当前显示的这样. 首先贴上前台

随心所欲导出你的 UI 界面到 PDF 文件

使用 C1PDF 控件可以导出文件到 PDF 文件,结合 .NET 平台特性你可以在任何客户端生成自定义报表.你可以打印任何 UI 界面,例如 DataGrid 导出到 PDF. 在本篇文章中我们将阐述在 XAML 平台中打印 UI 到 PDF 文件的通用方法. 打印 UI 界面到 PDF 文件,需要首先把 UI 界面导出到图片,然后把图片添加到 PDF 文件中.面让我们来进入实战部分. 导出UI到图片 UI导出到 PDF 文件,最简单明了的方法是把 UI 界面作为图片插入到 PDF 文件中.每

【Win10】开发中的新特性及原有的变更

声明:本文内容适用于 Visual Studio 2015 RC 及 Windows 10 10069 SDK 环境下,若以后有任何变更,请以新的特性为准. 一.Password 控件的小眼睛属性的变更 在 Windows 8.1(含 Windows 8) 及 Windows Phone 8.1 Runtime 中,Password 控件的小眼睛是由 IsPasswordRevealButtonEnabled 属性定义的,但是,尽管是相同的属性名字,却有着不同的表现形式. Windows 8.1