How can I select a part of an image in C#? - c#

Lets say I have a picturebox and I want to crop the image. I know how to crop by rectangles.
I want to be able to select a part of the image with mouse and crop it.
I think its called Free Form Selecting.

It really is simply tracking one corner of your selection rectangle (usually captured with the MouseDown event) and also the opposing corner for your selection rectangle (usually captured with the MouseUp event). These two coordinate pairs give you the region that the user selected.

Related

How do I select a Rectangle that's already been drawn?

I've been learning how to draw lines in winforms apps, and I'd like to be able to select something (rectangle, for example) that has already been drawn by left clicking it, and then be able to move it around to another location by dragging it with the mouse.
How can this be done? I don't see any methods for this so I think I will need to figure out if there is anything where I left-click on the form, and if there is, then somehow figure out the dimensions of it and redraw it appropriately. Is this correct? And how would I know where the reactangle starts, where it ends, how heigh it is, what color(s) it has, and what if it's overlapping another line, rectangle or another shape?
I've not been able to find much on the System.Drawing namespace for things like this, and what I have found so far is just basic "How to draw lines" type stuff.
Your drawing is a bitmap, not a vectorial image. Basically, it's just lots of pixels. Once your rectangle is drawn, it's just some pixels, but the rectangle itself (with coordinates and size) doesn't exist anymore.
What you can do is saving data for every shape (in a List for example). Then, when you click on your image to select something, you test every object in your list in reverse order until the mouse coordinates are within your shape. Then, if, for example, you want to delete the shape, you remove the shape from your list, then you clear your image and redraw every shape in your list.

Create an effect of magnifying glass for a picturebox

I would like to know how to create an effect of a magnifying glass for a picturebox.
Not zooming the picturebox but magnifying a part of the the image in the PictureBox control (circle or rectangle) and setting the size of the glass and the magnification factor.
It may only work within the picturebox control.
Language: C#
Thanks in advance !
Basically, you'd need two pictureboxes. One for the whole image and another for the magnified section. Also, you have to place the magnified picturebox according to user's mouse position.
You'll find a good article about it at http://www.codeproject.com/Articles/21097/PictureBox-Zoom. Just change the source to show the second picturebox in appropriate place (under user's cursor position).
You need 2 picturebox objects, one for picture itself and second for magnified area.
Next load picture into memory, you haven't specified source of the picture but in any case I recommend using streams.
Then create bitmap image in memory.
Using Image method set property of a picturebox.
To create source image for magnifying picturebox you need to clone selected part (calculating dimensions of a new picture area). Whole thing is not as trivial as you may expect as clone method accepts Rectangle objects as an area selector and generally works on rectangles rather than circles to copy selection. I also recommend to Dispose() unused bitmap objects as soon as possible.
Hope this helps.

How to realize with WinForms in C# something like an image with map areas in a homepage (at hoovering cover areas with semi transparent rectangle)?

