Search code examples
c#.net-3.5drawing.net-4.5system.windows.media

custom drawing portion of image .net 4.5


I am custom drawing two zoom-in images on the screen, one next to each other. Each one of them occupies half of the screen.

I have previously done it in .net 3.5 (I think) by overriding the OnPaint():

    //using System.Drawing

    /// <summary>
    /// Custom drawing
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.DrawImage(Image, DestRectangle, SrcRectangle, GraphicsUnit);
    }

The description of the DrawImage method: "Draws the specified portion of the specified Image at the specified location and with the specified size." (MSDN)

I am trying to achieve the same thing using .net 4.5. I am overriding the OnRender and using the DrawingContext object to perform my drawings. Basically this is my loop:

    //using System.Windows.Media;

    /// <summary>
    /// Overide the OnRender to have access to a lower level of drawing.
    /// </summary>
    /// <param name="drawingContext"></param>
    protected override void OnRender(DrawingContext drawingContext)
    {
        drawingContext.DrawImage(BitmapImage_Left, Window_LeftHalf);
        drawingContext.DrawImage(BitmapImage_Right, Window_RightHalf);
    }

It works just fine if I want to display the stretched picture. What I want is to display (in Window_LeftHalf and Window_RightHalf) a portion of the picture (like zoom-in). Basically what graphics.DrawImage (look above) does, but using the DrawingContext object.

I have tried to look at MSDN but I couldn't pull anything interesting out. Maybe creating a buffer that is later used by the DrawingContext? I'm almost sure there is the need for an intermediate object that holds the zoomed-in images. Any ideas?

UPDATE: I am using the mouse to navigate through the image, so performance is important. For example:

    /// <summary>
    /// Handles the mouse move events.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private static void MouseMoveEventHandler(RoutedEventArgs e)
    {
        // The size of the crop is always the same
        // but the portion of the picture different.
        crop.X += mouseDelta.X;
        crop.Y += mouseDelta.Y;
    }

Solution

  • Take a look at the CroppedBitmap class. Just as you used to be able to do with e.Graphics.DrawImage(), CroppedBitmap allows you to specify just the portion of the image you're interested in.

    Here's an example:

    protected override void OnRender(System.Windows.Media.DrawingContext dc)
    {
        int halfWidth = (int)this.Width / 2;
        int height = (int)this.Height;
        BitmapImage leftImage = new BitmapImage(new Uri(@"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg"));
        BitmapImage rightImage = new BitmapImage(new Uri(@"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"));
        CroppedBitmap leftImageCropped = new CroppedBitmap(leftImage, new Int32Rect(0, 0, halfWidth, height));
        CroppedBitmap rightImageCropped = new CroppedBitmap(rightImage, new Int32Rect(0, 0, halfWidth, height));
        dc.DrawImage(leftImageCropped, new System.Windows.Rect(0, 0, leftImageCropped.Width, height));
        dc.DrawImage(rightImageCropped, new System.Windows.Rect(halfWidth, 0, halfWidth, height));
    }