You need to calculate the zoom and the offset of the image when it is zoomed.
Here is how to do that; this assumes the PictureBox
is indeed in Zoom
mode, not in Stretch
mode. If you stretch it you need to calculate the zooms for x and y separately..
SizeF sp = pictureBox5.ClientSize;
SizeF si = pictureBox5.Image.Size;
float rp = sp.Width / sp.Height; // calculate the ratios of
float ri = si.Width / si.Height; // pbox and image
float zoom = (rp > ri) ? sp.Height / si.Height : sp.Width / si.Width;
float offx = (rp > ri) ? (sp.Width - si.Width * zoom) / 2 : 0;
float offy = (rp <= ri)? (sp.Height - si.Height * zoom) / 2 : 0;
Point offset = Point.Round(new PointF(offx, offy));
You calculate this after setting the Image
and after resizing the PictureBox
..
Now you can transform each drawn point into a zoomed or an unzoomed coordinate:
PointF zoomed(Point p1, float zoom, Point offset)
{
return (new PointF(p1.X * zoom + offset.X, p1.Y * zoom + offset.Y));
}
PointF unZoomed(Point p1, float zoom, Point offset)
{
return (new PointF((p1.X - offset.X) / zoom, (p1.Y - offset.Y) / zoom));
}
Here is a demo the draws on to either a normal (left) or a zoomed in (middle) image. To the right is the result of placing your GetSelectedArea
bitmap onto a PictureBox
with a checkerbox background:
Case 1: If you store the points as they come in: In your GetSelectedArea
method use this point list instead:
private Bitmap GetSelectedArea(Image source, Color bg_color, List<Point> points)
{
var unzoomedPoints =
points.Select(x => Point.Round((unZoomed(Point.Round(x), zoom, offset))))
.ToList();
// Make a new bitmap that has the background
After this replace each reference to points
in the method by one to unzoomedPoints
. Actually there are just two of them..
Case 2: If you store the points already 'unZoomed' :
Points.Add(unZoomed(e.Location, zoom, offset));
you can use the list directly..
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…