{"id":3699,"date":"2013-02-28T15:23:24","date_gmt":"2013-02-28T23:23:24","guid":{"rendered":"http:\/\/blog.xamarin.com\/?p=3699"},"modified":"2013-02-28T15:23:24","modified_gmt":"2013-02-28T23:23:24","slug":"android-tricks-vignette-image-effect","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/android-tricks-vignette-image-effect\/","title":{"rendered":"Android Tricks: Vignette Image Effect"},"content":{"rendered":"<p>\t\t\t\t<em>The code in this blog post is based on code from Romain Guy&#8217;s <a href=\"http:\/\/www.curious-creature.org\/2012\/12\/11\/android-recipe-1-image-with-rounded-corners\/\">blog<\/a>.<\/em><\/p>\n<p>Today, we are going to discuss a really nice effect that you can apply to your <code>ImageView<\/code> to automatically add rounded corners and extra shadowing to the displayed <code>Bitmap<\/code>:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/vignette-image-300x207.png\" alt=\"vignette-image\" width=\"300\" height=\"207\" class=\"aligncenter size-medium wp-image-3700\" \/><\/p>\n<p>These effects are based on a couple of <code>Shader<\/code> classes like <code>BitmapShader<\/code>, <code>RadialGradient<\/code> and <code>ComposeShader<\/code>, so it&#8217;s also a nice introduction if you have not previously used them. The code of the <code>Drawable<\/code> wrapper that you use on your source <code>Bitmap<\/code> follows:<\/p>\n<div style=\"font-size: 11px\">\n<pre class=\"lang:csharp decode:true\">\nusing System;\n\nusing Android.Graphics;\nusing Android.Graphics.Drawables;\n\npublic class VignetteDrawable : Drawable\n{\n\tbool useGradientOverlay;\n\tfloat cornerRadius;\n\tRectF rect = new RectF ();\n\tBitmapShader bitmapShader;\n\tPaint paint;\n\tint margin;\n\t\n\tpublic VignetteDrawable (Bitmap bitmap, float cornerRadius = 5, int margin = 3, bool withEffect = true)\n\t{\n\t\tthis.useGradientOverlay = withEffect;\n\t\tthis.cornerRadius = cornerRadius;\n\t\t\n\t\tbitmapShader = new BitmapShader (bitmap, Shader.TileMode.Clamp, Shader.TileMode.Clamp);\n\t\t\n\t\tpaint = new Paint () { AntiAlias = true };\n\t\tpaint.SetShader (bitmapShader);\n\t\t\n\t\tthis.margin = margin;\n\t}\n\t\n\tprotected override void OnBoundsChange (Rect bounds)\n\t{\n\t\tbase.OnBoundsChange (bounds);\n\t\trect.Set (margin, margin, bounds.Width () - margin, bounds.Height () - margin);\n\t\t\n\t\tif (useGradientOverlay) {\n\t\t\tvar colors = new int[] { 0, 0, 0x7f000000 };\n\t\t\tvar pos = new float[] { 0.0f, 0.7f, 1.0f };\n\t\t\tRadialGradient vignette = new RadialGradient (rect.CenterX (),\n\t\t\t                                              rect.CenterY () * 1.0f \/ 0.7f,\n\t\t\t                                              rect.CenterX () * 1.3f,\n\t\t\t                                              colors,\n\t\t\t                                              pos, Shader.TileMode.Clamp);\n\t\t\t\n\t\t\tMatrix oval = new Matrix ();\n\t\t\toval.SetScale (1.0f, 0.7f);\n\t\t\tvignette.SetLocalMatrix (oval);\n\t\t\t\n\t\t\tpaint.SetShader (new ComposeShader (bitmapShader, vignette, PorterDuff.Mode.SrcOver));\n\t\t}\n\t}\n\t\n\tpublic override void Draw (Canvas canvas)\n\t{\n\t\tcanvas.DrawRoundRect (rect, cornerRadius, cornerRadius, paint);\n\t}\n\t\n\tpublic override int Opacity {\n\t\tget {\n\t\t\treturn (int)Format.Translucent;\n\t\t}\n\t}\n\t\n\tpublic override void SetAlpha (int alpha)\n\t{\n\t\tpaint.Alpha = alpha;\n\t}\n\t\n\tpublic override void SetColorFilter (ColorFilter cf)\n\t{\n\t\tpaint.SetColorFilter (cf);\n\t}\n}\n<\/pre>\n<\/div>\n<p>Usage of this class is pretty self-explanatory: together with the mandatory <code>Bitmap<\/code> parameter, you can set the corner radius and margin used to paint the image. You can also turn off the shadowing step using the <code>withEffect<\/code> parameter if it doesn&#8217;t go too well with your <code>Bitmap<\/code> (which is generally the case when using icons with a dominant solid color). When set up, use the <code>SetImageDrawable<\/code> method of the <code>ImageView<\/code> class to display the final result. Note that you need to give it a manual size for the code to behave correctly.<\/p>\n<p>Below is an example instantiation:<\/p>\n<pre class=\"lang:csharp decode:true\">\nvar bmp = BitmapFactory.DecodeResource (Resources, Resource.Drawable.pic1);\nimageView.SetImageDrawable (new VignetteDrawable (bmp, cornerRadius: 20, withEffect: true));\n<\/pre>\n<p>Now, let&#8217;s talk about how it actually works. As mentioned before, we use two main shaders to do the magic for us. First, we use <code>BitmapShader<\/code>, which takes a <code>Bitmap<\/code> and transforms it into a texture that can be set as the source of a <code>Paint<\/code> object. Combined with the <code>DrawRoundRect<\/code> method of <code>Canvas<\/code>, it gives us a pain-free way to display our image with rounded corners without having to manually add them to the initial bitmap.<\/p>\n<p>Then, to create our halo effect, we use a gray-to-transparent <code>RadialGradient<\/code> that is set to fill the bounds of our <code>Drawable<\/code> canvas. That last shader is combined with the first one using a <code>ComposeShader<\/code> which takes two shader objects and puts them one over the other according to the specified <a href=\"http:\/\/www.cairographics.org\/operators\/\">Porter\/Duff operator<\/a> (in our case SourceOver, meaning the halo is simply layered on top of the texture).<\/p>\n<p>To show you the effect of the radial gradient on your image, here is a version where it&#8217;s applied on a solid color:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/vignette-empty-300x201.png\" alt=\"vignette-empty\" width=\"300\" height=\"201\" class=\"aligncenter size-medium wp-image-3701\" \/>\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The code in this blog post is based on code from Romain Guy&#8217;s blog. Today, we are going to discuss a really nice effect that you can apply to your ImageView to automatically add rounded corners and extra shadowing to the displayed Bitmap: These effects are based on a couple of Shader classes like BitmapShader, [&hellip;]<\/p>\n","protected":false},"author":1925,"featured_media":39167,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[5,4],"class_list":["post-3699","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-android","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>The code in this blog post is based on code from Romain Guy&#8217;s blog. Today, we are going to discuss a really nice effect that you can apply to your ImageView to automatically add rounded corners and extra shadowing to the displayed Bitmap: These effects are based on a couple of Shader classes like BitmapShader, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/3699","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/1925"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=3699"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/3699\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/39167"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=3699"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=3699"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=3699"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}