#699 – Converting an Image Control to a Bitmap

You may want to work with the image from an Image control as a standard Windows bitmap.  You can convert the System.Windows.Controls.Image to a System.Drawing.Bitmap as follows (imgLife is an Image control):

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            RenderTargetBitmap rtBmp = new RenderTargetBitmap((int)imgLife.ActualWidth, (int)imgLife.ActualHeight,
                96.0, 96.0, PixelFormats.Pbgra32);

            imgLife.Measure(new System.Windows.Size((int)imgLife.ActualWidth, (int)imgLife.ActualHeight));
            imgLife.Arrange(new Rect(new System.Windows.Size((int)imgLife.ActualWidth, (int)imgLife.ActualHeight)));

            rtBmp.Render(imgLife);

            PngBitmapEncoder encoder = new PngBitmapEncoder();
            MemoryStream stream = new MemoryStream();
            encoder.Frames.Add(BitmapFrame.Create(rtBmp));

            // Save to memory stream and create Bitamp from stream
            encoder.Save(stream);
            System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(stream);

            // Demonstrate that we can do something with the Bitmap
            bitmap.Save(@"D:\Temp\Life.png", ImageFormat.Png);

            // Optionally, if we didn't need Bitmap object, but
            // just wanted to render to file, we could:
            //encoder.Save(new FileStream(@"D:\Temp\Life-Other.png", FileMode.Create));
        }

#566 – Setting Properties of an Effect in Blend

Like other elements, you can set various properties of an effect in Blend using the Properties panel.

In the example below, we’ve added a DropShadowEffect to a Label.  If you select the effect in the XAML editor or the Objects and Timeline panel, you’ll see several properties that we can set for this effect.

For example, we can increase the ShadowDepth, so that the shadow appears further away from the Label.

#564 – Other Places to Get Third Party Effects

An effect in WPF changes the appearance of a visual element.  The .NET Framework comes with only a couple of effects, but you can find a few other third party effects on the web.

Here are some of the effects from the Pixel Shader Effects Library:

 

#563 – Additional Effects in Expression SDK

In addition to the two effects that come with the .NET Framework, you can get access to a number of other effects when you download and install the Expression Blend SDK for .NET 4.

Once you install the SDK, you’ll see the new effects show up in the Effects folder of the Assets panel.

The effects include:

  • Bloom – Make bright areas appear brighter
  • Color Tone – Render a visual using shades of two colors
  • Emboss – Make visual appear raised or stamped
  • Magnify – Magnify a circular area
  • Monochrome – Render using shades of a single color
  • Pixelate – Reduce resolution, rendering as large pixels
  • Ripple – Apply visual that looks like rippling liquid
  • Sharpen – Sharpen image edges
  • Swirl – Apply effect that twists entire image

 

#562 – Setting an Effect for an Element in Blend

You can set the value of the Effect property for any control deriving from UIElement.  An effect is a two-dimensional graphical effect applied to the control when it is rendered.

To apply an effect to a control in Blend, start by left-clicking on the Effects folder in the Assets panel.

The .NET Framework comes with two pre-defined effects, located in PresentationCore–BlurEffect and DropShadowEffect.  (The other effects shown above come from the Expression SDK for .NET 4).  You can drag either of these effects onto a control on the artboard, or a control listed in the Objects and Timeline panel.

Two Label controls, before adding effects:

After adding effects:

Corresponding XAML:

		<Label Content="Drop Shadow Effect" FontFamily="Cooper Black" FontSize="48"
			Margin="20,20,20,5" Foreground="#FF047800" HorizontalAlignment="Center">
			<Label.Effect>
				<DropShadowEffect/>
			</Label.Effect>
		</Label>
		<Label Content="Blur Effect" FontFamily="Cooper Black" FontSize="48"
			Margin="20,5,20,20" Foreground="#FF047800" HorizontalAlignment="Center">
			<Label.Effect>
				<BlurEffect/>
			</Label.Effect>
		</Label>

#561 – Drawing a 3D Donut Using a Radial Gradient

Here’s another visual effect that you can easily create in WPF and Blend, using a gradient.

Let’s say that you want to draw a ring or donut-shaped object that looks 3D.  You can start by using the Ellipse shape to draw a circle.

Next, set the Fill property of the Ellipse to use a radial gradient.  Define five gradient stops, as shown, and use the gradient tool to position them as shown.

For the hole in the middle of the donut, you can use an opacity mask.  Use a paint program to create an opaque circle that is the same size as the circle, but with a smaller transparent circle in its center.  (Trick: Run your app and screen capture what you have so far, then tweak it in a paint program).  Finally, set this image as the OpacityMask of the Ellipse.

