Zoom Image in Picture Box - c#

I am creating an application, in which user will be able to Upload an image and then Zoom in and Out the image on a particular location (current mouse pointer).
Also user should be able to drag the image to see other parts of the image when the image is zoomed.
I have implemented some functionality to achieve it but i am scaling the complete image. I want to know that how i can scale a particular portion of image, or scale the complete image and then point to that location where my current mouse pointer is placed.
Code:
private void DisplayIsdDiagram(BO.IsdDiagram IsdDiagram)
{
DoubleBuffered = true;
zoomFac = 1;
translateX = 0;
translateY = 0;
transStartX = 0f;
transStartY = 0f;
picIsdDiagram.BorderStyle = BorderStyle.Fixed3D;
bmp = new Bitmap(Image.FromStream(new MemoryStream(IsdDiagram.Image.ToArray())));
if (bmp.Width > bmp.Height)
{
ratio = (float)picIsdDiagram.Width / (float)bmp.Width;
translateRatio = (float)bmp.Width / (float)picIsdDiagram.Width;
}
else
{
ratio = (float)picIsdDiagram.Height / (float)bmp.Height;
translateRatio = (float)bmp.Height / (float)picIsdDiagram.Height;
}
//picIsdDiagram.Image = bmp;
picIsdDiagram.Refresh();
picIsdDiagram.MouseWheel += new MouseEventHandler(picIsdDiagram_MouseWheel);
}
private void picIsdDiagram_MouseWheel(object sender, MouseEventArgs e)
{
IsZooming = true;
if (e.Delta < 0)
{
if (zoomFac > 1)
zoomFac = zoomFac - (float)0.1;
}
else
{
if (zoomFac <= 5)
zoomFac = zoomFac + (float)0.1;
}
picIsdDiagram.Refresh();
IsZooming = false;
}
private void picIsdDiagram_MouseDown(object sender, MouseEventArgs e)
{
IsZooming = false;
IsMouseDown = true;
transStartX = e.X;
transStartY = e.Y;
}
private void picIsdDiagram_MouseUp(object sender, MouseEventArgs e)
{
IsZooming = false;
IsMouseDown = false;
translateX = translateX + ((e.X - transStartX) * (translateRatio / zoomFac));
translateY = translateY + ((e.Y - transStartY) * (translateRatio / zoomFac));
picIsdDiagram.Refresh();
}
private void picIsdDiagram_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.ScaleTransform(ratio * zoomFac, ratio * zoomFac);
if (IsZooming == false && IsMouseDown == true)
g.TranslateTransform(translateX, translateY);
g.DrawImage(bmp, 0, 0);
}
I tried to get the current mouse position from MouseHover event and tried to Translate the picture when only Zoom is done, but that is not working.
Also the Picture Box has some other multiple Picture boxes inside it, to show some representation on the big image. While scaling the Big Image, small images (inside images) should not be scaled. Although there position needs to be recalculated to show them at their real places even after zooming on the Big image.
So in above i am facing two problems:
1) To Zoom an Image at any particular location (current mouse pointer)
by scrolling.
2) To regenerate the coordinates of the sub images while
zooming and translating.
Any help that can guide me in correct direction.
Also if by any other means, i could be able to achieve this functionality.
Application : Windows
Control : Picture Box (Please suggest if any other control can be used, if not possible with this)
Language : C#
Waiting for response!

PictureEdit control provided by DevExpress 13.2

Related

how to move and edit drawing object inside picturebox in C#?

