zoukankan      html  css  js  c++  java
  • 【WP8.1开发】RenderTargetBitmap类的特殊用途

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

    在Runtime API里面也有这个位图组件,可以将UI元素呈现到位图中,当然,它也不是万能的,首先,要写入到位图中的UI对象必须已经在用户界面上呈现了,也就是说,只要你能看到界面上出现的东东,它才会写入位图对象;其次,要呈现到位图中的UI元素需要位于可视化树中,我简单地总结为:只要是放在Page内并且可见的元素,都可以生成位图

    调用RenderTargetBitmap类的RenderAsync方法来将可视化对象呈现到RenderTargetBitmap中,如果只是在应用程序中显示该生成的位图,那么,直接把RenderTargetBitmap对象赋值给Image控件的Source属性即可。

    要是希望保存为图像文件,就要用到BitmapEncoder类,也就是图像编码。大家知道,在编码图像文件时,是向流中写入字节数组(byte[])作为图像的像素数据的,那么,如何提取RenderTargetBitmap位图中的像素数据呢。你会发现RenderTargetBitmap类有个GetPixelsAsync方法,对的,通过该方法就可以返回位图的像素数据,只不过其类型为IBuffer,这样大家又会疑惑了,如何变成byte[]呢?

    勿急,你只要引入System.Runtime.InteropServices.WindowsRuntime命名空间,里面就有相关类型为IBuffer定义了扩展方法——ToArray,调用它可以返回byte[]。

    之后的事情就好办了。

    理论永远是抽象的,咱们还是干点实事吧,这里我弄了个不那么美观的示例。

    示例项目中有四张图片,顺便Show一下老周的书法作品。在应用页面上,把这四张图片分别作为画刷来填充图形。XAML如下:

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Canvas x:Name="cv"> 
                <Ellipse Width="250" Height="200" Canvas.Left="50" Canvas.Top="20">
                    <Ellipse.Fill>
                        <ImageBrush ImageSource="/01.png" Stretch="UniformToFill"/>
                    </Ellipse.Fill>
                </Ellipse>
                <Rectangle Width="180" Height="250" Canvas.Top="240" Canvas.Left="10" RadiusX="12" RadiusY="20">
                    <Rectangle.Fill>
                        <ImageBrush ImageSource="/02.png" Stretch="UniformToFill"/>
                    </Rectangle.Fill>
                </Rectangle>
                <Polygon Points="50,0 100,50 50,100 0,50" Width="240" Height="240" Canvas.Left="150" Canvas.Top="230" Stretch="Uniform">
                    <Polygon.Fill>
                        <ImageBrush ImageSource="03.png" Stretch="UniformToFill"/>
                    </Polygon.Fill>
                </Polygon>
                <Ellipse Width="130" Height="130" Canvas.Left="245" Canvas.Top="80">
                    <Ellipse.Fill>
                        <ImageBrush ImageSource="/04.png" Stretch="UniformToFill"/>
                    </Ellipse.Fill>
                </Ellipse>
            </Canvas>
            
            <Button Content="保存图像文件" Grid.Row="1" Click="OnClick"/>
        </Grid>

    然后,处理Button的事件,生成图片,保存到相册中的“保存的图片”中。

            private async void OnClick(object sender, RoutedEventArgs e)
            {
                Button b = sender as Button;
                b.IsEnabled = false;
                StorageFolder savedPics = KnownFolders.SavedPictures;
                // 1、在位图中呈现UI元素
                RenderTargetBitmap rtb = new RenderTargetBitmap();
                await rtb.RenderAsync(this.cv);
                // 提取像素数据
                IBuffer buffer = await rtb.GetPixelsAsync();
    
                // 创建新文件
                StorageFile newFile = await savedPics.CreateFileAsync("test-3-7-11-5.png", CreationCollisionOption.ReplaceExisting);
                // 获取文件流
                IRandomAccessStream streamOut = await newFile.OpenAsync(FileAccessMode.ReadWrite);
                // 实例化编码器
                BitmapEncoder pngEncoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, streamOut);
                // 写入像素数据
                byte[] data = buffer.ToArray();
                pngEncoder.SetPixelData(BitmapPixelFormat.Bgra8,
                                        BitmapAlphaMode.Straight,
                                        (uint)rtb.PixelWidth,
                                        (uint)rtb.PixelHeight,
                                        96d, 96d, data);
                await pngEncoder.FlushAsync();
                streamOut.Dispose();
                b.IsEnabled = true;
            }

    运行效果如下图

    在写入像素数据时,最常用的格式是rgba8或bgra8,一般8位够用了,虽然就是R值和B值的通道顺序不同,但这两种格式所保存的图片文件效果不太一样,我觉得bgra8好一点,没有偏色。

    下面是保存后的PNG图片,左边的是用RGBA格式的,右边是用BGRA格式的,大家自行比较吧。

               

    虽然老周的书法水平不怎么样,大家将就着看吧,重点是看RenderTargetBitmap类的用法。

    示例下载:http://files.cnblogs.com/tcjiaan/RenderUiApp.zip

    好,再次感谢您收看老周吹牛节目,再见。

  • 相关阅读:
    1. Spring Cloud Greenwich SR2 概览
    Spring zuul 快速入门实践 --服务转发实现解析
    文件上传下载原理:http协议分析及实现
    Tomcat session的实现:线程安全与管理
    Dubbo(七):redis注册中心的应用
    Dubbo(六):zookeeper注册中心的应用
    Dubbo(五):集群容错的实现
    Dubbo(四):服务路由的实现
    Dubbo(三):负载均衡实现解析
    Nginx(一):启动流程解析
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/4248568.html
Copyright © 2011-2022 走看看