<Ellipse.OpacityMask>
    <ImageBrush ImageSource="Images\Mask.png"/>
</Ellipse.OpacityMask>

Voila.

#560 – Using a Radial Gradient to Create a 3D Effect

You can use a radial gradient in WPF to create a 3D effect on a shape.  In the example below, we set up a gradient on a circle (Ellipse shape) to make the circle look like a 3D sphere.

Start by drawing a simple circle (Ellipse).

Now specify a radial gradient for the Fill property.

Next, click on the Gradient tool and then slide the radial gradient off-center, relative to the ellipse.

Finally, adjust the gradient so that the center starts out white and fades to a darker color at the edge of the gradient.  You can also enlarge the gradient so that its outer edge lines up with the outer edge of the ellipse.

Here’s the final result:

#242 – Drawing Text Using DrawGlyphRun

If you want an even lower-level mechanism for drawing text than provided by DrawingContext.DrawText, you can use DrawingContext.DrawGlyphRun.

DrawGlyphRun lets you draw text based on glyphs, which are individual characters within a font that typically represent a single character in a language.

Below is an example of rendering the word “Wow” using DrawGlyphRun, in a custom DrawingVisual.

    class MyDrawingVisual : DrawingVisual
    {
        public MyDrawingVisual()
        {
            using (DrawingContext dc = RenderOpen())
            {
                GlyphRun gr = new GlyphRun(
                    new GlyphTypeface(new Uri(@"C:\Windows\Fonts\BKANT.TTF")),
                    0,       // Bi-directional nesting level
                    false,   // isSideways
                    96,      // pt size
                    new ushort[] { 58, 82, 90 },   // glyphIndices
                    new Point(100.0, 100.0),           // baselineOrigin
                    new double[] { 80.0, 45.0, 0.0 },  // advanceWidths
                    null,    // glyphOffsets
                    null,    // characters
                    null,    // deviceFontName
                    null,    // clusterMap
                    null,    // caretStops
                    null);   // xmlLanguage

                // Draw the text at a location
                dc.DrawGlyphRun(Brushes.Black, gr);
            }
        }
    }

The glyphIndices parameter specifies a list of indexes into the font for the glyphs that are to be rendered.

#241 – Rendering Text Using DrawText

You can render text into a visual using the DrawText method of a DrawingContextDrawText renders text that is represented by an instance of FormattedText into the drawing context at a specified location.

Below is an example of drawing some text into a custom DrawingVisual.

    class MyDrawingVisual : DrawingVisual
    {
        public MyDrawingVisual()
        {
            using (DrawingContext dc = RenderOpen())
            {
                // Create formatted text--in a particular font at a particular size
                FormattedText ft = new FormattedText(
                    "When things are at their worst I find something always happens.",
                    CultureInfo.CurrentCulture,
                    FlowDirection.LeftToRight,
                    new Typeface(new FontFamily("Century"), FontStyles.Normal, FontWeights.Bold, FontStretches.Normal),
                    24,    // 36 pt type
                    Brushes.Black);

                // Draw the text at a location
                dc.DrawText(ft, new Point(10.0, 10.0));
            }
        }
    }

Once we host this DrawingVisual in an UIElement, we can see the text in a window:

#240 – Shape vs. DrawingVisual

We’ve seen two ways to render custom 2D geometries–by inheriting from DrawingVisual and hosting in an UIElement or by inheriting from Shape and instancing your object directly in XAML.

You might wonder which of these methods to use for drawing custom 2D objects.

Shape is at a higher level of abstraction than DrawingVisualShape provides the following functionality, beyond what you get with DrawingVisual:

  • Derives from FrameworkElement, so you can include your subclass directly into a logical tree as a child of a Panel
  • Takes care of things like the Pen used to render the geometry (Stroke and StrokeThickness) and the Brush used to fill the interior of the geometry

Below is an example of including several instances of a custom Shape and specifying different stroke/fill properties for each instance.

	<StackPanel Orientation="Horizontal">
		<local:MyWeirdShape Stroke="Black" StrokeThickness="2" Fill="Orange"/>
		<local:MyWeirdShape Stroke="Red" StrokeThickness="1" Fill="DimGray"/>
		<local:MyWeirdShape Stroke="Blue" StrokeThickness="10" Fill="White"/>
	</StackPanel>

Follow

Get every new post delivered to your Inbox.

Join 238 other followers