I'm currently making simple programs to draw line on picturebox. Click for the first point then drag & release for the 2nd point.
Now I want to make that line can be edited rather than making new one. like when click & drag on the edge it will resized to the new drop point and when click & drag on the body it will move the entire item without changing the shape.
the current picturebox code is like this
public Form1()
{
InitializeComponent();
pictureBox1.BackgroundImage = Image.FromFile("C:/Users/RPC1940/Pictures/500px.jpg");
DrawArea = new Bitmap(pictureBox1.Size.Width, pictureBox1.Size.Height);
pictureBox1.Image = DrawArea;
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen pen = new Pen(Color.Black, 3);
g.DrawLine(pen,x1,y1,x2,y2);
pen.Dispose();
pictureBox1.Refresh();
this.DoubleBuffered = true;
}
and the current mouse click & drag to draw line is like this
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (drawRadio.Checked == true)
{
x1 = e.Location.X;
y1 = e.Location.Y;
x1Box.Text = x1.ToString();
y1Box.Text = y1.ToString();
}
else if (editRadio1.Checked == true)
{
x1 = e.Location.X;
y1 = e.Location.Y;
x1Box.Text = x1.ToString();
y1Box.Text = y1.ToString();
pictureBox1.Refresh();
}
else if(editRadio2.Checked == true)
{
x2 = e.Location.X;
y2 = e.Location.Y;
x2Box.Text = x2.ToString();
y2Box.Text = y2.ToString();
pictureBox1.Refresh();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if(drawRadio.Checked == true)
{
x2 = e.Location.X; //Second x coordinate (mouse release)
y2 = e.Location.Y; //Second y coordinate (mouse release)
x2Box.Text = x2.ToString();
y2Box.Text = y2.ToString();
}
}
Anyone know how to edit the lines that has drawn in the box by dragging the edge or body of it? Thank you very much
**Edit
added few radio box. drawRadio is default to draw the line, editRadio1 & editRadio2 for edit the coordinates of point 1 & 2. there's 1 more radio box to move the etire line shape but I dont know how is it works yet. if anyone know please tell me. Thanks

rectangle drawn in different point when canvas is zoomed

