42、XAML Images

 

1、Displaying images :

    在 xaml 中引用程序包中的图片的方法 :

 <Image Source="Assets/image1.jpg" Height="200" />

 

2、Images from  a  file stream:

      本实例演示用户通过 File Picker 选择图片,并且进行编码解析。

操作截图:

原始图片:

经过解析:

页面的 XAML :

<!--高度-->
 <TextBox x:Name="Scenario2DecodePixelHeight"  Width="100" Text="100" HorizontalAlignment="Left" />

 <!--宽度-->
 <TextBox x:Name="Scenario2DecodePixelWidth"  Width="100" Text="100" HorizontalAlignment="Left" />

 <!-- 点击打开 FileOpenPicker. -->
 <Button x:Name="Scenario2Button1" Content="Select image..."  Click = “Scenario2Button1_Click”/>
 
<!--显示结果-->
<Image x:Name="Scenario2Image" Stretch="None" />


相应的 C# :

按钮的单击事件:

async void Scenario2Button1_Click(object sender, RoutedEventArgs e)
{
    int decodePixelHeight;
    int decodePixelWidth;

      if (!int.TryParse(Scenario2DecodePixelHeight.Text, out decodePixelHeight))
    {
        Scenario2DecodePixelHeight.Text = "100";
        decodePixelHeight = 100;
    }

    if (!int.TryParse(Scenario2DecodePixelWidth.Text, out decodePixelWidth))
    {
        Scenario2DecodePixelWidth.Text = "100";
        decodePixelWidth = 100;
    }

    FileOpenPicker open = new FileOpenPicker();
    open.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
    open.ViewMode = PickerViewMode.Thumbnail;

    // Filter to include a sample subset of file types
    open.FileTypeFilter.Clear();
    open.FileTypeFilter.Add(".bmp");
    open.FileTypeFilter.Add(".png");
    open.FileTypeFilter.Add(".jpeg");
    open.FileTypeFilter.Add(".jpg");


    StorageFile file = await open.PickSingleFileAsync();

    if (file != null)
    {
        using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
        {

            BitmapImage bitmapImage = new BitmapImage();

             //获取或设置要用于图像编码操作的高度。
            bitmapImage.DecodePixelHeight = decodePixelHeight;
            bitmapImage.DecodePixelWidth = decodePixelWidth;

            await bitmapImage.SetSourceAsync(fileStream);
            Scenario2Image.Source = bitmapImage;
        }
    }
}

 

3、Displaying a NineGrid image :

      下面的实例展示了怎样使用 NineGrid margins 显示一个图片。

      第一张图片是原始图片(8x7 像素)。第二张是把原图片放大到 100x200 的图片。第三张图片是放大到 100x200 并且指定

 了 3 像素的 NineGrid margins 。这些控件使用拉伸边缘和边角的行为。

 

   NineGrid  属性: 获取或设置控制图像大小调整方式的九格形式的值。

 

显示截图 :

 

相应的 xaml :

 <Image Source="Assets/NineGridSource.png"  Stretch="None" />

 <Image Source="Assets/NineGridSource.png"/>

<!--NineGrid :  获取或设置控制图像大小调整方式的九格形式的值。-->
<Image Source="Assets/NineGridSource.png" NineGrid="3,3,3,3"/>


4、Using a WriteableBitmap :

     下面的演示展示了如何直接操作  WriteableBitmap  对象的像素点。

      首先在 XAML 页面中,放置三个按钮 和 一个显示图片操作结果的容器 :

<!--异步绘制曼德尔勃特集合,并且将结果显示在下面的  WriteableBitmap 中。-->
<Button   Content="Draw Mandelbrot set" Click="DrawMandelbrotSet_Click" />


<!--加载一个选取的图片,并使用  SetSource  方法将其显示在 WriteableBitmap 中-->
 <Button x:Name="Scenario4SetSourceButton"              Content="Load image using SetSource" Click="LoadImageUsingSetSource_Click" />


<!--加载一个选择的图片,并使用  BitmapDecoder 解码像素并复制到  WriteableBitmap 中。-->
<Button x:Name="Scenario4LoadImageButton"       Content="Load image using PixelBuffer" Click="LoadImageUsingPixelBuffer_Click" />


显示结果的容器:

<Viewbox Width="400" Height="300" x:Name="Scenario4ImageContainer">
    <Image x:Name="Scenario4Image" />
</Viewbox>            


在相应的  C# 中,定义一个全局的  WriteableBitmap:

 
//下面的操作都是用这个对象
private WriteableBitmap Scenario4WriteableBitmap;

 

在页面的构造函数中,使用 Image 控件的容器 Scenario4ImageContainer 控件的尺寸初始化这个对象:

 Scenario4WriteableBitmap = new WriteableBitmap((int)Scenario4ImageContainer.Width, (int)Scenario4ImageContainer.Height);
 Scenario4Image.Source = Scenario4WriteableBitmap;

 


第一个按钮的单击事件:

