重新想象 Windows 8 Store Apps (29) - 图片处理

简介: 原文:重新想象 Windows 8 Store Apps (29) - 图片处理[源码下载] 重新想象 Windows 8 Store Apps (29) - 图片处理 作者:webabcd介绍重新想象 Windows 8 Store Apps 之 图片处理 显示图片 图片的 9 切片 ...
原文: 重新想象 Windows 8 Store Apps (29) - 图片处理

[源码下载]


重新想象 Windows 8 Store Apps (29) - 图片处理



作者:webabcd


介绍
重新想象 Windows 8 Store Apps 之 图片处理

  • 显示图片
  • 图片的 9 切片
  • WriteableBitmap
  • 获取和修改图片属性
  • 对图片文件做“缩放/旋转/编码”操作,并保存操作后的结果



示例
1、演示最基础的图片显示
Image/Display.xaml

<Page
    x:Class="XamlDemo.Image.Display"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlDemo.Image"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0" Orientation="Horizontal" VerticalAlignment="Top">

            <Border BorderBrush="Red" BorderThickness="1" Width="200" Height="100" Margin="20 0 0 0">
                <Image Source="/Assets/Logo.png" Stretch="Uniform" Width="200" Height="100" />
            </Border>

            <Border BorderBrush="Red" BorderThickness="1" Width="200" Height="100" Margin="20 0 0 0">
                <Image Source="ms-appx:///Assets/Logo.png" Stretch="Uniform" Width="200" Height="100" />
            </Border>

            <Border BorderBrush="Red" BorderThickness="1" Width="200" Height="100" Margin="20 0 0 0">
                <Image x:Name="img" Stretch="Uniform" Width="200" Height="100" />
            </Border>

            <Border BorderBrush="Red" BorderThickness="1" Width="200" Height="100" Margin="20 0 0 0">
                <Image x:Name="img2" Stretch="Uniform" Width="200" Height="100" />
            </Border>

        </StackPanel>
    </Grid>
</Page>

Image/Display.xaml.cs

/*
 * 演示最基础的图片显示
 * 
 * 注:
 * 1、引用 package 中的图片用:ms-appx:///
 * 2、引用 ApplicationData 中的图片:
 *    a) LocalFolder 对应 ms-appdata:///local/
 *    b) RoamingFolder 对应 ms-appdata:///roaming/
 *    c) TemporaryFolder 对应 ms-appdata:///temp/
 */

using System;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;

namespace XamlDemo.Image
{
    public sealed partial class Display : Page
    {
        public Display()
        {
            this.InitializeComponent();
        }

        protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            // code-behind 指定图片源
            img.Source = new BitmapImage(new Uri("ms-appx:///Assets/Logo.png", UriKind.Absolute));


            // code-behind 指定图片源
            RandomAccessStreamReference imageStreamRef = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/Logo.png", UriKind.Absolute));
            IRandomAccessStream imageStream = await imageStreamRef.OpenReadAsync();
            BitmapImage bitmapImage = new BitmapImage();
            bitmapImage.SetSource(imageStream);
            img2.Source = bitmapImage;
        }
    }
}


2、演示图片的 NineGrid
Image/NineGrid.xaml

<Page
    x:Class="XamlDemo.Image.NineGrid"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlDemo.Image"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0" Orientation="Horizontal" VerticalAlignment="Top">

            <!--
                Image - 图片控件
                    NineGrid - 指定9网格(相当于flash中的9切片)中的4条线,Thickness 类型
                        Left - 左边的线相对于图片最左端的距离
                        Top - 上边的线相对于图片最顶端的距离
                        Right - 右边的线相对于图片最右端的距离
                        Bottom - 下边的线相对于图片最底端的距离
            
                以下示例图片的原始大小为 16 * 16
            -->

            <Image Source="/Assets/NineGrid/Demo.png" Width="200" Height="200" />

            <!--通过指定9切片,防止边框被放大或缩小-->
            <Image Source="/Assets/NineGrid/Demo.png" Width="200" Height="200" NineGrid="1 1 1 1" Margin="20 0 0 0" />

        </StackPanel>
    </Grid>