I have a canvas which has a zooming function. There are a lot of elements inside of it so, for selection I was going to use a selection box which I create dynamically when selection box is clicked. On clicking the button, I add the rectangle to the canvas and again, on clicking the button, I remove it.
I have the following xaml code:
<Viewbox x:Name="vbCanvas">
<Grid x:Name="theGrid"
MouseDown="Grid_MouseDown"
MouseUp="Grid_MouseUp"
MouseMove="Grid_MouseMove"
Background="Transparent">
<Canvas Name="canvasWaSNA" Margin="0,10,10,10" Height="720" Width="1280">
</Canvas>
</Grid>
</Viewbox>
mouse events of theGrid draws the rectangle on runtime on the canvas. The codes for those events are:
bool mouseDown = false;
Point mouseDownPos;
Point mouseUpPos;
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
mouseDown = true;
mouseDownPos = e.GetPosition(theGrid);
theGrid.CaptureMouse();
// Initial placement of the drag selection box.
Canvas.SetLeft(sBox, mouseDownPos.X);
Canvas.SetTop(sBox, mouseDownPos.Y);
sBox.Width = 0;
sBox.Height = 0;
// Make the drag selection box visible.
sBox.Visibility = Visibility.Visible;
}
}
private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
{
// Release the mouse capture and stop tracking it.
mouseDown = false;
mouseUpPos = e.GetPosition(theGrid);
theGrid.ReleaseMouseCapture();
// Show the drag selection box.
sBox.Visibility = Visibility.Visible;
MessageBox.Show(mouseDownPos.ToString() + " " + mouseUpPos.ToString());
}
private void Grid_MouseMove(object sender, MouseEventArgs e)
{
if (mouseDown)
{
// When the mouse is held down, reposition the drag selection box.
Point mousePos = e.GetPosition(theGrid);
if (mouseDownPos.X < mousePos.X)
{
Canvas.SetLeft(sBox, mouseDownPos.X);
sBox.Width = mousePos.X - mouseDownPos.X;
}
else
{
Canvas.SetLeft(sBox, mousePos.X);
sBox.Width = mouseDownPos.X - mousePos.X;
}
if (mouseDownPos.Y < mousePos.Y)
{
Canvas.SetTop(sBox, mouseDownPos.Y);
sBox.Height = mousePos.Y - mouseDownPos.Y;
}
else
{
Canvas.SetTop(sBox, mousePos.Y);
sBox.Height = mouseDownPos.Y - mousePos.Y;
}
}
}
To create a Rectangle at runtime, I have to click a button. The event of that button is as follows:
private void select_Click_1(object sender, RoutedEventArgs e)
{
if (!canvasWaSNA.Children.Contains(sBox))
{
sBox.Name = "selectionBox";
sBox.StrokeThickness = 1.5 / zoomfactor;
sBox.StrokeDashArray = new DoubleCollection { 1, 2 };
sBox.Visibility = System.Windows.Visibility.Collapsed;
sBox.Stroke = Brushes.Gray;
canvasWaSNA.Children.Add(sBox);
}
else
{
sBox.Visibility = System.Windows.Visibility.Collapsed;
canvasWaSNA.Children.Remove(sBox);
}
}
I am using the following code to zoom into the canvas:
double zoomfactor = 1.0;
void window_MouseWheel(object sender, MouseWheelEventArgs e)
{
Point p = e.MouseDevice.GetPosition(canvasWaSNA); //gets the location of the canvas at which the mouse is pointed
Matrix m = canvasWaSNA.RenderTransform.Value;
if (e.Delta > 0)
{ //the amount of wheel of mouse changed. e.Delta holds int value.. +ve for uproll and -ve for downroll
m.ScaleAtPrepend(1.1, 1.1, p.X, p.Y);
zoomfactor *= 1.1;
}
else
{
m.ScaleAtPrepend(1 / 1.1, 1 / 1.1, p.X, p.Y);
zoomfactor /= 1.1;
}
canvasWaSNA.RenderTransform = new MatrixTransform(m);
}
When my canvas is on original size, The rectangle is drawn perfectly but as I zoom in or zoom out, rectangle is drawn abnormally. It starts to draw from other points. What might be the problem? Please help
Well, I wasnot supposed to capture the mouse position with respect to theGrid, as I had to create the rectangle with respect to canvas. So, I have to get the position as e.GetPosition(canvasWaSNA) and the intended result was shown. It captured the mouse position on the canvas. Now, the rectangle is drawn perfectly even when zoomed in or zoomed out.
Also, I improved the StrokeThickness of the rectangle drawn by referencing it with the zoomfactor of the canvas.
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{mouseDown = true;
mouseDownPos = e.GetPosition(canvasWaSNA);
theGrid.CaptureMouse();
sBox.StrokeThickness = 1.5 / zoomfactor;
// Initial placement of the drag selection box.
Canvas.SetLeft(sBox, mouseDownPos.X);
Canvas.SetTop(sBox, mouseDownPos.Y);
sBox.Width = 0;
sBox.Height = 0;
// Make the drag selection box visible.
sBox.Visibility = Visibility.Visible;
}

winform move an image inside a picturebox

I've been trying to do this for a few hours now, but for the life of me I can't make it possible.
What I'm trying to do is simply move the image found within a picture box in a winform application. My image is roughly 1000x1000 pixels and my box is something arbitrary like 400x500, so, for example, when I click the mouse I'd want the image to move 50 to the left. But the image box should remain the same size.
For the life of me, however, I can't get this to work. What I have been able to do is the following:
if (kinectController.hands[0].fingertips.Count == 1)
{
pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage;
}
This function is for my kinect finger tracking app. So when the application finds a single finder point visiable on the screen, the image is centered. However, I would eventually like the image to move along with my finger movement, which will come once I work out the basic step of moving the image a few pixels to the side.
Any help with this would be appreciated.
I did a little bit of research and apparently moving an image within a PictureBox is no easy task, at the very least I couldn't find anything that would make this possible (not saying there isn't a way to do it though).
However, I came up with a bit of a "workaround", see if this fits your needs. To accomplish this:
Create a Panel control, and size it to however much of the image you
would like to display
Inside that panel place a PictureBox control with your image in it
and set the SizeMode property to AutoSize.
Now, put this code in your form
private bool Dragging;
private int xPos;
private int yPos;
private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { Dragging = false; }
private void pictureBox1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
Dragging = true;
xPos = e.X;
yPos = e.Y;
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e) {
Control c = sender as Control;
if (Dragging && c!= null) {
c.Top = e.Y + c.Top - yPos;
c.Left = e.X + c.Left - xPos;
}
}
Now whenever you click and drag on the PictureBox, it won't actually move the image within it, but the PictureBox control within the panel. Again, not exactly what you were looking for and I'm not sure how this would convert over to Kinect, but I hope this gets you on the right track.
Not enough reputation to comment but I wanted to add on Ben Black answer if someone ever need more control over the image moving around so you can't move the image past it's borders :
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Control c = sender as Control;
if (Dragging && c != null)
{
int maxX = pictureBox1.Size.Width * -1 + panel.Size.Width;
int maxY = pictureBox1.Size.Height * -1 + panel.Size.Height;
int newposLeft = e.X + c.Left - xPos;
int newposTop = e.Y + c.Top - yPos;
if (newposTop > 0)
{
newposTop = 0;
}
if (newposLeft > 0)
{
newposLeft = 0;
}
if (newposLeft < maxX)
{
newposLeft = maxX;
}
if (newposTop < maxY)
{
newposTop = maxY;
}
c.Top = newposTop;
c.Left = newposLeft;
}
}

