[WinRT] [processing]: Create a circular image in XAML,

Source: Internet
Author: User

[WinRT] [processing]: Create a circular image in XAML,

Address: http://timheuer.com/blog/archive/2015/05/06/making-circular-images-in-xaml-easily.aspx

 

A few times ago, it seems that some cool Programs began to use a circular avatar to replace the display mode of the square or rounded corner. Me (original author. If it is not mentioned below, it refers to the author of the original article. When I noticed that some apps started to do so two years ago, I made a radical speech:

Let's take a look. There will be more and more circular portraits in the program, and there will be no more square portraits.

-- Tim Heuer (@ timheuer) February May 23, 2013

Now, this seems to be a popular trend, because everyone is doing this. I want programmers who use XAML to develop to know how to implement it. However, I still see many people asking this question, but some people try to implement it, but it becomes more complicated. Therefore, I think I should post a blog to address this issue. I have seen stupid people crop images by algorithms, store them on hard disks, and display them to their users. This is completely unnecessary. In fact, we can simply achieve this display effect.

<Ellipse Width="250" Height="250">    <Ellipse.Fill>        <ImageBrush ImageSource="ms-appx:///highfive.jpg" />    </Ellipse.Fill></Ellipse>

You will see that in the third line, we use an ImageBrush to fill in an Ellipse. Using an Ellipse can help us get a precise circular crop without any edges. The above code will show the following results:

<Ellipse Width = "250" Height = "250"> <Ellipse. fill> <ImageBrush. imageSource> <BitmapImage DecodePixelHeight = "250" DecodePixelWidth = "250" UriSource = "ms-appx: // highfive.jpg"/> </ImageBrush. imageSource> </ImageBrush> </Ellipse. fill> </Ellipse>

The DecodePixelHeight and DecodePixelWidth are used in Row 3 to tell the size of the system framework decoding. The rendered results are the same as those above. This technique is very effective when you need to show less than the source image, rather than using other odd tricks.

So hurry up and help the coders who are crazy about displaying their round portraits! Hope to help them.

 

H82258652 Note: This article is a free translation. Try to translate what the original author wants to tell you. If you have any questions, refer to the original article. Thank you!

 

The following describes how to process the Translator:

In general, we are still used to making a control. It is impossible to write such a large pile of data every time we use a circular image. Let's start it!

Create a new user control (UserControl) in Visual Studio and name it CircleImage.

Public static readonly DependencyProperty SourceProperty = DependencyProperty. register (nameof (Source), typeof (Uri), typeof (CircleImage), new PropertyMetadata (null, SourceChanged); private static void SourceChanged (DependencyObject d, DependencyPropertyChangedEventArgs e) {var obj = (CircleImage) d; var value = (Uri) e. newValue; obj. bitmapImage. uriSource = value;} public Uri Source {get {return (Uri) GetValue (SourceProperty);} set {SetValue (SourceProperty, value );}}

Then write the front-end XAML:

<UserControl    x:Class="MyApp.CircleImage"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:local="using:MyApp"    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    mc:Ignorable="d"    d:DesignHeight="300"    d:DesignWidth="400">    <Ellipse>        <Ellipse.Fill>            <ImageBrush>                <ImageBrush.ImageSource>                    <BitmapImage x:Name="bitmapImage"                                 DecodePixelWidth="1"                                 DecodePixelHeight="1" />                </ImageBrush.ImageSource>            </ImageBrush>        </Ellipse.Fill>    </Ellipse></UserControl>

Name BitmapImage as bitmapImage and use it for the above background cs code.

Here you may wonder why I converted the decoded case to 1? This is because if the decoding size is written as an integer smaller than 1, it means that the decoding function is not automatically decoded Based on the rendering size, which is the same as that of the original author at the beginning. So here I first write 1, and then dynamically adjust it according to the control size during running.

Now that we need to dynamically adjust the code, we must complete the background code and add some code and modify it as follows:

Public sealed partial class CircleImage: UserControl {public static readonly DependencyProperty SourceProperty = DependencyProperty. register (nameof (Source), typeof (Uri), typeof (CircleImage), new PropertyMetadata (null, SourceChanged); private static void SourceChanged (DependencyObject d, DependencyPropertyChangedEventArgs e) {var obj = (CircleImage) d; var value = (Uri) e. newValue; obj. bitmapImage. UriSource = value;} public Uri Source {get {return (Uri) GetValue (SourceProperty);} set {SetValue (SourceProperty, value) ;}} public CircleImage () {this. initializeComponent (); this. sizeChanged + = CircleImage_SizeChanged; // The monitoring control size changes.} Private void ReSize () {// calculate the new decoding size and perform an integer upward. Int width = (int) Math. ceiling (this. actualWidth); int height = (int) Math. ceiling (this. actualHeight); // make sure that the decoding size must be greater than 0, because the preceding result may be 0. BitmapImage. DecodePixelWidth = Math. Max (width, 1); bitmapImage. DecodePixelHeight = Math. Max (height, 1); // re-render BitmapImage. Var temp = bitmapImage. UriSource; bitmapImage. UriSource = null; bitmapImage. UriSource = temp;} private void CircleImage_SizeChanged (object sender, SizeChangedEventArgs e) {ReSize ();}}

In this way, we have completed this control. Next we will test how powerful this item is.

Test:

The testing image uses the background image of my blog, which is large enough, 1920*1080. I believe it will eat a lot of memory ^-^.

Image address: http://images.cnblogs.com/cnblogs_com/h82258652/693238/o_wallpaper_summer2013_1920X1080.jpg

Test code:

Front-end XAML code:

<Page x: Class = "MyApp. MainPage" xmlns =" http://schemas.microsoft.com/winfx/2006/xaml /Presentation "xmlns: x =" http://schemas.microsoft.com/winfx/2006/xaml "Xmlns: local =" using: MyApp "xmlns: d =" http://schemas.microsoft.com/expression/blend/2008 "Xmlns: mc =" http://schemas.openxmlformats.org/markup-compatibility/2006 "Mc: Ignorable =" d "> <Grid Background =" {ThemeResource ApplicationPageBackgroundThemeBrush} "> <Grid. rowDefinitions> <RowDefinition Height = "Auto"/> <RowDefinition/> </Grid. rowDefinitions> <StackPanel Grid. row = "0" HorizontalAlignment = "Center" Orientation = "Horizontal"> <Button Content = "load old version" Click = "BtnOld_Click"/> <Button Content = "Load new version" Click = "BtnNew_Click"/> </StackPanel> <GridView Grid. row = "1" x: Name = "gvwBigMemory"> <GridView. itemTemplate> <DataTemplate> <Ellipse Width = "100" Height = "100"> <Ellipse. fill> <ImageBrush ImageSource =" http://images.cnblogs.com/cnblogs_com/h82258652/693238/o_wallpaper_summer2013_1920X1080.jpg "/> </Ellipse. fill> </Ellipse> </DataTemplate> </GridView. itemTemplate> </GridView> <GridView Grid. row = "2" x: Name = "gvwMinMemory"> <GridView. itemTemplate> <DataTemplate> <local: CircleImage Width = "100" Height = "100" Source =" http://images.cnblogs.com/cnblogs_com/h82258652/693238/o_wallpaper_summer2013_1920X1080.jpg "/> </DataTemplate> </GridView. ItemTemplate> </GridView> </Grid> </Page>

All are placed in the GridView, And the size is set to 100*100.

Background code:

public sealed partial class MainPage : Page{    public MainPage()    {        this.InitializeComponent();    }    private void BtnOld_Click(object sender, RoutedEventArgs e)    {        gvwBigMemory.ItemsSource = Enumerable.Range(1, 100);    }    private void BtnNew_Click(object sender, RoutedEventArgs e)    {        gvwMinMemory.ItemsSource = Enumerable.Range(1, 100);    }}

It is very easy, that is, let the GridView load 100.

Okay, start!

The initial operation occupies 40.6 MB of memory. Of course, this value may be different for the next operation, which may fluctuate somewhat.

Next we will load the old version:

Surprisingly, it just ran to 250.6 MB of memory.

Let's take a look at the new version. Remember to turn it off and open it again. Otherwise, the result will be affected.

New Version:

44.6 MB! Almost no changes have taken place. It can be seen that the power is very powerful, indicating that our code has taken effect.

 

Conclusion:

We can see the impact of this small optimization. In addition, because the GridView uses virtualization by default, it is not actually loaded to 100, but it can still be seen that the old version of memory usage is very high, so it's hard to imagine how spectacular it was when we were loading 100 million. Small details may cause huge changes. Considering that there are many Windows Phone users with 512 MB of memory, this small details are still necessary.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.