private async void DrawMandelbrotSet_Click(object sender, RoutedEventArgs e)
        {
              int pixelWidth = Scenario4WriteableBitmap.PixelWidth;
            int pixelHeight = Scenario4WriteableBitmap.PixelHeight;

            // 在一个后台线程中异步绘制 曼德尔勃特集
            byte[] result = null;
            await ThreadPool.RunAsync(new WorkItemHandler(
                (IAsyncAction action) =>
                {
                    result = DrawMandelbrotGraph(pixelWidth, pixelHeight);
                }
                ));

            // 打开一个流,用来复制图片到  WriteableBitmap的 像素缓冲区
            using (Stream stream = Scenario4WriteableBitmap.PixelBuffer.AsStream())
            {
                await stream.WriteAsync(result, 0, result.Length);
            }

            // 绘制  WriteableBitmap
            Scenario4WriteableBitmap.Invalidate(); //请求绘制或重绘整个位图。
        }

        private byte[] DrawMandelbrotGraph(int width, int height)
        {
            //每个像素需要 4 字节
            byte[] result = new byte[width * height * 4];
            int resultIndex = 0;

            // 当测试时,最大次数的迭代,来判断一个点是否在这个集中
            int maxIterationCount = 50;

            // 选择间隔
            //Complex : 表示一个复数。
            Complex minimum = new Complex(-2.5, -1.0);
            Complex maximum = new Complex(1.0, 1);

            // Normalize x and y values based on chosen interval and size of WriteableBitmap
            double xScaleFactor = (maximum.Real - minimum.Real) / width;
            double yScaleFactor = (maximum.Imaginary - minimum.Imaginary) / height;

            //在 xy 平面绘制 曼德尔勃特集
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    Complex c = new Complex(minimum.Real + x * xScaleFactor, maximum.Imaginary - y * yScaleFactor);
                    Complex z = new Complex(c.Real, c.Imaginary);

                    //用简单的逃逸时间算法进行迭代
                    int iteration = 0;
                    while (z.Magnitude < 2 && iteration < maxIterationCount)
                    {
                        z = (z * z) + c;
                        iteration++;
                    }

                    // 基于概率的设置像素的阴影
                    byte grayScaleValue = Convert.ToByte(255 - 255.0 * iteration / maxIterationCount);
                    result[resultIndex++] = grayScaleValue; // Green value of pixel
                    result[resultIndex++] = grayScaleValue; // Blue value of pixel
                    result[resultIndex++] = grayScaleValue; // Red value of pixel
                    result[resultIndex++] = 255;            // Alpha value of pixel
                }
            }

            return result;
        }


显示结果 :

 

第二个按钮的 单击事件:

//用户选取文件后,通过 SetSource() 方法进行赋值
 private async void LoadImageUsingSetSource_Click(object sender, RoutedEventArgs e)
 {
     
     FileOpenPicker picker = new FileOpenPicker();
     picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
     picker.FileTypeFilter.Add(".png");
     picker.FileTypeFilter.Add(".jpeg");
     picker.FileTypeFilter.Add(".jpg");
     picker.FileTypeFilter.Add(".bmp");

     StorageFile file = await picker.PickSingleFileAsync();

     if (file != null)
     {
         using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
         {
             try
             {
                 await Scenario4WriteableBitmap.SetSourceAsync(fileStream);
             }
             catch (TaskCanceledException)
             {
                 // 如果用户重复点击按钮,从而设置 WriteableBitmap 对象的 Source 属性的操作失败
             }
         }
     }
 }

 

显示截图:

 

 

第三个按钮的 单击事件:

private async void LoadImageUsingPixelBuffer_Click(object sender, RoutedEventArgs e)
{
    //这个方法通过把一张图片编码到一个 byte 流中,然后加载到 
    //WriteableBitmap 中,并且把结果复制到一个 WriteableBitmap 的
    //像素的 buffer(缓冲区) 中
    FileOpenPicker picker = new FileOpenPicker();
    picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
    picker.FileTypeFilter.Add(".png");
    picker.FileTypeFilter.Add(".jpeg");
    picker.FileTypeFilter.Add(".jpg");
    picker.FileTypeFilter.Add(".bmp");

    StorageFile file = await picker.PickSingleFileAsync();

      if (file != null)
    {
        using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
        {

            // 异步创建新的 BitmapDecoder 并使用流将其初始化。
            BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);
            
        


// 缩放图像到大小适当的尺寸 // 包含可应用于像素或位图数据的转换集。 BitmapTransform transform = new BitmapTransform() {
//
指定任何转换缩略图的高度(以像素为单位)。 ScaledWidth = Convert.ToUInt32(Scenario4WriteableBitmap.PixelWidth), ScaledHeight = Convert.ToUInt32(Scenario4WriteableBitmap.PixelHeight)}; //使用指定参数异步请求帧的像素数据。 PixelDataProvider pixelData = await decoder.GetPixelDataAsync( BitmapPixelFormat.Bgra8, // WriteableBitmap 使用 BGRA 格式 BitmapAlphaMode.Straight, transform, // EXIF 方向标志被忽略。未执行旋转或翻转操作。 //This sample ignores Exif orientation ExifOrientationMode.IgnoreExifOrientation, // 未执行颜色管理 ColorManagementMode.DoNotColorManage); // 一个包含图像解码数据的数组,可以在显示之前修改 //返回内部存储的像素数据。 byte[] sourcePixels = pixelData.DetachPixelData(); // 打开一个流,并将图像的内容复制到 WriteableBitmap 的像素缓冲区中 using (Stream stream = Scenario4WriteableBitmap.PixelBuffer.AsStream()) { //将字节序列异步写入当前流,并将流的当前位置向前移动写入的字节数。 await stream.WriteAsync(sourcePixels, 0, sourcePixels.Length); } } // 重新绘制这个 WriteableBitmap 对象 //请求绘制或重绘整个位图。 Scenario4WriteableBitmap.Invalidate(); } }


显示结果和 上一个方法的结果相同。

posted @ 2012-11-15 17:58  博琼  阅读(869)  评论(0编辑  收藏  举报