Results 1 to 3 of 3
  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2009

    Question How to find the size of a Bitmap on a canvas?

    Okay, I've got a canvas sized at 800 x 600, and I want to read in a bitmap and place it on the canvas. This works fine, and I've got the stretch property set to "Uniform"... so the bitmap grows/shrinks to fit the canvas, but retains the original aspect ratio. All of this works fine, but is there a way to find out what the bitmap dimensions are after it is resized by the uniform stretch?

    I load the jpg into a bitmap image:

                String myImageFile = @"C:\MyFolder\MyImage.jpg";
                BitmapImage myBitmap = new BitmapImage();
                myBitmap.UriSource = new Uri(myImageFile, UriKind.Absolute);
    Then I place the bitmap on the canvas:

                ImageBrush imageBrush = new ImageBrush();
                imageBrush.ImageSource = myBitmap;
                imageBrush.Stretch = Stretch.Uniform;
                imgCanvas.Background = imageBrush;
    Here's the issue. Because it retains the aspect ratio of the original image during the stretch, which is quite likely to be different from the aspect ratio of the canvas, there are probably going to be unused portions of the canvas. Later, when the user is clicking on the canvas to add elements to it (which also works fine), I don't want to let him/her click outside of the image area.

    So, how do I find out the new, uniform stretched, size of the bitmap?

  2. #2
    Hyperactive Member
    Join Date
    Apr 2011

    Re: How to find the size of a Bitmap on a canvas?

    I'm not sure of a built in way to get the size from the scaled image within the canvas. You can calculate the size yourself easily enough by comparing the width/height of the canvas with the original image.

    For the sake of ease, I have used VB, but you should be able to convert this easily enough to C#.

    Firstly add the following function:
    VB.NET Code:
    1. Private Function CalculateCanvasImageSize() As Size
    2.   ' Get the original image from the canvas (NOTE: this will throw an error if the ImageSource is empty)
    3.   Dim CanvasImage As BitmapImage = CType(imgCanvas.Background, ImageBrush).ImageSource
    5.   ' The following conditions will work out whether the image fills the width or height of the canvas. Then calculates the ratio of that axis compared to the original image. The ratio can then be used to find the scaled size of the other axis.
    7.   If CanvasImage.Width >= imgCanvas.ActualWidth AndAlso CanvasImage.Height >= imgCanvas.ActualHeight Then
    8.     ' Where the original image is bigger in width and height than the canvas size
    9.     Dim RatioX As Decimal = CanvasImage.Width / imgCanvas.ActualWidth
    10.     Dim RatioY As Decimal = CanvasImage.Height / imgCanvas.ActualHeight
    12.     If RatioX = RatioY Then
    13.       Return New Size(imgCanvas.ActualWidth, imgCanvas.ActualHeight)
    14.     ElseIf RatioX > RatioY Then
    15.       Return New Size(imgCanvas.ActualWidth, Math.Round(CanvasImage.Height / RatioX, 0, MidpointRounding.AwayFromZero))
    16.     ElseIf RatioX < RatioY Then
    17.       Return New Size(Math.Round(CanvasImage.Width / RatioY, 0, MidpointRounding.AwayFromZero), imgCanvas.ActualHeight)
    18.     End If
    19.   ElseIf CanvasImage.Width >= imgCanvas.ActualWidth Then
    20.     ' If only the width is bigger
    21.     Dim ScaleX As Decimal = CanvasImage.Width / imgCanvas.ActualWidth
    22.     Return New Size(imgCanvas.ActualWidth, Math.Round(CanvasImage.Height / ScaleX, 0, MidpointRounding.AwayFromZero))
    23.   ElseIf CanvasImage.Height >= imgCanvas.ActualHeight Then
    24.     ' If only the height is bigger
    25.     Dim ScaleY As Decimal = CanvasImage.Height / imgCanvas.ActualHeight
    26.     Return New Size(Math.Round(CanvasImage.Width / ScaleY, 0, MidpointRounding.AwayFromZero), imgCanvas.ActualHeight)
    27.   Else
    28.     ' The canvas must be bigger in width and height than the source image
    29.     Dim RatioX As Decimal = imgCanvas.ActualWidth / CanvasImage.Width
    30.     Dim RatioY As Decimal = imgCanvas.ActualHeight / CanvasImage.Height
    32.     If RatioX = RatioY Then
    33.       Return New Size(imgCanvas.ActualWidth, imgCanvas.ActualHeight)
    34.     ElseIf RatioX < RatioY Then
    35.       Return New Size(imgCanvas.ActualWidth, Math.Round(CanvasImage.Height * RatioX, 0, MidpointRounding.AwayFromZero))
    36.     ElseIf RatioX > RatioY Then
    37.       Return New Size(Math.Round(CanvasImage.Width * RatioY, 0, MidpointRounding.AwayFromZero), imgCanvas.ActualHeight)
    38.     End If
    39.   End If
    41. End Function
    And then to test it, use the following in a button click between the resizing of the canvas:
    VB.NET Code:
    1. ' Get the original image from the Canvas (for the example only)
    2. Dim OriginalImage As BitmapImage = CType(imgCanvas.Background, ImageBrush).ImageSource
    4. ' This will retrieve the size of the scaled image from the method below
    5. Dim CanvasImageSize As Size = Me.CalculateCanvasImageSize
    7. ' And this is just to show the results
    8. MessageBox.Show(String.Format("Original Image Width: {1}{0}Original Image Height: {2}{0}{0}Canvas Image Width: {3}{0}Canvas Image Height: {4}{0}{0}Canvas Width:{5}{0}Canvas Height: {6}", Environment.NewLine, OriginalImage.Width, OriginalImage.Height, CanvasImageSize.Width, CanvasImageSize.Height, imgCanvas.ActualWidth, imgCanvas.ActualHeight))
    Finally, make sure to adapt the code to make sure the canvas contains an image before attempting to access the background.

    Last edited by jay20aiii; Aug 26th, 2017 at 08:47 PM. Reason: Code Highlighting

  3. #3
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008

    Re: How to find the size of a Bitmap on a canvas?

    Jay, I take it that your solution works (haven't tried it) but I'm certain it could be a lot simpler. Here's my own idea. It's a function with just one If-Else and a handful of declarations. Sorry, HongKongCV, it's in VB again!

    The function returns a rect structure, which provides both the size and the location (in Canvas coordinates) of the scaled image.
     Private Function GetUniformBounds(canv As Canvas, bi As BitmapImage) As Rect
          Dim x, y As Double
          Dim w As Double = canv.ActualWidth
          Dim h As Double = canv.ActualHeight
          Dim imageAspect = bi.Height / bi.Width
          If imageAspect > h / w Then
             w = h / imageAspect
             x = (canv.ActualWidth - w) / 2
             h = w * imageAspect
             y = (canv.ActualHeight - h) / 2
          End If
          Return New Rect(x, y, w, h)
      End Function
    To check that it works, you can call the following sub, which draws a semi-transparent rectangle over the image area. It assumes the variable names given in post #1:
       Private Sub CheckUniformBounds()
          Dim bounds As Rect = GetUniformBounds(imageCanvas, myBitmap)
          Dim r As New Rectangle
          r.Fill = New SolidColorBrush(Color.FromArgb(80, 0, 255, 255))
          r.Width = bounds.Width
          r.Height = bounds.Height
          Canvas.SetLeft(r, bounds.Left)
          Canvas.SetTop(r, bounds.Top)
       End Sub

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts


Click Here to Expand Forum to Full Width

We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.