处理图片(updated)

    高像素的图片,比如分辨率为 7712x4352 的照片,当加载到一个 bitmap 中时会占用相当大的内存。

每个像素会占用 4个字节的内存,所以当没有被压缩时,全部的图片会占用 12800万字节(约122MB)。高像素

图片的另一个问题就是渲染,因为图片不适合windows phone 8 的最大纹理尺寸为 4096x4096 像素,所以

它会被裁切。无论怎样,因为有很多方法来处理高像素图片,所以没有什么好担心的。

显示捕获的照片

     首先,把一个 Image 控件放到页面中,用来显示预览:

<!-- 取景框 -->
<phone:PhoneApplicationPage x:Class="PreviewPage" ... >
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid x:Name="ContentPanel">
            <Image x:Name="PreviewImage"/>
        </Grid>
    </Grid>
</phone:PhoneApplicationPage>  

 然后,在 C# 页面我们可以用 BitmapImage 的  intDecodePixelWidth和 int DecodePixelHeight 属性来初始化

 通过void BitmapImage.SetSource(Stream streamSource) 方法调用加载的 JPEG 的数据流 bitmap 的尺寸。

 为了知道 stream 中时一个横向的 或者 纵向的照片,你可以使用 Nokia Imaging SDK 中的ImageProviderInfo

using Nokia.Graphics.Imaging;
using System.Runtime.InteropServices.WindowsRuntime;

...

public partial class PreviewPage : PhoneApplicationPage
{
    ...

    private BitmapImage _bitmap = new BitmapImage();

    public PreviewPage()
    {
        InitializeComponent();

        PreviewImage.Source = _bitmap;

        ...
    }

    ...

    private void InitializePreview(Stream stream)
    {
        // 使用 Nokia Imaging SDK 找出 image 的 orientation 属性,
//并且相应地设置 BitmapImage 解码选项
stream.Position = 0; using (StreamImageSource source = new StreamImageSource(stream)) { ImageProviderInfo info = null; Task.Run(async () => { info = await source.GetInfoAsync(); }).Wait(); if (info.ImageSize.Width >= info.ImageSize.Height) { _bitmap.DecodePixelWidth = 1536; _bitmap.DecodePixelHeight = 0; } else { _bitmap.DecodePixelWidth = 0; _bitmap.DecodePixelHeight = 1536; } // 把 stream 设置为 bitmap 的源 stream.Position = 0; _bitmap.SetSource(stream); } } ... }


可以注意到通常你从平台 APIs 中得到的照片数据是一个 Stream,然后在 Nokia Imaging SDK 中通常采用 IBuffers.

通过下面的方法你可以进行方便的类型转换: 

using System.Runtime.InteropServices.WindowsRuntime; // MemoryStream 的扩展方法命名空间

...

public class Utilities
{
    ...

    /// <summary>
    /// 把 Stream 转换为 IBuffer 对象
/// <param name="stream">stream源</param> /// <returns>包含stream数据的IBuffer 对象</returns> /// </summary> public static IBuffer StreamToBuffer(Stream stream) { var memoryStream = stream as MemoryStream; if (memoryStream == null) { using (memoryStream = new MemoryStream()) { stream.Position = 0; stream.CopyTo(memoryStream); try { // 一些流类型不支持 stream.Flush(); } catch (Exception ex) { } return memoryStream.GetWindowsRuntimeBuffer(); } } else { return memoryStream.GetWindowsRuntimeBuffer(); } } /// <summary> /// 把 IBuffer 对象转换为 stream /// <param name="stream">buffer源</param> /// <returns>stream</returns> /// </summary> public static Stream BufferToStream(IBuffer buffer) { return buffer.AsStream(); } ... }


手动缩小图片的尺寸

实现的方式除了使用 BitmapImage 外,你也可以使用 Nokia Imaging SDK 方便的实现图片的缩小。Nokia Imaging SDK

可以让你指定比如 buffer 的最大的 size(bytes) 和 图片的最大 size(pixels) 来进行操作,并且为你提供了一个新的 data stream

从而你也可以用于其他的目的,而不仅仅把缩小的图片显示到屏幕中——比如保存和分享。

using Nokia.Graphics.Imaging;

...

public class Utilities
{
    ...

    /// <summary>
    /// 异步压缩一个 image 并且最终 JPEG 数据在字节上不会超过 maxBytes,并且在尺寸上不会超过指定的 maxSize.
    /// <param name="image">压缩的 Image</param>
    /// <param name="maxBytes">缓冲区最大字节大小</param>
    /// <param name="maxSize">压缩的最大图片的像素</param>
    /// <returns>返回压缩后的 JPEG数据缓冲区 </returns>
    /// </summary>
    private static async Task<IBuffer> ScaleAsync(IBuffer image, uint maxBytes, Size maxSize)
    {
        using (var source = new BufferImageSource(image))
        {
            var info = await source.GetInfoAsync();

            if (info.ImageSize.Width * info.ImageSize.Height > maxSize)
            {
                var resizeConfiguration = new AutoResizeConfiguration(maxBytes, maxSize,
                    new Size(0, 0), AutoResizeMode.Automatic, 0, ColorSpace.Yuv420);

                return await Nokia.Graphics.Imaging.JpegTools.AutoResizeAsync(buffer, resizeConfiguration);
            }
            else
            {
                return image;
            }
        }
    }

    ...
}  


裁切高像素图片

显示高像素图片你可以创建各种 bitmaps 对象,更小或者等于 4096x4096 像素的最大纹理尺寸。

使用 Nokia Imaging SDK 去裁切高像素原图的各个部分是很容易的。

using Nokia.Graphics.Imaging;
using Windows.Foundation;

...

public class Utilities
{
    ...

    /// <summary>
    /// 异步重构(裁切)照片,并且返回一个 JPEG data buffer
/// <param name="image">将要重构的照片</param> /// <param name="area">裁切的区域</param> /// <returns>处理后的 JPEG data buffer </returns> /// </summary> public static async Task<IBuffer> Reframe(IBuffer image, Rect area) { using (var source = new BufferImageSource(image)) using (var effect = new FilterEffect(source)) { effect.Filters = new List<IFilter>() { new ReframingFilter() { ReframingArea = area } }; using (var renderer = new JpegRenderer(effect)) { return await renderer.RenderAsync(); } } } /// <summary> /// 异步重构(裁切)照片并且把结果输出到指定的 bitmap 对象
/// <param name="image">将要重构的照片</param> /// <param name="area">重构的区域</param> /// <param name="bitmap">输出结果到 bitmap 对象</param> /// </summary> public static async Task Reframe(IBuffer image, Rect area, WriteableBitmap bitmap) { using (var source = new BufferImageSource(image)) using (var effect = new FilterEffect(source)) { effect.Filters = new List<IFilter>() { new ReframingFilter() { ReframingArea = area } }; using (var renderer = new WriteableBitmapRenderer(effect, bitmap)) { await renderer.RenderAsync(); } } } ... }

Nokia Wiki 原文链接:http://developer.nokia.com/Resources/Library/Lumia/#!imaging/working-with-high-resolution-photos/processing-photos.html

原文地址:https://www.cnblogs.com/hebeiDGL/p/3315186.html