</Page>


3、演示 WriteableBitmap 的应用
Image/WriteableBitmapDemo.xaml

<Page
    x:Class="XamlDemo.Image.WriteableBitmapDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlDemo.Image"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">
            
            <Image x:Name="img" Width="300" Height="300" HorizontalAlignment="Left" />

            <Button x:Name="btnLoadImage" Content="load image" Margin="0 10 0 0" Click="btnLoadImage_Click_1" />

            <Button x:Name="btnChangePixel" Content="加载一个图片并修改其中的像素的颜色值" Margin="0 10 0 0" Click="btnChangePixel_Click_1" />

            <Button x:Name="btnCreatePixel" Content="创建一个图片,设置其每个像素的颜色值" Margin="0 10 0 0" Click="btnCreatePixel_Click_1" />

        </StackPanel>
    </Grid>
</Page>

Image/WriteableBitmapDemo.xaml.cs

/*
 * 演示 WriteableBitmap 的应用
 * 
 * 注:WriteableBitmap 使用的是 BGRA 格式
 */

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
using System;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;

namespace XamlDemo.Image
{
    public sealed partial class WriteableBitmapDemo : Page
    {
        public WriteableBitmapDemo()
        {
            this.InitializeComponent();
        }


        // 加载一个图片
        private async void btnLoadImage_Click_1(object sender, RoutedEventArgs e)
        {
            // 实例化一个 300*300 的 WriteableBitmap,并将其作为 Image 控件的图片源
            WriteableBitmap writeableBitmap = new WriteableBitmap(300, 300);
            img.Source = writeableBitmap;

            StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Logo.png"));
            using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read))
            {
                // 设置 WriteableBitmap 对象的图片流
                await writeableBitmap.SetSourceAsync(fileStream);
            }
        }


        // 加载一个图片并修改其中的像素的颜色值
        private async void btnChangePixel_Click_1(object sender, RoutedEventArgs e)
        {
            // 实例化一个 300*300 的 WriteableBitmap,并将其作为 Image 控件的图片源
            WriteableBitmap writeableBitmap = new WriteableBitmap(300, 300);
            img.Source = writeableBitmap;

            StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Logo.png"));
            using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read))
            {
                // 将指定的图片转换成 BitmapDecoder 对象
                BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);

                // 通过 BitmapTransform 缩放图片的尺寸
                BitmapTransform transform = new BitmapTransform()
                {
                    ScaledWidth = Convert.ToUInt32(writeableBitmap.PixelWidth),
                    ScaledHeight = Convert.ToUInt32(writeableBitmap.PixelHeight)
                };

                // 获取图片的 PixelDataProvider 对象
                PixelDataProvider pixelData = await decoder.GetPixelDataAsync(
                    BitmapPixelFormat.Bgra8,
                    BitmapAlphaMode.Straight,
                    transform,
                    ExifOrientationMode.IgnoreExifOrientation, 
                    ColorManagementMode.DoNotColorManage);

                // 获取图片的像素数据,由于之前指定的格式是 BitmapPixelFormat.Bgra8,所以每一个像素由 4 个字节组成,分别是 bgra
                byte[] sourcePixels = pixelData.DetachPixelData();
                for (int i = 0; i < sourcePixels.Length; i++)
                {
                   sourcePixels[i] -= 10;
                }

                // 将修改后的像素数据写入 WriteableBitmap 对象的像素缓冲区(WriteableBitmap 使用的是 BGRA 格式)
                using (Stream stream = writeableBitmap.PixelBuffer.AsStream()) // IBuffer.AsStream() 为来自 System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions 中的扩展方法
                {
                    await stream.WriteAsync(sourcePixels, 0, sourcePixels.Length);
                }
            }

            // 用像素缓冲区的数据绘制图片
            writeableBitmap.Invalidate();
        }
        

        // 创建一个图片,设置其每个像素的颜色值
        private async void btnCreatePixel_Click_1(object sender, RoutedEventArgs e)
        {
            // 实例化一个 300*300 的 WriteableBitmap,并将其作为 Image 控件的图片源
            WriteableBitmap writeableBitmap = new WriteableBitmap(300, 300);
            img.Source = writeableBitmap;

            Random random = new Random();

            // 设置需要绘制的图片的像素数据(每一个像素由 4 个字节组成,分别是 bgra)
            byte[] result = new byte[300 * 300 * 4];
            for (int i = 0; i < result.Length; )
            {
                result[i++] = (byte)random.Next(0, 256); // Green
                result[i++] = (byte)random.Next(0, 256); // Blue
                result[i++] = (byte)random.Next(0, 256); // Red
                result[i++] = 255; // Alpha
            }

            // 将像素数据写入 WriteableBitmap 对象的像素缓冲区
            using (Stream stream = writeableBitmap.PixelBuffer.AsStream())
            {
                await stream.WriteAsync(result, 0, result.Length);
            }

            // 用像素缓冲区的数据绘制图片
            writeableBitmap.Invalidate();
        }
    }
}