I have a panel (here called parent), where I draw a calculated picture.
Some rectangular areas of this picture shall higlight by hoovering over.
It is the same behaviour like on a web page using , and , e. g.
the german map on the right upper side.
At hoovering the according rectangle shall be covered by a half transparent blue .
(And depending on keys like Alt, Ctrl and/or Shift in other colors, and clickable).
The first solution was a single instance of a transparent Panel - inherited from the Panel class.
In the hoovering event of the parent I moved and resized the single instance to the right place, changing the color.
This had some problems:
* moving and resizing (SetBounds()) fired MouseLeave event of the parent and a MouseEnter event of the single panel. The events had to be adapted accordingly to get it working correctly, I did it, but it is was very slow, due to finding the right map area from the list.
The second solution was to generate dynamically an instance of a transparent panel for each map area.
Each transparent panel had to set the e. g. Color.FromArgb(50, Color.Blue) at entering, and
remove it at leaving the panel.
But it seems to be even slower than before.
If the mouse hurries over several maps, they are all drawn like hoovered, and slowly get transparent again.
Does anybody know a good solution for this requirements:
at picture resize in parent panel, map etc. has to be changed as well
partly transparent highlight hoovered rectangle area.
detection of Ctrl/Shift/Alt as events for an area and change of the color.
detect click events there
Are there other controls I better use for this purpose?
Thanks for on practice based ideas.
PS: The world map with satellite pictures shows better what I want to do:
At hoovering the background is still visible more or less.
But in my case the parent image, its size and the maps are calculated at runtime
(after settings are completed by the user).
Solution
Description
I found now a solution, that reacts sufficiently fast to hoovering areas with the mouse.
The Main pictures is drawn in a PictureBox instance, in more detail its property Image is assigned.
The SizeMode property is set to Zoom, that automatically centers and resizes the image with keeping the aspect ratio of the assigned image.
I use a dynamically created Picturebox instance for each map area (childs), that is invisible, if the mouse does not hoover over it.
At hoovering over the map area the child shall appear - this is done in the mouse move event of the parent PictureBox,
where I iterate over the children, detecting whether the mouse position is in the bounds of a child.
The found child is set visible. Therefore the mouse enters this child control.
In the leave event of the child control I set it invisible again.
I experienced losses of mouse leave events for the child controls, if the mouse is moved too fast over all map areas.
I assume, if the mouse pointer already left the area before it has been set visible, the event is never raised.
The solution is, that all (other) child controls are set invisible, if in the mouse move event handler of the parent control does find no (a) child control.
Steps to implement
What to do, to implement my solution:
Use a designed parent PictureBox instance.
Assign the (dynamically) drawn picture to the Image property
Set SizeMode to Zoom
a list of Picturebox instances as form field
At assignment of a newly calculated image to the parent Picturebox instance:
remove all child controls, its event handler, its entry from the list, if they already exist.
create dynamically a PictureBox instance for each map area and add it to a list.
add it to the parent PictureBox instance as a child control.
set its Tag property points to a data object containing the origin map bounds and the object represented by the rectangular map area.
set the bounds to the map area scaled and centered according to the bounds of the parent Picturebox instance, that it suits the automatically zoomed image.
register a mouse click event
register a mouse leave event
set background color to e. g. semi transparent green
set Visible to false
In the parent Picturebox instance the mouse over event handler does:
finding the child Picturebox instance, where the mouse points at
if found it sets the found child visible
set all (other) child Picturebox invisible
In the parent Picturebox instance the resize event handler does:
scale/move all the map area Picturebox instances according to the bounds of the parent image and the bounds of the parent Picturebox instance.
The mouse leave event of each map area Picturebox instance set itself invisible (losses of events previously mentionned).
The mouse click event of each map area Picturebox instance makes whatever shall be done by clicking the map area.
Here playing a sine tone of the right chromatic pitch.
Pictures
The pictures below show the prototype with the map areas (not yet correctly aligned, some offset):
The first picture is for illustration of parent picture and all map areas.
The main picture (scale) and all map areas (dynamically created child Picturebox instances) are drawn in the first picture (by disabling the invisible action for map areas).
The second image is productive, where the mouse hoovers over tone G4.
In the second image the form has been resized - therefore the parent image is automatically been centered and resized.
The map areas were simply changed in their Bound property in the resize event handler of the parent PictureBox.
And the invisible action has been enabled for the map areas.
I checked the ImageMap:
It is a user control, that contains a static image, that was drawn before compile time.
At runtime the clickable areas are added – rectangle, polygon, ellipse are possible.
It uses a PictureBox, that is created as child of the ImageMap (that is inherited from UserControl).
It registers a Click, a Move and a Leave event to its event handlers.
In these event handlers it checks the current position against the list of paths in a GraphicsPath instance and returns an index (int).
The ImageMap keeps track of the last selected index (-1 = no object selected), sets the cursor accordingly (hand or default), sets or removes the tooltip.
But it has no hoover event, it does not change the area at hoovering, like I need it too.
Therefore I can need ImageMap it for proper detection of area,
but my picture is drawn at runtime!
And still I have to switch on and off the rectangles with its semi transparent layer.
I got the idea to use the property Visible to switch on and off the controls for the areas.
That it is easier to draw, I will set the background to the part of the parent image,
covered with the semi transparent color - this is a workaround, that is possible,
because the maps are relatively fixed to the parent picture.
If I have time, I will test this solution idea - it is a private project, therefore I can not work fulltime :-).

Drawing squares in WPF

I want to achieve the following with a WPF application (in a certain area/defined area):
When clicking and holding on the app, you can draw a square
You can do this as many times, but not overlap any squares
You can drag squares around the application
What do I need to achieve this, I assume a bunch of onclick/onmove's. Is there an easier way, such as using canvas? Any insight would be great.
You will have to use a canvas if you want the squares to appear where the user clicks and drags.
The mouse down event would define one corner and the mouse up the second. You'd have to constrain the movement of the cursor so that the x and y dimensions of the rectangle were the same.
On each mouse move event you'd have to check if the cursor were over one of the existing squares and prevent the square growing any further.
For the dragging of existing squares modify the mouse down event to check what's under the cursor. If it's the canvas start the square drawing mode, if it's a rectangle (square) then start the dragging mode. Again you'd need to use the mouse move event to check that the square doesn't intersect with any existing squares.
There's a code project article describing how to drag elements inside a Canvas: Dragging Elements in a Canvas
Speaking of ChrisF's mentioning of using a Canvas, I would suggest you use DragCanvas (found in the article)

Convert screen coordinates to picture coordinates

I have the following problem: A program displays a picture using a PictureBox. The picture contains two rectangles A and B that are drawn after the image is loaded.
The image inside the picture box is zoomed and the rectangles A and B are painted using the Graphics object of the loaded image. Is there a simple method to determinate if a user clicked the area inside these rectangles e.g. converting screen coordinates to picture coordinates.
Edit: No longer relevant, found another solution.
Edit 2: My solution was to use two picture boxes at the A and B location instead of modifying the image directly. It has some minor disadvantages specific to my solution, but I had to finish the project in time
This SO post discusses the zoom factor of a picture box and that you cannot determine it.
Therefore I think, without getting the zoom factor, you may not be able to calculate the position.

Categories

Resources