Set autoscroll position on mouse move

I need to update scroll bar position when I click on image and move picturebox. It is always at the beggining, it only moving on the right side (horizontall) and down (vertical).
private void pictureBox1_MouseMove_1(object sender, MouseEventArgs e)
{
....
Point currentMousePos = e.Location;
int distanceX = currentMousePos.X - mouseX;
int distanceY = currentMousePos.Y - mouseY;
int newX = pictureBox1.Location.X + distanceX;
int newY = pictureBox1.Location.Y + distanceY;
if (newX + pictureBox1.Image.Width + 10 < pictureBox1.Image.Width && pictureBox1.Image.Width + newX + 10 > panel1.Width)
{
pictureBox1.Location = new Point(newX, pictureBox1.Location.Y);
}
if (newY + pictureBox1.Image.Height + 10 < pictureBox1.Image.Height && pictureBox1.Image.Height + newY + 10 > panel1.Height)
{
pictureBox1.Location = new Point(pictureBox1.Location.X, newY);
}
}
I think you need to change the AutoScrollPosition of the parent panel and not play around with the Location points of the PictureBox. After all, the scroll bars of the parent panel are already taking care of the position of the PictureBox.
Try something like this (by the way, my code only does this when a button is pressed, otherwise, I think it would be a weird user interface design):
private Point _StartPoint;
void pictureBox1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left)
_StartPoint = e.Location;
}
void pictureBox1_MouseMove(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
Point changePoint = new Point(e.Location.X - _StartPoint.X,
e.Location.Y - _StartPoint.Y);
panel1.AutoScrollPosition = new Point(-panel1.AutoScrollPosition.X - changePoint.X,
-panel1.AutoScrollPosition.Y - changePoint.Y);
}
}
LarsTech's code isn't 100% correct. 2 notes:
Note that if slider is moved, then the same point on screen changes it's coordinates relative to pictureBox1 (as pictureBox moved with moved slider). Therefore we want to use the screen coordinates (Control.MousePosition instead of e.Location).
Changing panel1.AutoScrollPosition causes the move of pictureBox relative to mouseCursor, so the pictureBox1.MouseMove event is fired again, even if cursor didn't move on the screen. Adding _StartPoint = Control.MousePosition prevents unwanted scrolling.

Track cusor location and add image from cusor location into PDF with iTextSharp

