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

原文: 重新想象 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
[源码下载]

你可能感兴趣的:(windows)