4、演示如何获取、修改图片属性
Image/ImageProperty.xaml.cs

/*
 * 演示如何获取、修改图片属性
 */

using System;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.FileProperties;
using Windows.Storage.Pickers;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using XamlDemo.Common;

namespace XamlDemo.Image
{
    public sealed partial class ImageProperty : Page
    {
        public ImageProperty()
        {
            this.InitializeComponent();
        }

        protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (Helper.EnsureUnsnapped())
            {
                // 选择一个图片文件
                FileOpenPicker picker = new FileOpenPicker();
                picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
                picker.FileTypeFilter.Add(".jpg");
                picker.FileTypeFilter.Add(".png");

                StorageFile file = await picker.PickSingleFileAsync();

                if (file != null)
                {
                    ImageProperties imageProperties = await GetImageProperty(file);
                    UpdateImageProperty(imageProperties);
                }
            }
        }

        // 获取图片属性
        private async Task<ImageProperties> GetImageProperty(StorageFile file)
        {
            // 获取图片文件的图片属性信息
            ImageProperties imageProperties = await file.Properties.GetImagePropertiesAsync();

            // 显示图片文件的图片属性(以下试举几例,不全)
            lblMsg.Text = "title: " + imageProperties.Title;
            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "keywords: " + string.Join(",", imageProperties.Keywords);
            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "width: " + imageProperties.Width;
            lblMsg.Text += Environment.NewLine;
            lblMsg.Text += "height: " + imageProperties.Height;
            lblMsg.Text += Environment.NewLine;

            return imageProperties;
        }

        // 更新图片属性
        private async void UpdateImageProperty(ImageProperties imageProperties)
        {
            Random random = new Random();

            // 设置图片文件的图片属性(以下试举几例,不全)
            imageProperties.Title = random.Next(0, 1000).ToString();
            imageProperties.Keywords.Clear();
            imageProperties.Keywords.Add(random.Next(0, 1000).ToString());
            imageProperties.Keywords.Add(random.Next(0, 1000).ToString());

            try
            {
                // 保存图片文件的图片属性信息
                await imageProperties.SavePropertiesAsync();
                lblMsg.Text += "title 和 keywords 已被修改,重新进来可看效果";
            }
            catch (Exception ex)
            {
                lblMsg.Text = ex.ToString();
            }
        }
    }
}


5、演示如何对图片文件做“缩放/旋转/编码”操作,并保存操作后的结果
Image/ImageTransform.xaml

<Page
    x:Class="XamlDemo.Image.ImageTransform"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlDemo.Image"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">

            <Image x:Name="imgOriginal" Stretch="Uniform" Width="300" Height="200" HorizontalAlignment="Left" />

            <Image x:Name="imgTransformed" Stretch="Uniform" Width="300" Height="200" HorizontalAlignment="Left" Margin="0 10 0 0" />

        </StackPanel>
    </Grid>
</Page>

Image/ImageTransform.xaml.cs

/*
 * 演示如何对图片文件做“缩放/旋转/编码”操作,并保存操作后的结果
 */

using System;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
using XamlDemo.Common;

namespace XamlDemo.Image
{
    public sealed partial class ImageTransform : Page
    {
        public ImageTransform()
        {
            this.InitializeComponent();
        }

        protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (Helper.EnsureUnsnapped())
            {
                // 选择一个 .jpg 图片文件
                FileOpenPicker picker = new FileOpenPicker();
                picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
                picker.FileTypeFilter.Add(".jpg");

                StorageFile fileRead = await picker.PickSingleFileAsync();

                if (fileRead != null)
                {
                    // 显示用户选中的图片文件
                    BitmapImage src = new BitmapImage();
                    src.SetSource(await fileRead.OpenAsync(FileAccessMode.Read));
                    imgOriginal.Source = src;


                    // 定义一个转换后的图片文件
                    StorageFile fileWrite = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(@"webabcdTest\imageTransformDemo.png", CreationCollisionOption.ReplaceExisting);


                    using (IRandomAccessStream inputStream = await fileRead.OpenAsync(FileAccessMode.Read), outputStream = await fileWrite.OpenAsync(FileAccessMode.ReadWrite))
                    {
                        // 将用户选择的图片文件转换为一个 BitmapDecoder 对象
                        BitmapDecoder decoder = await BitmapDecoder.CreateAsync(inputStream);

                        // 通过 BitmapTransform 来配置图片的宽度、高度和顺时针旋转角度
                        BitmapTransform transform = new BitmapTransform();
                        transform.ScaledWidth = 100;
                        transform.ScaledHeight = 100;
                        transform.Rotation = BitmapRotation.Clockwise180Degrees;

                        // 获取图片的 PixelDataProvider 对象
                        PixelDataProvider pixelProvider = await decoder.GetPixelDataAsync(
                            decoder.BitmapPixelFormat,
                            decoder.BitmapAlphaMode,
                            transform,
                            ExifOrientationMode.RespectExifOrientation,
                            ColorManagementMode.ColorManageToSRgb
                        );

                        // 获取经过了 BitmapTransform 转换后的图片的像素数据
                        byte[] pixels = pixelProvider.DetachPixelData();

                        // 创建一个 BitmapEncoder 对象,可以指定图片的编码格式(PngEncoderId, JpegEncoderId, JpegXREncoderId, GifEncoderId, TiffEncoderId)
                        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, outputStream);

                        // 转码像素数据到指定的图片编码格式(本例会转吗为 png 格式),并将转码后的数据写入 stream 缓冲区
                        encoder.SetPixelData(
                            decoder.BitmapPixelFormat,
                            decoder.BitmapAlphaMode,
                            100,
                            100,
                            decoder.DpiX,
                            decoder.DpiY,
                            pixels
                        );

                        // 提交 stream 缓冲区中的所有内容
                        await encoder.FlushAsync();
                    }

                    // 显示经过“缩放/旋转/编码”操作后的图片文件
                    imgTransformed.Source = new BitmapImage(new Uri("ms-appdata:///temp/webabcdTest/imageTransformDemo.png", UriKind.Absolute));
                }
            }
        }
    }
}



OK
[源码下载]

目录
相关文章
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
138 0
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
10月前
|
C# Windows
【Azure App Service】在App Service for Windows上验证能占用的内存最大值
根据以上测验,当使用App Service内存没有达到预期的值,且应用异常日志出现OutOfMemory时,就需要检查Platform的设置是否位64bit。
160 11
|
Java 应用服务中间件 开发工具
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
133 2
|
Java 应用服务中间件 Windows
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
114 2
|
PHP Windows
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
209 1
|
PHP 开发工具 git
【Azure 应用服务】在 App Service for Windows 中自定义 PHP 版本的方法
【Azure 应用服务】在 App Service for Windows 中自定义 PHP 版本的方法
118 1
|
网络安全 API 数据安全/隐私保护
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
114 0
|
Shell PHP Windows
【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.
【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.
109 0
|
存储 Linux Windows
【应用服务 App Service】App Service For Windows 如何挂载Storage Account File Share 示例
【应用服务 App Service】App Service For Windows 如何挂载Storage Account File Share 示例
113 0
|
应用服务中间件 nginx Windows
【Azure 应用服务】在App Service for Windows中实现反向代理
【Azure 应用服务】在App Service for Windows中实现反向代理
131 0