Translate Rectangle Position in Zoom Mode Picturebox
I'm determining the rectangular area in an image and showing it to the user in a PictureBox.
Since the image can sometimes be very large, I'm using a PictureBox with its SizeMode
set to Zoom
.
I'm using the following code to translate the Rectangle (X, Y) coordinates:
public Point TranslateZoomMousePosition(Point coordinates)
{
// test to make sure our image is not null
if (pictureBox5.Image == null) return coordinates;
// Make sure our control width and height are not 0 and our
// image width and height are not 0
if (pictureBox5.Width == 0 || pictureBox5.Height == 0 || pictureBox5.Image.Width == 0 || pictureBox5.Image.Height == 0) return coordinates;
// This is the one that gets a little tricky. Essentially, need to check
// the aspect ratio of the image to the aspect ratio of the control
// to determine how it is being rendered
float imageAspect = (float)pictureBox5.Image.Width / pictureBox5.Image.Height;
float controlAspect = (float)pictureBox5.Width / pictureBox5.Height;
float newX = coordinates.X;
float newY = coordinates.Y;
if (imageAspect > controlAspect)
{
// This means that we are limited by width,
// meaning the image fills up the entire control from left to right
float ratioWidth = (float)pictureBox5.Image.Width / pictureBox5.Width;
newX *= ratioWidth;
float scale = (float)pictureBox5.Width / pictureBox5.Image.Width;
float displayHeight = scale * pictureBox5.Image.Height;
float diffHeight = pictureBox5.Height - displayHeight;
diffHeight /= 2;
newY -= diffHeight;
newY /= scale;
}
else
{
// This means that we are limited by height,
// meaning the image fills up the entire control from top to bottom
float ratioHeight = (float)pictureBox5.Image.Height / pictureBox5.Height;
newY *= ratioHeight;
float scale = (float)pictureBox5.Height / pictureBox5.Image.Height;
float displayWidth = scale * pictureBox5.Image.Width;
float diffWidth = pictureBox5.Width - displayWidth;
diffWidth /= 2;
newX -= diffWidth;
newX /= scale;
}
return new Point((int)newX, (int)newY);
}
Adding a frame control at the determined position:
pictureBox5.Controls.Clear();
var c = new FrameControl();
c.Size = new Size(myrect.Width, myrect.Height);
c.Location=TranslateZoomMousePosition(newPoint(myrect.Location.X,myrect.Location.Y));
pictureBox5.Controls.Add(c);
But the determined frame/rectangle location is not correct.
What am I i doing wrong?
c# .net winforms picturebox system.drawing
add a comment |
I'm determining the rectangular area in an image and showing it to the user in a PictureBox.
Since the image can sometimes be very large, I'm using a PictureBox with its SizeMode
set to Zoom
.
I'm using the following code to translate the Rectangle (X, Y) coordinates:
public Point TranslateZoomMousePosition(Point coordinates)
{
// test to make sure our image is not null
if (pictureBox5.Image == null) return coordinates;
// Make sure our control width and height are not 0 and our
// image width and height are not 0
if (pictureBox5.Width == 0 || pictureBox5.Height == 0 || pictureBox5.Image.Width == 0 || pictureBox5.Image.Height == 0) return coordinates;
// This is the one that gets a little tricky. Essentially, need to check
// the aspect ratio of the image to the aspect ratio of the control
// to determine how it is being rendered
float imageAspect = (float)pictureBox5.Image.Width / pictureBox5.Image.Height;
float controlAspect = (float)pictureBox5.Width / pictureBox5.Height;
float newX = coordinates.X;
float newY = coordinates.Y;
if (imageAspect > controlAspect)
{
// This means that we are limited by width,
// meaning the image fills up the entire control from left to right
float ratioWidth = (float)pictureBox5.Image.Width / pictureBox5.Width;
newX *= ratioWidth;
float scale = (float)pictureBox5.Width / pictureBox5.Image.Width;
float displayHeight = scale * pictureBox5.Image.Height;
float diffHeight = pictureBox5.Height - displayHeight;
diffHeight /= 2;
newY -= diffHeight;
newY /= scale;
}
else
{
// This means that we are limited by height,
// meaning the image fills up the entire control from top to bottom
float ratioHeight = (float)pictureBox5.Image.Height / pictureBox5.Height;
newY *= ratioHeight;
float scale = (float)pictureBox5.Height / pictureBox5.Image.Height;
float displayWidth = scale * pictureBox5.Image.Width;
float diffWidth = pictureBox5.Width - displayWidth;
diffWidth /= 2;
newX -= diffWidth;
newX /= scale;
}
return new Point((int)newX, (int)newY);
}
Adding a frame control at the determined position:
pictureBox5.Controls.Clear();
var c = new FrameControl();
c.Size = new Size(myrect.Width, myrect.Height);
c.Location=TranslateZoomMousePosition(newPoint(myrect.Location.X,myrect.Location.Y));
pictureBox5.Controls.Add(c);
But the determined frame/rectangle location is not correct.
What am I i doing wrong?
c# .net winforms picturebox system.drawing
add a comment |
I'm determining the rectangular area in an image and showing it to the user in a PictureBox.
Since the image can sometimes be very large, I'm using a PictureBox with its SizeMode
set to Zoom
.
I'm using the following code to translate the Rectangle (X, Y) coordinates:
public Point TranslateZoomMousePosition(Point coordinates)
{
// test to make sure our image is not null
if (pictureBox5.Image == null) return coordinates;
// Make sure our control width and height are not 0 and our
// image width and height are not 0
if (pictureBox5.Width == 0 || pictureBox5.Height == 0 || pictureBox5.Image.Width == 0 || pictureBox5.Image.Height == 0) return coordinates;
// This is the one that gets a little tricky. Essentially, need to check
// the aspect ratio of the image to the aspect ratio of the control
// to determine how it is being rendered
float imageAspect = (float)pictureBox5.Image.Width / pictureBox5.Image.Height;
float controlAspect = (float)pictureBox5.Width / pictureBox5.Height;
float newX = coordinates.X;
float newY = coordinates.Y;
if (imageAspect > controlAspect)
{
// This means that we are limited by width,
// meaning the image fills up the entire control from left to right
float ratioWidth = (float)pictureBox5.Image.Width / pictureBox5.Width;
newX *= ratioWidth;
float scale = (float)pictureBox5.Width / pictureBox5.Image.Width;
float displayHeight = scale * pictureBox5.Image.Height;
float diffHeight = pictureBox5.Height - displayHeight;
diffHeight /= 2;
newY -= diffHeight;
newY /= scale;
}
else
{
// This means that we are limited by height,
// meaning the image fills up the entire control from top to bottom
float ratioHeight = (float)pictureBox5.Image.Height / pictureBox5.Height;
newY *= ratioHeight;
float scale = (float)pictureBox5.Height / pictureBox5.Image.Height;
float displayWidth = scale * pictureBox5.Image.Width;
float diffWidth = pictureBox5.Width - displayWidth;
diffWidth /= 2;
newX -= diffWidth;
newX /= scale;
}
return new Point((int)newX, (int)newY);
}
Adding a frame control at the determined position:
pictureBox5.Controls.Clear();
var c = new FrameControl();
c.Size = new Size(myrect.Width, myrect.Height);
c.Location=TranslateZoomMousePosition(newPoint(myrect.Location.X,myrect.Location.Y));
pictureBox5.Controls.Add(c);
But the determined frame/rectangle location is not correct.
What am I i doing wrong?
c# .net winforms picturebox system.drawing
I'm determining the rectangular area in an image and showing it to the user in a PictureBox.
Since the image can sometimes be very large, I'm using a PictureBox with its SizeMode
set to Zoom
.
I'm using the following code to translate the Rectangle (X, Y) coordinates:
public Point TranslateZoomMousePosition(Point coordinates)
{
// test to make sure our image is not null
if (pictureBox5.Image == null) return coordinates;
// Make sure our control width and height are not 0 and our
// image width and height are not 0
if (pictureBox5.Width == 0 || pictureBox5.Height == 0 || pictureBox5.Image.Width == 0 || pictureBox5.Image.Height == 0) return coordinates;
// This is the one that gets a little tricky. Essentially, need to check
// the aspect ratio of the image to the aspect ratio of the control
// to determine how it is being rendered
float imageAspect = (float)pictureBox5.Image.Width / pictureBox5.Image.Height;
float controlAspect = (float)pictureBox5.Width / pictureBox5.Height;
float newX = coordinates.X;
float newY = coordinates.Y;
if (imageAspect > controlAspect)
{
// This means that we are limited by width,
// meaning the image fills up the entire control from left to right
float ratioWidth = (float)pictureBox5.Image.Width / pictureBox5.Width;
newX *= ratioWidth;
float scale = (float)pictureBox5.Width / pictureBox5.Image.Width;
float displayHeight = scale * pictureBox5.Image.Height;
float diffHeight = pictureBox5.Height - displayHeight;
diffHeight /= 2;
newY -= diffHeight;
newY /= scale;
}
else
{
// This means that we are limited by height,
// meaning the image fills up the entire control from top to bottom
float ratioHeight = (float)pictureBox5.Image.Height / pictureBox5.Height;
newY *= ratioHeight;
float scale = (float)pictureBox5.Height / pictureBox5.Image.Height;
float displayWidth = scale * pictureBox5.Image.Width;
float diffWidth = pictureBox5.Width - displayWidth;
diffWidth /= 2;
newX -= diffWidth;
newX /= scale;
}
return new Point((int)newX, (int)newY);
}
Adding a frame control at the determined position:
pictureBox5.Controls.Clear();
var c = new FrameControl();
c.Size = new Size(myrect.Width, myrect.Height);
c.Location=TranslateZoomMousePosition(newPoint(myrect.Location.X,myrect.Location.Y));
pictureBox5.Controls.Add(c);
But the determined frame/rectangle location is not correct.
What am I i doing wrong?
c# .net winforms picturebox system.drawing
c# .net winforms picturebox system.drawing
edited Dec 16 '18 at 16:41
Jimi
8,12241934
8,12241934
asked Dec 16 '18 at 7:38
technotechno
1,7431046101
1,7431046101
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
You can translate selected rectangle on the picture box to the rectangle on image this way:
public RectangleF GetRectangeOnImage(PictureBox p, Rectangle selectionRect)
{
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 selectionRect;
var cx = (float)p.Image.Width / (float)imageRect.Width;
var cy = (float)p.Image.Height / (float)imageRect.Height;
var r2 = Rectangle.Intersect(imageRect, selectionRect);
r2.Offset(-imageRect.X, -imageRect.Y);
return new RectangleF(r2.X * cx, r2.Y * cy, r2.Width * cx, r2.Height * cy);
}
Note: You can find ImageRectangleFromSizeMode
method source code here and use it as write such method as part of your application code.
Example - Crop Image of PictureBox having SizeMode = Zoom
As an example, the following code will crop the given rectangle of the picture box 1 and will set the result as image of picture box 2:
var selectedRectangle = new Rectangle(7, 30, 50, 40);
var result = GetRectangeOnImage(pictureBox1, selectedRectangle);
using (var bm = new Bitmap((int)result.Width, (int)result.Height))
{
using (var g = Graphics.FromImage(bm))
g.DrawImage(pictureBox1.Image, 0, 0, result, GraphicsUnit.Pixel);
pictureBox2.Image = (Image)bm.Clone();
}
Here is the input image:
And this is the result:
1
ImageRectangleFromSizeMode
wow, this is digging deep into the hidden vault!
– TaW
Dec 16 '18 at 9:53
@techno Changed a bit to supportStretch
mode as well.
– Reza Aghaei
Dec 16 '18 at 10:04
1
@TaW Added the link toImageRectangleFromSizeMode
source code so future readers can use it and write such method as part of their application code.
– Reza Aghaei
Dec 16 '18 at 10:16
1
Ha!ImageRectangleFromSizeMode
is something you usually see mentioned in stack traces (when something goes wrong). Well done!
– Jimi
Dec 16 '18 at 12:21
@RezaAghaei Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:33
|
show 1 more comment
Consider this an addition to Reza Aghaei answer.
A specialized class that provides some helper tools to determine the scaling factor of a selection and translates the selection coordinates to the scaled Bitmap
coordinates.
This version is for zoomed images only.
The ZoomFactor
class provides these methods:
PointF TranslateZoomPosition(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
:
returns the PointF
translated coordinates of a Point location inside a Container to the Point location inside a Bitmap, zoomed in the container.
RectangleF TranslateZoomSelection(RectangleF Selection, SizeF ContainerSize, SizeF ImageSize)
:
returns a RectangleF
representing a selection created inside a Container, translated to the Bitmap coordinates.
RectangleF TranslateSelectionToZoomedSel(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
:
returns a RectangleF
representing a pre-selected area of the original Bitmap translated to the zoomed selection Image inside a Container.
PointF GetImageScaledOrigin(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
:
returns the PointF
reference of the zoomed Image origin coordinates inside the Container.
SizeF GetImageScaledSize(SizeF ContainerSize, SizeF ImageSize)
:
returns the SizeF
reference of the Image when scaled inside the Container.
Sample usage, showing how to crop a Bitmap using a selection Rectangle created inside a Container control. The TranslateZoomSelection
method returns the Bitmap section corresponding to a selection area:
ZoomFactor ZoomHelper = new ZoomFactor()
Bitmap originalBitmap;
RectangleF currentSelection = [Current Selection Rectangle];
RectangleF bitmapRect = ZoomHelper.TranslateZoomSelection(currentSelection, [Container].Size, originalBitmap.Size);
using (Bitmap croppedBitmap = new Bitmap((int)bitmapRect.Width, (int)bitmapRect.Height, originalBitmap.PixelFormat))
using (Graphics g = Graphics.FromImage(croppedBitmap))
{
g.DrawImage(originalBitmap, new Rectangle(Point.Empty, Size.Round(bitmapRect.Size)),
bitmapRect, GraphicsUnit.Pixel);
[Container].Image = (Bitmap)croppedBitmap.Clone();
}
A Sample of the behaviour described above:
Note: In the example, the pre-selection of the image in Portrait inverts Width
and Height
The ZoomFactor
class:
public class ZoomFactor
{
public ZoomFactor() { }
public PointF TranslateZoomPosition(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
{
PointF imageOrigin = TranslateCoordinatesOrigin(Coordinates, ContainerSize, ImageSize);
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
return new PointF(imageOrigin.X / scaleFactor, imageOrigin.Y / scaleFactor);
}
public RectangleF TranslateZoomSelection(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
{
PointF selectionTrueOrigin = TranslateZoomPosition(SelectionRect.Location, ContainerSize, ImageSize);
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
SizeF selectionTrueSize = new SizeF(SelectionRect.Width / scaleFactor, SelectionRect.Height / scaleFactor);
return new RectangleF(selectionTrueOrigin, selectionTrueSize);
}
public RectangleF TranslateSelectionToZoomedSel(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
{
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
RectangleF zoomedSelectionRect = new
RectangleF(SelectionRect.X * scaleFactor, SelectionRect.Y * scaleFactor,
SelectionRect.Width * scaleFactor, SelectionRect.Height * scaleFactor);
PointF imageScaledOrigin = GetImageScaledOrigin(ContainerSize, ImageSize);
zoomedSelectionRect.Location = new PointF(zoomedSelectionRect.Location.X + imageScaledOrigin.X,
zoomedSelectionRect.Location.Y + imageScaledOrigin.Y);
return zoomedSelectionRect;
}
public PointF TranslateCoordinatesOrigin(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
{
PointF imageOrigin = GetImageScaledOrigin(ContainerSize, ImageSize);
return new PointF(Coordinates.X - imageOrigin.X, Coordinates.Y - imageOrigin.Y);
}
public PointF GetImageScaledOrigin(SizeF ContainerSize, SizeF ImageSize)
{
SizeF imageScaleSize = GetImageScaledSize(ContainerSize, ImageSize);
return new PointF((ContainerSize.Width - imageScaleSize.Width) / 2,
(ContainerSize.Height - imageScaleSize.Height) / 2);
}
public SizeF GetImageScaledSize(SizeF ContainerSize, SizeF ImageSize)
{
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
return new SizeF(ImageSize.Width * scaleFactor, ImageSize.Height * scaleFactor);
}
internal float GetScaleFactor(SizeF Scaled, SizeF Original)
{
return (Original.Width > Original.Height) ? (Scaled.Width / Original.Width)
: (Scaled.Height / Original.Height);
}
}
Thanks a lot :). I will take a look at both of your answers.
– techno
Dec 16 '18 at 12:58
Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:34
@techno See the edit. I've added a selection translator from coordinates relative to the original image to the scaled image (and a sample animation too :). I didn't have not much time, so it's not tested properly, but I've made some slections in different conditions and it looks OK. I'll revise it tomorrow.
– Jimi
Dec 16 '18 at 20:37
okay...Thanks... :)
– techno
Dec 18 '18 at 2:27
How do i detect if the control was resized or moved in the picturebox? Currently i use picturebox mouse mouse event. Is there a better way?
– techno
Dec 18 '18 at 2:27
|
show 18 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53800328%2ftranslate-rectangle-position-in-zoom-mode-picturebox%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can translate selected rectangle on the picture box to the rectangle on image this way:
public RectangleF GetRectangeOnImage(PictureBox p, Rectangle selectionRect)
{
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 selectionRect;
var cx = (float)p.Image.Width / (float)imageRect.Width;
var cy = (float)p.Image.Height / (float)imageRect.Height;
var r2 = Rectangle.Intersect(imageRect, selectionRect);
r2.Offset(-imageRect.X, -imageRect.Y);
return new RectangleF(r2.X * cx, r2.Y * cy, r2.Width * cx, r2.Height * cy);
}
Note: You can find ImageRectangleFromSizeMode
method source code here and use it as write such method as part of your application code.
Example - Crop Image of PictureBox having SizeMode = Zoom
As an example, the following code will crop the given rectangle of the picture box 1 and will set the result as image of picture box 2:
var selectedRectangle = new Rectangle(7, 30, 50, 40);
var result = GetRectangeOnImage(pictureBox1, selectedRectangle);
using (var bm = new Bitmap((int)result.Width, (int)result.Height))
{
using (var g = Graphics.FromImage(bm))
g.DrawImage(pictureBox1.Image, 0, 0, result, GraphicsUnit.Pixel);
pictureBox2.Image = (Image)bm.Clone();
}
Here is the input image:
And this is the result:
1
ImageRectangleFromSizeMode
wow, this is digging deep into the hidden vault!
– TaW
Dec 16 '18 at 9:53
@techno Changed a bit to supportStretch
mode as well.
– Reza Aghaei
Dec 16 '18 at 10:04
1
@TaW Added the link toImageRectangleFromSizeMode
source code so future readers can use it and write such method as part of their application code.
– Reza Aghaei
Dec 16 '18 at 10:16
1
Ha!ImageRectangleFromSizeMode
is something you usually see mentioned in stack traces (when something goes wrong). Well done!
– Jimi
Dec 16 '18 at 12:21
@RezaAghaei Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:33
|
show 1 more comment
You can translate selected rectangle on the picture box to the rectangle on image this way:
public RectangleF GetRectangeOnImage(PictureBox p, Rectangle selectionRect)
{
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 selectionRect;
var cx = (float)p.Image.Width / (float)imageRect.Width;
var cy = (float)p.Image.Height / (float)imageRect.Height;
var r2 = Rectangle.Intersect(imageRect, selectionRect);
r2.Offset(-imageRect.X, -imageRect.Y);
return new RectangleF(r2.X * cx, r2.Y * cy, r2.Width * cx, r2.Height * cy);
}
Note: You can find ImageRectangleFromSizeMode
method source code here and use it as write such method as part of your application code.
Example - Crop Image of PictureBox having SizeMode = Zoom
As an example, the following code will crop the given rectangle of the picture box 1 and will set the result as image of picture box 2:
var selectedRectangle = new Rectangle(7, 30, 50, 40);
var result = GetRectangeOnImage(pictureBox1, selectedRectangle);
using (var bm = new Bitmap((int)result.Width, (int)result.Height))
{
using (var g = Graphics.FromImage(bm))
g.DrawImage(pictureBox1.Image, 0, 0, result, GraphicsUnit.Pixel);
pictureBox2.Image = (Image)bm.Clone();
}
Here is the input image:
And this is the result:
1
ImageRectangleFromSizeMode
wow, this is digging deep into the hidden vault!
– TaW
Dec 16 '18 at 9:53
@techno Changed a bit to supportStretch
mode as well.
– Reza Aghaei
Dec 16 '18 at 10:04
1
@TaW Added the link toImageRectangleFromSizeMode
source code so future readers can use it and write such method as part of their application code.
– Reza Aghaei
Dec 16 '18 at 10:16
1
Ha!ImageRectangleFromSizeMode
is something you usually see mentioned in stack traces (when something goes wrong). Well done!
– Jimi
Dec 16 '18 at 12:21
@RezaAghaei Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:33
|
show 1 more comment
You can translate selected rectangle on the picture box to the rectangle on image this way:
public RectangleF GetRectangeOnImage(PictureBox p, Rectangle selectionRect)
{
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 selectionRect;
var cx = (float)p.Image.Width / (float)imageRect.Width;
var cy = (float)p.Image.Height / (float)imageRect.Height;
var r2 = Rectangle.Intersect(imageRect, selectionRect);
r2.Offset(-imageRect.X, -imageRect.Y);
return new RectangleF(r2.X * cx, r2.Y * cy, r2.Width * cx, r2.Height * cy);
}
Note: You can find ImageRectangleFromSizeMode
method source code here and use it as write such method as part of your application code.
Example - Crop Image of PictureBox having SizeMode = Zoom
As an example, the following code will crop the given rectangle of the picture box 1 and will set the result as image of picture box 2:
var selectedRectangle = new Rectangle(7, 30, 50, 40);
var result = GetRectangeOnImage(pictureBox1, selectedRectangle);
using (var bm = new Bitmap((int)result.Width, (int)result.Height))
{
using (var g = Graphics.FromImage(bm))
g.DrawImage(pictureBox1.Image, 0, 0, result, GraphicsUnit.Pixel);
pictureBox2.Image = (Image)bm.Clone();
}
Here is the input image:
And this is the result:
You can translate selected rectangle on the picture box to the rectangle on image this way:
public RectangleF GetRectangeOnImage(PictureBox p, Rectangle selectionRect)
{
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 selectionRect;
var cx = (float)p.Image.Width / (float)imageRect.Width;
var cy = (float)p.Image.Height / (float)imageRect.Height;
var r2 = Rectangle.Intersect(imageRect, selectionRect);
r2.Offset(-imageRect.X, -imageRect.Y);
return new RectangleF(r2.X * cx, r2.Y * cy, r2.Width * cx, r2.Height * cy);
}
Note: You can find ImageRectangleFromSizeMode
method source code here and use it as write such method as part of your application code.
Example - Crop Image of PictureBox having SizeMode = Zoom
As an example, the following code will crop the given rectangle of the picture box 1 and will set the result as image of picture box 2:
var selectedRectangle = new Rectangle(7, 30, 50, 40);
var result = GetRectangeOnImage(pictureBox1, selectedRectangle);
using (var bm = new Bitmap((int)result.Width, (int)result.Height))
{
using (var g = Graphics.FromImage(bm))
g.DrawImage(pictureBox1.Image, 0, 0, result, GraphicsUnit.Pixel);
pictureBox2.Image = (Image)bm.Clone();
}
Here is the input image:
And this is the result:
edited Dec 16 '18 at 10:12
answered Dec 16 '18 at 8:24
Reza AghaeiReza Aghaei
65.9k854162
65.9k854162
1
ImageRectangleFromSizeMode
wow, this is digging deep into the hidden vault!
– TaW
Dec 16 '18 at 9:53
@techno Changed a bit to supportStretch
mode as well.
– Reza Aghaei
Dec 16 '18 at 10:04
1
@TaW Added the link toImageRectangleFromSizeMode
source code so future readers can use it and write such method as part of their application code.
– Reza Aghaei
Dec 16 '18 at 10:16
1
Ha!ImageRectangleFromSizeMode
is something you usually see mentioned in stack traces (when something goes wrong). Well done!
– Jimi
Dec 16 '18 at 12:21
@RezaAghaei Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:33
|
show 1 more comment
1
ImageRectangleFromSizeMode
wow, this is digging deep into the hidden vault!
– TaW
Dec 16 '18 at 9:53
@techno Changed a bit to supportStretch
mode as well.
– Reza Aghaei
Dec 16 '18 at 10:04
1
@TaW Added the link toImageRectangleFromSizeMode
source code so future readers can use it and write such method as part of their application code.
– Reza Aghaei
Dec 16 '18 at 10:16
1
Ha!ImageRectangleFromSizeMode
is something you usually see mentioned in stack traces (when something goes wrong). Well done!
– Jimi
Dec 16 '18 at 12:21
@RezaAghaei Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:33
1
1
ImageRectangleFromSizeMode
wow, this is digging deep into the hidden vault!– TaW
Dec 16 '18 at 9:53
ImageRectangleFromSizeMode
wow, this is digging deep into the hidden vault!– TaW
Dec 16 '18 at 9:53
@techno Changed a bit to support
Stretch
mode as well.– Reza Aghaei
Dec 16 '18 at 10:04
@techno Changed a bit to support
Stretch
mode as well.– Reza Aghaei
Dec 16 '18 at 10:04
1
1
@TaW Added the link to
ImageRectangleFromSizeMode
source code so future readers can use it and write such method as part of their application code.– Reza Aghaei
Dec 16 '18 at 10:16
@TaW Added the link to
ImageRectangleFromSizeMode
source code so future readers can use it and write such method as part of their application code.– Reza Aghaei
Dec 16 '18 at 10:16
1
1
Ha!
ImageRectangleFromSizeMode
is something you usually see mentioned in stack traces (when something goes wrong). Well done!– Jimi
Dec 16 '18 at 12:21
Ha!
ImageRectangleFromSizeMode
is something you usually see mentioned in stack traces (when something goes wrong). Well done!– Jimi
Dec 16 '18 at 12:21
@RezaAghaei Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:33
@RezaAghaei Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:33
|
show 1 more comment
Consider this an addition to Reza Aghaei answer.
A specialized class that provides some helper tools to determine the scaling factor of a selection and translates the selection coordinates to the scaled Bitmap
coordinates.
This version is for zoomed images only.
The ZoomFactor
class provides these methods:
PointF TranslateZoomPosition(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
:
returns the PointF
translated coordinates of a Point location inside a Container to the Point location inside a Bitmap, zoomed in the container.
RectangleF TranslateZoomSelection(RectangleF Selection, SizeF ContainerSize, SizeF ImageSize)
:
returns a RectangleF
representing a selection created inside a Container, translated to the Bitmap coordinates.
RectangleF TranslateSelectionToZoomedSel(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
:
returns a RectangleF
representing a pre-selected area of the original Bitmap translated to the zoomed selection Image inside a Container.
PointF GetImageScaledOrigin(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
:
returns the PointF
reference of the zoomed Image origin coordinates inside the Container.
SizeF GetImageScaledSize(SizeF ContainerSize, SizeF ImageSize)
:
returns the SizeF
reference of the Image when scaled inside the Container.
Sample usage, showing how to crop a Bitmap using a selection Rectangle created inside a Container control. The TranslateZoomSelection
method returns the Bitmap section corresponding to a selection area:
ZoomFactor ZoomHelper = new ZoomFactor()
Bitmap originalBitmap;
RectangleF currentSelection = [Current Selection Rectangle];
RectangleF bitmapRect = ZoomHelper.TranslateZoomSelection(currentSelection, [Container].Size, originalBitmap.Size);
using (Bitmap croppedBitmap = new Bitmap((int)bitmapRect.Width, (int)bitmapRect.Height, originalBitmap.PixelFormat))
using (Graphics g = Graphics.FromImage(croppedBitmap))
{
g.DrawImage(originalBitmap, new Rectangle(Point.Empty, Size.Round(bitmapRect.Size)),
bitmapRect, GraphicsUnit.Pixel);
[Container].Image = (Bitmap)croppedBitmap.Clone();
}
A Sample of the behaviour described above:
Note: In the example, the pre-selection of the image in Portrait inverts Width
and Height
The ZoomFactor
class:
public class ZoomFactor
{
public ZoomFactor() { }
public PointF TranslateZoomPosition(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
{
PointF imageOrigin = TranslateCoordinatesOrigin(Coordinates, ContainerSize, ImageSize);
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
return new PointF(imageOrigin.X / scaleFactor, imageOrigin.Y / scaleFactor);
}
public RectangleF TranslateZoomSelection(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
{
PointF selectionTrueOrigin = TranslateZoomPosition(SelectionRect.Location, ContainerSize, ImageSize);
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
SizeF selectionTrueSize = new SizeF(SelectionRect.Width / scaleFactor, SelectionRect.Height / scaleFactor);
return new RectangleF(selectionTrueOrigin, selectionTrueSize);
}
public RectangleF TranslateSelectionToZoomedSel(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
{
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
RectangleF zoomedSelectionRect = new
RectangleF(SelectionRect.X * scaleFactor, SelectionRect.Y * scaleFactor,
SelectionRect.Width * scaleFactor, SelectionRect.Height * scaleFactor);
PointF imageScaledOrigin = GetImageScaledOrigin(ContainerSize, ImageSize);
zoomedSelectionRect.Location = new PointF(zoomedSelectionRect.Location.X + imageScaledOrigin.X,
zoomedSelectionRect.Location.Y + imageScaledOrigin.Y);
return zoomedSelectionRect;
}
public PointF TranslateCoordinatesOrigin(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
{
PointF imageOrigin = GetImageScaledOrigin(ContainerSize, ImageSize);
return new PointF(Coordinates.X - imageOrigin.X, Coordinates.Y - imageOrigin.Y);
}
public PointF GetImageScaledOrigin(SizeF ContainerSize, SizeF ImageSize)
{
SizeF imageScaleSize = GetImageScaledSize(ContainerSize, ImageSize);
return new PointF((ContainerSize.Width - imageScaleSize.Width) / 2,
(ContainerSize.Height - imageScaleSize.Height) / 2);
}
public SizeF GetImageScaledSize(SizeF ContainerSize, SizeF ImageSize)
{
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
return new SizeF(ImageSize.Width * scaleFactor, ImageSize.Height * scaleFactor);
}
internal float GetScaleFactor(SizeF Scaled, SizeF Original)
{
return (Original.Width > Original.Height) ? (Scaled.Width / Original.Width)
: (Scaled.Height / Original.Height);
}
}
Thanks a lot :). I will take a look at both of your answers.
– techno
Dec 16 '18 at 12:58
Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:34
@techno See the edit. I've added a selection translator from coordinates relative to the original image to the scaled image (and a sample animation too :). I didn't have not much time, so it's not tested properly, but I've made some slections in different conditions and it looks OK. I'll revise it tomorrow.
– Jimi
Dec 16 '18 at 20:37
okay...Thanks... :)
– techno
Dec 18 '18 at 2:27
How do i detect if the control was resized or moved in the picturebox? Currently i use picturebox mouse mouse event. Is there a better way?
– techno
Dec 18 '18 at 2:27
|
show 18 more comments
Consider this an addition to Reza Aghaei answer.
A specialized class that provides some helper tools to determine the scaling factor of a selection and translates the selection coordinates to the scaled Bitmap
coordinates.
This version is for zoomed images only.
The ZoomFactor
class provides these methods:
PointF TranslateZoomPosition(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
:
returns the PointF
translated coordinates of a Point location inside a Container to the Point location inside a Bitmap, zoomed in the container.
RectangleF TranslateZoomSelection(RectangleF Selection, SizeF ContainerSize, SizeF ImageSize)
:
returns a RectangleF
representing a selection created inside a Container, translated to the Bitmap coordinates.
RectangleF TranslateSelectionToZoomedSel(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
:
returns a RectangleF
representing a pre-selected area of the original Bitmap translated to the zoomed selection Image inside a Container.
PointF GetImageScaledOrigin(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
:
returns the PointF
reference of the zoomed Image origin coordinates inside the Container.
SizeF GetImageScaledSize(SizeF ContainerSize, SizeF ImageSize)
:
returns the SizeF
reference of the Image when scaled inside the Container.
Sample usage, showing how to crop a Bitmap using a selection Rectangle created inside a Container control. The TranslateZoomSelection
method returns the Bitmap section corresponding to a selection area:
ZoomFactor ZoomHelper = new ZoomFactor()
Bitmap originalBitmap;
RectangleF currentSelection = [Current Selection Rectangle];
RectangleF bitmapRect = ZoomHelper.TranslateZoomSelection(currentSelection, [Container].Size, originalBitmap.Size);
using (Bitmap croppedBitmap = new Bitmap((int)bitmapRect.Width, (int)bitmapRect.Height, originalBitmap.PixelFormat))
using (Graphics g = Graphics.FromImage(croppedBitmap))
{
g.DrawImage(originalBitmap, new Rectangle(Point.Empty, Size.Round(bitmapRect.Size)),
bitmapRect, GraphicsUnit.Pixel);
[Container].Image = (Bitmap)croppedBitmap.Clone();
}
A Sample of the behaviour described above:
Note: In the example, the pre-selection of the image in Portrait inverts Width
and Height
The ZoomFactor
class:
public class ZoomFactor
{
public ZoomFactor() { }
public PointF TranslateZoomPosition(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
{
PointF imageOrigin = TranslateCoordinatesOrigin(Coordinates, ContainerSize, ImageSize);
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
return new PointF(imageOrigin.X / scaleFactor, imageOrigin.Y / scaleFactor);
}
public RectangleF TranslateZoomSelection(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
{
PointF selectionTrueOrigin = TranslateZoomPosition(SelectionRect.Location, ContainerSize, ImageSize);
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
SizeF selectionTrueSize = new SizeF(SelectionRect.Width / scaleFactor, SelectionRect.Height / scaleFactor);
return new RectangleF(selectionTrueOrigin, selectionTrueSize);
}
public RectangleF TranslateSelectionToZoomedSel(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
{
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
RectangleF zoomedSelectionRect = new
RectangleF(SelectionRect.X * scaleFactor, SelectionRect.Y * scaleFactor,
SelectionRect.Width * scaleFactor, SelectionRect.Height * scaleFactor);
PointF imageScaledOrigin = GetImageScaledOrigin(ContainerSize, ImageSize);
zoomedSelectionRect.Location = new PointF(zoomedSelectionRect.Location.X + imageScaledOrigin.X,
zoomedSelectionRect.Location.Y + imageScaledOrigin.Y);
return zoomedSelectionRect;
}
public PointF TranslateCoordinatesOrigin(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
{
PointF imageOrigin = GetImageScaledOrigin(ContainerSize, ImageSize);
return new PointF(Coordinates.X - imageOrigin.X, Coordinates.Y - imageOrigin.Y);
}
public PointF GetImageScaledOrigin(SizeF ContainerSize, SizeF ImageSize)
{
SizeF imageScaleSize = GetImageScaledSize(ContainerSize, ImageSize);
return new PointF((ContainerSize.Width - imageScaleSize.Width) / 2,
(ContainerSize.Height - imageScaleSize.Height) / 2);
}
public SizeF GetImageScaledSize(SizeF ContainerSize, SizeF ImageSize)
{
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
return new SizeF(ImageSize.Width * scaleFactor, ImageSize.Height * scaleFactor);
}
internal float GetScaleFactor(SizeF Scaled, SizeF Original)
{
return (Original.Width > Original.Height) ? (Scaled.Width / Original.Width)
: (Scaled.Height / Original.Height);
}
}
Thanks a lot :). I will take a look at both of your answers.
– techno
Dec 16 '18 at 12:58
Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:34
@techno See the edit. I've added a selection translator from coordinates relative to the original image to the scaled image (and a sample animation too :). I didn't have not much time, so it's not tested properly, but I've made some slections in different conditions and it looks OK. I'll revise it tomorrow.
– Jimi
Dec 16 '18 at 20:37
okay...Thanks... :)
– techno
Dec 18 '18 at 2:27
How do i detect if the control was resized or moved in the picturebox? Currently i use picturebox mouse mouse event. Is there a better way?
– techno
Dec 18 '18 at 2:27
|
show 18 more comments
Consider this an addition to Reza Aghaei answer.
A specialized class that provides some helper tools to determine the scaling factor of a selection and translates the selection coordinates to the scaled Bitmap
coordinates.
This version is for zoomed images only.
The ZoomFactor
class provides these methods:
PointF TranslateZoomPosition(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
:
returns the PointF
translated coordinates of a Point location inside a Container to the Point location inside a Bitmap, zoomed in the container.
RectangleF TranslateZoomSelection(RectangleF Selection, SizeF ContainerSize, SizeF ImageSize)
:
returns a RectangleF
representing a selection created inside a Container, translated to the Bitmap coordinates.
RectangleF TranslateSelectionToZoomedSel(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
:
returns a RectangleF
representing a pre-selected area of the original Bitmap translated to the zoomed selection Image inside a Container.
PointF GetImageScaledOrigin(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
:
returns the PointF
reference of the zoomed Image origin coordinates inside the Container.
SizeF GetImageScaledSize(SizeF ContainerSize, SizeF ImageSize)
:
returns the SizeF
reference of the Image when scaled inside the Container.
Sample usage, showing how to crop a Bitmap using a selection Rectangle created inside a Container control. The TranslateZoomSelection
method returns the Bitmap section corresponding to a selection area:
ZoomFactor ZoomHelper = new ZoomFactor()
Bitmap originalBitmap;
RectangleF currentSelection = [Current Selection Rectangle];
RectangleF bitmapRect = ZoomHelper.TranslateZoomSelection(currentSelection, [Container].Size, originalBitmap.Size);
using (Bitmap croppedBitmap = new Bitmap((int)bitmapRect.Width, (int)bitmapRect.Height, originalBitmap.PixelFormat))
using (Graphics g = Graphics.FromImage(croppedBitmap))
{
g.DrawImage(originalBitmap, new Rectangle(Point.Empty, Size.Round(bitmapRect.Size)),
bitmapRect, GraphicsUnit.Pixel);
[Container].Image = (Bitmap)croppedBitmap.Clone();
}
A Sample of the behaviour described above:
Note: In the example, the pre-selection of the image in Portrait inverts Width
and Height
The ZoomFactor
class:
public class ZoomFactor
{
public ZoomFactor() { }
public PointF TranslateZoomPosition(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
{
PointF imageOrigin = TranslateCoordinatesOrigin(Coordinates, ContainerSize, ImageSize);
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
return new PointF(imageOrigin.X / scaleFactor, imageOrigin.Y / scaleFactor);
}
public RectangleF TranslateZoomSelection(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
{
PointF selectionTrueOrigin = TranslateZoomPosition(SelectionRect.Location, ContainerSize, ImageSize);
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
SizeF selectionTrueSize = new SizeF(SelectionRect.Width / scaleFactor, SelectionRect.Height / scaleFactor);
return new RectangleF(selectionTrueOrigin, selectionTrueSize);
}
public RectangleF TranslateSelectionToZoomedSel(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
{
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
RectangleF zoomedSelectionRect = new
RectangleF(SelectionRect.X * scaleFactor, SelectionRect.Y * scaleFactor,
SelectionRect.Width * scaleFactor, SelectionRect.Height * scaleFactor);
PointF imageScaledOrigin = GetImageScaledOrigin(ContainerSize, ImageSize);
zoomedSelectionRect.Location = new PointF(zoomedSelectionRect.Location.X + imageScaledOrigin.X,
zoomedSelectionRect.Location.Y + imageScaledOrigin.Y);
return zoomedSelectionRect;
}
public PointF TranslateCoordinatesOrigin(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
{
PointF imageOrigin = GetImageScaledOrigin(ContainerSize, ImageSize);
return new PointF(Coordinates.X - imageOrigin.X, Coordinates.Y - imageOrigin.Y);
}
public PointF GetImageScaledOrigin(SizeF ContainerSize, SizeF ImageSize)
{
SizeF imageScaleSize = GetImageScaledSize(ContainerSize, ImageSize);
return new PointF((ContainerSize.Width - imageScaleSize.Width) / 2,
(ContainerSize.Height - imageScaleSize.Height) / 2);
}
public SizeF GetImageScaledSize(SizeF ContainerSize, SizeF ImageSize)
{
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
return new SizeF(ImageSize.Width * scaleFactor, ImageSize.Height * scaleFactor);
}
internal float GetScaleFactor(SizeF Scaled, SizeF Original)
{
return (Original.Width > Original.Height) ? (Scaled.Width / Original.Width)
: (Scaled.Height / Original.Height);
}
}
Consider this an addition to Reza Aghaei answer.
A specialized class that provides some helper tools to determine the scaling factor of a selection and translates the selection coordinates to the scaled Bitmap
coordinates.
This version is for zoomed images only.
The ZoomFactor
class provides these methods:
PointF TranslateZoomPosition(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
:
returns the PointF
translated coordinates of a Point location inside a Container to the Point location inside a Bitmap, zoomed in the container.
RectangleF TranslateZoomSelection(RectangleF Selection, SizeF ContainerSize, SizeF ImageSize)
:
returns a RectangleF
representing a selection created inside a Container, translated to the Bitmap coordinates.
RectangleF TranslateSelectionToZoomedSel(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
:
returns a RectangleF
representing a pre-selected area of the original Bitmap translated to the zoomed selection Image inside a Container.
PointF GetImageScaledOrigin(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
:
returns the PointF
reference of the zoomed Image origin coordinates inside the Container.
SizeF GetImageScaledSize(SizeF ContainerSize, SizeF ImageSize)
:
returns the SizeF
reference of the Image when scaled inside the Container.
Sample usage, showing how to crop a Bitmap using a selection Rectangle created inside a Container control. The TranslateZoomSelection
method returns the Bitmap section corresponding to a selection area:
ZoomFactor ZoomHelper = new ZoomFactor()
Bitmap originalBitmap;
RectangleF currentSelection = [Current Selection Rectangle];
RectangleF bitmapRect = ZoomHelper.TranslateZoomSelection(currentSelection, [Container].Size, originalBitmap.Size);
using (Bitmap croppedBitmap = new Bitmap((int)bitmapRect.Width, (int)bitmapRect.Height, originalBitmap.PixelFormat))
using (Graphics g = Graphics.FromImage(croppedBitmap))
{
g.DrawImage(originalBitmap, new Rectangle(Point.Empty, Size.Round(bitmapRect.Size)),
bitmapRect, GraphicsUnit.Pixel);
[Container].Image = (Bitmap)croppedBitmap.Clone();
}
A Sample of the behaviour described above:
Note: In the example, the pre-selection of the image in Portrait inverts Width
and Height
The ZoomFactor
class:
public class ZoomFactor
{
public ZoomFactor() { }
public PointF TranslateZoomPosition(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
{
PointF imageOrigin = TranslateCoordinatesOrigin(Coordinates, ContainerSize, ImageSize);
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
return new PointF(imageOrigin.X / scaleFactor, imageOrigin.Y / scaleFactor);
}
public RectangleF TranslateZoomSelection(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
{
PointF selectionTrueOrigin = TranslateZoomPosition(SelectionRect.Location, ContainerSize, ImageSize);
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
SizeF selectionTrueSize = new SizeF(SelectionRect.Width / scaleFactor, SelectionRect.Height / scaleFactor);
return new RectangleF(selectionTrueOrigin, selectionTrueSize);
}
public RectangleF TranslateSelectionToZoomedSel(RectangleF SelectionRect, SizeF ContainerSize, SizeF ImageSize)
{
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
RectangleF zoomedSelectionRect = new
RectangleF(SelectionRect.X * scaleFactor, SelectionRect.Y * scaleFactor,
SelectionRect.Width * scaleFactor, SelectionRect.Height * scaleFactor);
PointF imageScaledOrigin = GetImageScaledOrigin(ContainerSize, ImageSize);
zoomedSelectionRect.Location = new PointF(zoomedSelectionRect.Location.X + imageScaledOrigin.X,
zoomedSelectionRect.Location.Y + imageScaledOrigin.Y);
return zoomedSelectionRect;
}
public PointF TranslateCoordinatesOrigin(PointF Coordinates, SizeF ContainerSize, SizeF ImageSize)
{
PointF imageOrigin = GetImageScaledOrigin(ContainerSize, ImageSize);
return new PointF(Coordinates.X - imageOrigin.X, Coordinates.Y - imageOrigin.Y);
}
public PointF GetImageScaledOrigin(SizeF ContainerSize, SizeF ImageSize)
{
SizeF imageScaleSize = GetImageScaledSize(ContainerSize, ImageSize);
return new PointF((ContainerSize.Width - imageScaleSize.Width) / 2,
(ContainerSize.Height - imageScaleSize.Height) / 2);
}
public SizeF GetImageScaledSize(SizeF ContainerSize, SizeF ImageSize)
{
float scaleFactor = GetScaleFactor(ContainerSize, ImageSize);
return new SizeF(ImageSize.Width * scaleFactor, ImageSize.Height * scaleFactor);
}
internal float GetScaleFactor(SizeF Scaled, SizeF Original)
{
return (Original.Width > Original.Height) ? (Scaled.Width / Original.Width)
: (Scaled.Height / Original.Height);
}
}
edited Jan 19 at 11:52
answered Dec 16 '18 at 12:19
JimiJimi
8,12241934
8,12241934
Thanks a lot :). I will take a look at both of your answers.
– techno
Dec 16 '18 at 12:58
Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:34
@techno See the edit. I've added a selection translator from coordinates relative to the original image to the scaled image (and a sample animation too :). I didn't have not much time, so it's not tested properly, but I've made some slections in different conditions and it looks OK. I'll revise it tomorrow.
– Jimi
Dec 16 '18 at 20:37
okay...Thanks... :)
– techno
Dec 18 '18 at 2:27
How do i detect if the control was resized or moved in the picturebox? Currently i use picturebox mouse mouse event. Is there a better way?
– techno
Dec 18 '18 at 2:27
|
show 18 more comments
Thanks a lot :). I will take a look at both of your answers.
– techno
Dec 16 '18 at 12:58
Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:34
@techno See the edit. I've added a selection translator from coordinates relative to the original image to the scaled image (and a sample animation too :). I didn't have not much time, so it's not tested properly, but I've made some slections in different conditions and it looks OK. I'll revise it tomorrow.
– Jimi
Dec 16 '18 at 20:37
okay...Thanks... :)
– techno
Dec 18 '18 at 2:27
How do i detect if the control was resized or moved in the picturebox? Currently i use picturebox mouse mouse event. Is there a better way?
– techno
Dec 18 '18 at 2:27
Thanks a lot :). I will take a look at both of your answers.
– techno
Dec 16 '18 at 12:58
Thanks a lot :). I will take a look at both of your answers.
– techno
Dec 16 '18 at 12:58
Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:34
Actually also need to do the reverse ie: i have the rectangle coordinates on the original image.When this image is displayed in the picturebox,i need to place the movable frame at the correct position by translating its known position in the original image.
– techno
Dec 16 '18 at 17:34
@techno See the edit. I've added a selection translator from coordinates relative to the original image to the scaled image (and a sample animation too :). I didn't have not much time, so it's not tested properly, but I've made some slections in different conditions and it looks OK. I'll revise it tomorrow.
– Jimi
Dec 16 '18 at 20:37
@techno See the edit. I've added a selection translator from coordinates relative to the original image to the scaled image (and a sample animation too :). I didn't have not much time, so it's not tested properly, but I've made some slections in different conditions and it looks OK. I'll revise it tomorrow.
– Jimi
Dec 16 '18 at 20:37
okay...Thanks... :)
– techno
Dec 18 '18 at 2:27
okay...Thanks... :)
– techno
Dec 18 '18 at 2:27
How do i detect if the control was resized or moved in the picturebox? Currently i use picturebox mouse mouse event. Is there a better way?
– techno
Dec 18 '18 at 2:27
How do i detect if the control was resized or moved in the picturebox? Currently i use picturebox mouse mouse event. Is there a better way?
– techno
Dec 18 '18 at 2:27
|
show 18 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53800328%2ftranslate-rectangle-position-in-zoom-mode-picturebox%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown