I'm displaying an image in a PictureBox
and allowing the user to specify an area in the image by providing the width and height of the rectangle.The location of the rectangle is determined programatically.
The image displayed in the picturebox is scaled down to save processing time.So if the user specifies 200X200 Rectangle this might look large in the preview image but it will be very small in the original image which can be quite large.
How can downscale or translate the Rectangle to show how it would look in the large image.Currently i'm using the following code to upscale a rectangle in the large image.Please advice.
Rectangle ConvertToLargeRect(Rectangle smallRect, Size largeImageSize, Size smallImageSize)
{
double xScale = (double)largeImageSize.Width / smallImageSize.Width;
double yScale = (double)largeImageSize.Height / smallImageSize.Height;
int x = (int)(smallRect.X * xScale + 0.5);
int y = (int)(smallRect.Y * yScale + 0.5);
int right = (int)(smallRect.Right * xScale + 0.5);
int bottom = (int)(smallRect.Bottom * yScale + 0.5);
return new Rectangle(x, y, right - x, bottom - y);
}
I'll use the following methods:
TranslatePictureBoxSelectedRectangleToImage
Translates a selected rectangle on the picture box to coordinates on the image.
TranslateImageSelectedRectangleToPictureBox
Translates a selected rectangle on the image box to coordinates on the picture box.
ScaleRectangle
Scales a rectangle by given scale factor.
TranslatePictureBoxSelectedRectangleToImage
public RectangleF TranslatePictureBoxSelectedRectangleToImage(PictureBox p,
RectangleF pictureBoxSelectedRectangle)
{
var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var imageRect = (Rectangle)method.Invoke(p, new object[] { p.SizeMode });
if (p.Image == null)
return pictureBoxSelectedRectangle;
var cx = (float)p.Image.Width / (float)imageRect.Width;
var cy = (float)p.Image.Height / (float)imageRect.Height;
var r2 = pictureBoxSelectedRectangle;
r2.Offset(-imageRect.X, -imageRect.Y);
return new RectangleF(r2.X * cx, r2.Y * cy, r2.Width * cx, r2.Height * cy);
}
TranslateImageSelectedRectangleToPictureBox
public RectangleF TranslateImageSelectedRectangleToPictureBox(PictureBox p,
RectangleF imageSelectedRectangle)
{
var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var imageRect = (Rectangle)method.Invoke(p, new object[] { p.SizeMode });
if (p.Image == null)
return imageSelectedRectangle;
var cx = (float)p.Image.Width / (float)imageRect.Width;
var cy = (float)p.Image.Height / (float)imageRect.Height;
var r2 = new RectangleF(imageSelectedRectangle.X / cx, imageSelectedRectangle.Y / cy,
imageSelectedRectangle.Width / cx, imageSelectedRectangle.Height / cy);
r2.Offset(imageRect.X, imageRect.Y);
return r2;
}
ScaleRectangle
public RectangleF ScaleRectangle(RectangleF r, float c)
{
return new RectangleF(r.X * c, r.Y * c, r.Width * c, r.Height * c);
}
Using above methods with following assumptions:
image1
in original size and image2
which is a programmatically resized version of image1
with zoom factor c
. (It means c = (float)image2.Width/(float)image1.Width
.)image2
in picture box in zoom mode. Question 1 - Having r1
as selected rectangle on picureBox1
, what is the rectangle size and location on image1
?
The first method shows how you can convert r1
on picture box, to a rectangle on image2
. To convert it to the rectangle on image1
, since you know the zoom factor which you used to create image2 from image1, it's enough to apply the same zoom factor on result of first method:
//First convert rectangle of pictureBox1 to rectangle of image2
var r2 = TranslatePictureBoxSelectedRectangleToImage(pictureBox1, r1);
//Then convert rectangle of image2 to rectangle of image1
var result = ScaleRectangle(r2, 1f/c);
Question 2 - Having r1
as selected rectangle on image1
, what is the rectangle size and location on pictureBox1
?
The second method shows how you can convert r1
on image2
, to a rectangle on pictureBox1
. To convert from a rectangle on image1
, since you know the zoom factor which you used to create image2 from image1, it's enough to apply the same zoom factor on r1
to get the rectangle on image2
, then use the second method:
//First convert rectangle of the image1 to rectangle of image2
var r2 = ScaleRectangle(r1, c);
//Then convert rectangle of image2 to rectangle of pictureBox1
var result = TranslateImageSelectedRectangleToPictureBox(pictureBox1, r2);