-
Jul 28th, 2017, 10:37 AM
#1
Thread Starter
Hyperactive Member
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:
Code:
String myImageFile = @"C:\MyFolder\MyImage.jpg";
BitmapImage myBitmap = new BitmapImage();
myBitmap.BeginInit();
myBitmap.UriSource = new Uri(myImageFile, UriKind.Absolute);
myBitmap.EndInit();
Then I place the bitmap on the canvas:
Code:
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?
-
Aug 26th, 2017, 08:43 PM
#2
Hyperactive Member
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:
Private Function CalculateCanvasImageSize() As Size ' Get the original image from the canvas (NOTE: this will throw an error if the ImageSource is empty) Dim CanvasImage As BitmapImage = CType(imgCanvas.Background, ImageBrush).ImageSource ' 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. If CanvasImage.Width >= imgCanvas.ActualWidth AndAlso CanvasImage.Height >= imgCanvas.ActualHeight Then ' Where the original image is bigger in width and height than the canvas size Dim RatioX As Decimal = CanvasImage.Width / imgCanvas.ActualWidth Dim RatioY As Decimal = CanvasImage.Height / imgCanvas.ActualHeight If RatioX = RatioY Then Return New Size(imgCanvas.ActualWidth, imgCanvas.ActualHeight) ElseIf RatioX > RatioY Then Return New Size(imgCanvas.ActualWidth, Math.Round(CanvasImage.Height / RatioX, 0, MidpointRounding.AwayFromZero)) ElseIf RatioX < RatioY Then Return New Size(Math.Round(CanvasImage.Width / RatioY, 0, MidpointRounding.AwayFromZero), imgCanvas.ActualHeight) End If ElseIf CanvasImage.Width >= imgCanvas.ActualWidth Then ' If only the width is bigger Dim ScaleX As Decimal = CanvasImage.Width / imgCanvas.ActualWidth Return New Size(imgCanvas.ActualWidth, Math.Round(CanvasImage.Height / ScaleX, 0, MidpointRounding.AwayFromZero)) ElseIf CanvasImage.Height >= imgCanvas.ActualHeight Then ' If only the height is bigger Dim ScaleY As Decimal = CanvasImage.Height / imgCanvas.ActualHeight Return New Size(Math.Round(CanvasImage.Width / ScaleY, 0, MidpointRounding.AwayFromZero), imgCanvas.ActualHeight) Else ' The canvas must be bigger in width and height than the source image Dim RatioX As Decimal = imgCanvas.ActualWidth / CanvasImage.Width Dim RatioY As Decimal = imgCanvas.ActualHeight / CanvasImage.Height If RatioX = RatioY Then Return New Size(imgCanvas.ActualWidth, imgCanvas.ActualHeight) ElseIf RatioX < RatioY Then Return New Size(imgCanvas.ActualWidth, Math.Round(CanvasImage.Height * RatioX, 0, MidpointRounding.AwayFromZero)) ElseIf RatioX > RatioY Then Return New Size(Math.Round(CanvasImage.Width * RatioY, 0, MidpointRounding.AwayFromZero), imgCanvas.ActualHeight) End If End If End Function
And then to test it, use the following in a button click between the resizing of the canvas:
VB.NET Code:
' Get the original image from the Canvas (for the example only) Dim OriginalImage As BitmapImage = CType(imgCanvas.Background, ImageBrush).ImageSource ' This will retrieve the size of the scaled image from the method below Dim CanvasImageSize As Size = Me.CalculateCanvasImageSize ' And this is just to show the results 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.
HTH
Last edited by JayJayson; Aug 26th, 2017 at 08:47 PM.
Reason: Code Highlighting
-
Sep 8th, 2017, 06:37 PM
#3
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.
Code:
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
Else
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:
Code:
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)
imageCanvas.Children.Add(r)
End Sub
BB
Last edited by boops boops; Sep 8th, 2017 at 06:46 PM.
Reason: slight improvement to function
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|