I'm looking for the most appropriate way to allow the user to import an image to a PDF and allow them to drag the picture around the PDF/winform and specify where the image is placed.
I'm thinking the best way to go about doing this is pulling the location from the cusor.
Something like:
Rectangle rect = new Rectangle(400, 772, 545, 792);
Instead of pre-defined coordinates, have the output be the selected cursor location of the user.
Any help would be very much appreciated.
Thank you in advance!
Users might have a hard time picking an image location just by pressing the mouse cursor on a form. Instead I recommend allowing them to drag a relatively sized rectangle around a grid. You'll have to translate coordinates appropriately, including fixing the Y value since iTextSharp starts at the bottom left instead of the top left, but that shouldn't be too hard.
Below is a full working C# 2010 WinForms app that allows you to drag a red rectangle around a black square. The comments in the code should pretty much explain everything. It has one big problem that need to be addressed, it stores the X/Y coordinates are screen-based and not form based, so if you drag once, move the entire form and drag again it will get "funky". This can be solved by calculating the x/y relative to the form instead which I'll leave up to you.
Hopefully this gets you down a path that works for you!
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
//Basic dimensions of our "border" and our "image". Assumes 72 dots per inch which isn't technically correct but gives us something to work with
private int BORDER_WIDTH = (int)11 * 72;
private int BORDER_HEIGHT = (int)8.5 * 72;
private int IMAGE_WIDTH = (int)2 * 72;
private int IMAGE_HEIGHT = (int)3 * 72;
private int IMAGE_OFFSET = 5;
//These will store the x/y when we press our mouse down so that we can calculate the drag later
private int offsetX;
private int offsetY;
//Our main "image" that we'll move around
PictureBox pb;
//The "border" to move the image around in
PictureBox border;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Resize the form and make it not user-resizable
this.Size = new Size(BORDER_WIDTH + 30, BORDER_HEIGHT + 50);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
//Create our "image"
pb = new PictureBox();
pb.Size = new Size(IMAGE_WIDTH, IMAGE_HEIGHT);
pb.Location = new Point(IMAGE_OFFSET, IMAGE_OFFSET);
pb.BackColor = Color.Red;
//Bind a handler to the mouse down event
pb.MouseDown += new MouseEventHandler(this.pbMouseDown);
this.Controls.Add(pb);
//Create our "border"
border = new PictureBox();
border.Size = new Size(BORDER_WIDTH, BORDER_HEIGHT);
border.Location = new Point(IMAGE_OFFSET, IMAGE_OFFSET);
border.BackColor = Color.Black;
this.Controls.Add(border);
}
private void pbMouseDown(object sender, MouseEventArgs e)
{
//Store the current x/y so that we can use them in calculations later
offsetX = e.X;
offsetY = e.Y;
//When the mouse is down we want to remove the original mouse down handler
pb.MouseDown -= new MouseEventHandler(this.pbMouseDown);
//Add to more handler looking for mouse up and mouse movement
pb.MouseUp += new MouseEventHandler(this.pbMouseUp);
pb.MouseMove += new MouseEventHandler(this.pbMouseMove);
}
private void pbMouseUp(object sender, MouseEventArgs e)
{
//When the mouse button is released, remove old handlers and add back the down event
pb.MouseMove -= new MouseEventHandler(this.pbMouseMove);
pb.MouseUp -= new MouseEventHandler(this.pbMouseUp);
pb.MouseDown += new MouseEventHandler(this.pbMouseDown);
//Pop up a message, this is where something with iTextSharp would be done
MessageBox.Show(String.Format("The top left of the image is at {0}x{1}", pb.Top - IMAGE_OFFSET, pb.Left - IMAGE_OFFSET));
}
private void pbMouseMove(object sender, MouseEventArgs e)
{
//Calculate where to draw the "image" at next
//First, calculate based on the current image's location, the offset that we stored ealier and the current mouse position
int newLeft = e.X + pb.Left - offsetX;
int newTop = e.Y + pb.Top - offsetY;
//Next, make sure that we haven't gone over one of the boundaries of the "border"
if (newLeft < border.Left) newLeft = border.Left;
if (newTop < border.Top) newTop = border.Top;
if (newLeft + pb.Width > border.Right) newLeft = border.Right - pb.Width;
if (newTop + pb.Height > border.Bottom) newTop = border.Bottom - pb.Height;
//Finally, assign the new value
pb.Left = newLeft;
pb.Top = newTop;
}
}
}

Categories