zoukankan      html  css  js  c++  java
  • MetroApp保存UIEment为图片

      写本文的起因是想截取Metro App画面作为图片来使用Win8的共享。

      话说自从大MS的客户端UI技术进入XAML时代之后,每次截屏的代码都不太一样,无论silverlight、WPF还是Windows Phone都不完全一样,搞得我头昏脑胀,每次都要搜索一下才写的出来。反观Winform许久未写,如何截屏我还记得一清二楚……真是尴尬……顺带吐槽Metro的各种奇葩Stream类,那跟.NET的Stream类互转那叫一个惨烈和别扭啊。

      花开两头,各表一枝。接下来我们进入今天的正题——如何在Metro下截屏,我再吐槽一下MS,这个截屏用的API似乎Win8.1才开放,还在用Win8的话还是撸撸睡吧……

      首先我们要用到一个奇葩类,这次真的不是WriteableBitmap了,这次的主角是叫做RenderTargetBitmap。

                var bitmap = new RenderTargetBitmap();
                await bitmap.RenderAsync(this.rootGrid);
                IBuffer buffer = await bitmap.GetPixelsAsync();
                var stream = buffer.AsStream();

      要想转换UIElement到Stream,通过以上几步就可以了,this.rootGrid是一个UIElement控件,也就是我想保存的图像。值得一提的是AsStream是一个扩展方法,记得要添加namespace System.Runtime.InteropServices.WindowsRuntime哟!

      如果是WPF应用,得到Stream之后存为图片文件是很容易的事情了,分分钟秒杀的程度,问题Metro下面还需要再折腾折腾……

      首先你需要创建一个StorageFile来存放这个图片,一个比较容易的方式是使用FileSavePicker。

                FileSavePicker savePicker = new FileSavePicker();
                savePicker.SuggestedStartLocation = PickerLocationId.Desktop;
                savePicker.FileTypeChoices.Add("Bitmap", new List<string>() { ".png" });
                savePicker.SuggestedFileName = "New Bitmap";
    
                StorageFile savedItem = await savePicker.PickSaveFileAsync();

      接下来你可能会想StorageFile也有了,Stream也有了,应该往StorageFile里写Stream就行了。

      可惜不是,直接使用FileIO.WriteBufferAsync的方法来写入图片文件是不行的。文件会无法作为图片正常显示。

      我们需要使用BitmapEncoder来写入Stream,而WinRT下的这个BitmapEncoder,又需要WinRT的IRandomAccessStream才能使用。

                    Guid encoderId = BitmapEncoder.PngEncoderId;
                    IRandomAccessStream fileStream = await savedItem.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
                    BitmapEncoder encoder = await BitmapEncoder.CreateAsync(encoderId, fileStream);
                    byte[] pixels = new byte[pixelStream.Length];
                    pixelStream.Read(pixels, 0, pixels.Length);
    
                    //pixal format shouldconvert to rgba8
                    for (int i = 0; i < pixels.Length; i += 4)
                    {
                        byte temp = pixels[i];
                        pixels[i] = pixels[i + 2];
                        pixels[i + 2] = temp;
                    }
    
                    encoder.SetPixelData(
                     BitmapPixelFormat.Rgba8,
                     BitmapAlphaMode.Straight,
                     (uint)bitmap.PixelWidth,
                     (uint)bitmap.PixelHeight,
                     96, // Horizontal DPI
                     96, // Vertical DPI
                     pixels);
    
                    await encoder.FlushAsync();

      本篇我们简单讨论了如何在MetroApp下截屏保存图片,下篇会根据本篇的成果来讨论一下Win8.1如何共享截屏的图片。同时会简单的提到.NET的Stream和WinRT的Stream的转换。

    代码下载

    本篇的参考资料:

    Windows 8.1 Apps with XAML and C# Unleashed

      这本书是Google搜索出了某个章节正好提到了RenderTargetBitmap,这会貌似又打不开了,感谢方校长八辈祖宗!这书出中文版了可以买一本!

    Win8 Metro(C#) 数字图像处理--图像打开,保存 

      图片文件BitmapEncoder是学习自这位仁兄的文章!

    韦恩卑鄙

      该参考资料明确指出了直接FileIO.WriteBufferAsync写入是不行的。

  • 相关阅读:
    SQL Server 2005 数据定义语言触发器(Data Definition Language Triggers)[翻译]
    sqlserver 存储过程例子
    微软CEO鲍尔默:科技产业终将成为经济救世主
    poj:2689用筛选法选素数求区间[L,U]的所有素数
    ZOJ Problem Set 1002 Fire Net
    去除多余括号
    模板元编程:求N的阶乘
    算法导论10.2习题
    奇数阶魔方算法
    TSQL 编程常用例子
  • 原文地址:https://www.cnblogs.com/manupstairs/p/3556642.html
Copyright © 2011-2022 走看看