Refresh an ImageSource efficiently: BitmapImage vs DrawingImage

1.1k views Asked by At

I have a WPF control with a GeometryModel3D with DiffuseMaterial using an ImageBrush with data bound ImageSource.

My goal is to display a "cross-section" while hovering the mouse, and for that I can already get the proper position on the object. The problem is: There is no "3D Line" in WPF.

I have made a test drawing the line in the image I use for ImageSource and the visual result is exactely what I want.

So I plan to do the following: generate the base image once, and then draw the appropriate line on it, setting the property used as ImageSource.

I have considered two approaches:

  1. Have the bound ImageSource of type BitmapImage. Then I create a System.Drawing.Bitmap once with the blank texture (without the line), and then each time I want the line to change position, I recreate the BitmapImage drawing a line with System.Drawing.Graphics;

  2. Have the bound ImageSource of type DrawingGroup. Then I create a System.Windows.Media.ImageDrawing once, and then each time I want the line to change position, I recreate the DrawingGroup by changing only the GeometryDrawing composed by one single line.

Is there any inherent advantage of one method over the other?

2

There are 2 answers

0
heltonbiker On

I ended up replacing the old GDI+ based "Graphics over Bitmap and then convert to BitmapImage" by a very WPF/XAML friendly way of generating the image with a somewhat bulky but actually very straightforward way of stacking "layers" of Drawing objects, with elimination of A LOT of code-behind.

The line itself is a hard-coded one, with its Geometry.Transform.Y property being directly set by events in code-behind using the alturaFatia Name.

<DiffuseMaterial>
    <DiffuseMaterial.Brush>
        <ImageBrush>
            <ImageBrush.ImageSource>
                <DrawingImage>
                    <DrawingImage.Drawing>
                        <DrawingGroup>
                            <DrawingGroup.ClipGeometry>
                                <RectangleGeometry Rect="{Binding LimitesMapa}" />
                            </DrawingGroup.ClipGeometry>
                            <ImageDrawing x:Name="MapaAtivo"
                                ImageSource="{Binding MapaAtivo}" Rect="{Binding LimitesMapa}"/>
                            <GeometryDrawing>
                                <GeometryDrawing.Pen>
                                    <Pen Thickness="2" Brush="Blue"/>
                                </GeometryDrawing.Pen>                                                              
                                <GeometryDrawing.Geometry>
                                    <LineGeometry>
                                        <LineGeometry.StartPoint>
                                            <Point X="-200" Y="0"/>
                                        </LineGeometry.StartPoint>
                                        <LineGeometry.EndPoint>
                                            <Point X="200" Y="0" />
                                        </LineGeometry.EndPoint>
                                        <LineGeometry.Transform>
                                            <TranslateTransform x:Name="alturaFatia" Y="-200" />
                                        </LineGeometry.Transform>
                                    </LineGeometry>
                                </GeometryDrawing.Geometry>
                            </GeometryDrawing>
                        </DrawingGroup>
                    </DrawingImage.Drawing>
                </DrawingImage>
            </ImageBrush.ImageSource>
        </ImageBrush>
    </DiffuseMaterial.Brush>
</DiffuseMaterial>
1
Sheridan On

I must admit that I've never actually tested the performance difference, but I know that the Drawing class enables a light-weight way to manipulate basic shapes and images. From the Drawing Class page on MSDN:

Drawing objects are light-weight objects that enable you to add geometric shapes, images, text, and media to an application. Drawing objects are considered light-weight because they do not provide support for Layout, Input Overview, and focus. Because of their performance benefits, drawings are ideal for backgrounds and clip art. You also use drawings when programming at the Visual level.

Conversely, the BitmapImage class has all sorts of additional extra functionality and convenience features built into it, making it less light-weight than the Drawing class. From the Imaging Overview page on MSDN:

BitmapImage is a specialized BitmapSource that is optimized for Extensible Application Markup Language (XAML) loading and is an easy way to display images as the Source of an Image control.