i have picturebox1 much larger than image i'd like to load. What i want to do is aligned this image to right side, and bottom of picturebox like on screenshot:
Edit: Working
private void FromCameraPictureBox_Paint(object sender, PaintEventArgs e)
{
if (loadimage == true)
{
var image = new Bitmap(#"image.jpg");
if (image != null)
{
var g = e.Graphics;
// -- Optional -- //
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// -- Optional -- //
g.DrawImage(image,
FromCameraPictureBox.Width - image.Width, // to right
FromCameraPictureBox.Height - image.Height, // to bottom
image.Width,
image.Height);
}
}
loadimage = false;
}
and now i want to fire paintevent from button:
void TestButtonClick(object sender, EventArgs e)
{
loadimage = true;
}
How to do this?
I'm confused why this code works nasty:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
g.DrawImage(pictureBox1.Image, pictureBox1.Width - pictureBox1.Image.Width, pictureBox1.Height - pictureBox1.Image.Height);
}
EDIT:
Ok now it works:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var image = Properties.Resources.SomeImage; //Import via Resource Manager
//Don't use pictureBox1.Image property because it will
//draw the image 2 times.
//Make sure the pictureBox1.Image property is null in Deisgn Mode
if (image != null)
{
var g = e.Graphics;
// -- Optional -- //
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// -- Optional -- //
g.DrawImage(image,
pictureBox1.Width - image.Width, // to right
pictureBox1.Height - image.Height, // to bottom
image.Width,
image.Height);
}
}
UPDATE:
Working :) But is there any possibility to use this code without
PaintEventsArgs ? I was trying to add to my button flag and in paint
(if (flag==true) then execute Your code, but it doesn't do anything -
no drawing on picturebox1
That's because Paint event fires once. We need to make it redraw. The default redraw method for controls is Refresh();
Here you go:
bool flag = false;
Bitmap image = null;
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (flag && image != null)
{
var g = e.Graphics;
// -- Optional -- //
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// -- Optional -- //
g.DrawImage(image,
pictureBox1.Width - image.Width,
pictureBox1.Height - image.Height,
image.Width,
image.Height);
}
}
private void button2_Click(object sender, EventArgs e)
{
image = new Bitmap("someimage.png");
flag = true;
pictureBox1.Refresh(); //Causes it repaint.
}
//If you resize the form (and anchor/dock the picturebox)
//or just resize the picturebox then you will need this:
private void pictureBox1_Resize(object sender, EventArgs e)
{
pictureBox1.Refresh();
}
You can use Bitmap + Graphics objects and copy the portion of your picture to a new bitmap (result) that will be assigned to the picturebox:
Size resultSize = new Size(100, 100);
Bitmap result = new Bitmap(resultSize.Width, resultSize.Height);
float left = yourbitmap.Width - resultSize.Width;
float top = yourbitmap.Height - resultSize.Height;
using (Graphics g = Graphics.FromImage(result))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(yourbitmap, left, top, resultSize.Width, resultSize.Height);
g.Save();
}
Related
First i'm drawing a rectangle on the pictureBox1 with the mouse
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
rect = new Rectangle(e.X, e.Y, 0, 0);
painting = true;
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
rect = new Rectangle(
rect.Left,
rect.Top,
Math.Min(e.X - rect.Left, pictureBox1.ClientRectangle.Width - rect.Left),
Math.Min(e.Y - rect.Top, pictureBox1.ClientRectangle.Height - rect.Top));
}
this.pictureBox1.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (painting == true)
{
using (Pen pen = new Pen(Color.Red, 2))
{
e.Graphics.DrawRectangle(pen, rect);
}
}
}
The variable rect is global Rectangle and painting is global bool.
Then I did inside the pictureBox1 mouseup event
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
pictureBox1.Image = SaveRectanglePart(pictureBox1.Image, rect);
}
And the method SaveRectanglePart
Bitmap bmptoreturn;
public Bitmap SaveRectanglePart(Image image, RectangleF sourceRect)
{
using (var bmp = new Bitmap((int)sourceRect.Width, (int)sourceRect.Height))
{
using (var graphics = Graphics.FromImage(bmp))
{
graphics.DrawImage(image, 0.0f, 0.0f, sourceRect, GraphicsUnit.Pixel);
}
bmptoreturn = bmp;
}
return bmptoreturn;
}
What i want to do is when i finish drawing the rectangle in the mouseup event to clear the pictureBox1 and replace the image in there with the rectangle image only.
But i'm getting exception parameter not valid in the mouseup event
pictureBox1.Image = SaveBitmapPart(pictureBox1.Image, rect);
And should i dispose somewhere the variable bmptoreturn ?
In the function SaveRectanglePart the variable bmp is Dispose of before the function returns as a result of the using statement. You need to remove the using statement and the code should work.
Bitmap bmptoreturn;
public Bitmap SaveRectanglePart(Image image, RectangleF sourceRect)
{
var bmp = new Bitmap((int)sourceRect.Width, (int)sourceRect.Height)
using (var graphics = Graphics.FromImage(bmp))
{
graphics.DrawImage(image, 0.0f, 0.0f, sourceRect, GraphicsUnit.Pixel);
}
bmptoreturn = bmp;
return bmptoreturn;
}
But we have the issue of what bmptoreturn and pictureBox1.Image were referencing before they were set. The old Image/Bitmap the reference will be lost in memory until garbage collection comes along to free their memory. To be a good programmer we need to Dispose of these Image/Bitmap when we are done with them.
Image tmp = bmptoreturn;
bmptoreturn = bmp;
if(tmp != null)
tmp.Dispose();
...
Image tmp = pictureBox1.Image;
pictureBox1.Image = SaveBitmapPart(pictureBox1.Image, rect);
if(tmp != null)
tmp.Dispose();
Also, I am not sure why you are using bmptoreturn but it is not needed in the code from what I can tell. You can simply return bmp if bmptoreturn is not being used elsewhere.
I'm trying to achieve an effect similar to this site. I am basically trying to implement a way to "compare" two similar images (with different colors, etc). I managed to do this in a not so brilliant way using two PictureBox controls (Winforms) one next to the other, and changing their Size and Location attributes on a MouseMove event.
The result works, but it flickers a lot and it's not really the best way to do it.
Is there a better way to do this, maybe with a WPF or by changing the code in any way? Here it is:
private void pbImg1_MouseMove(object sender, MouseEventArgs e)
{
pbImg2.Image = CropImage(array[1], new Rectangle(pbImg1.Size.Width, 0, totalSize.Width - pbImg1.Size.Width, 240));
pbImg1.Size = new Size(e.X, pbImg1.Height);
pbImg2.Location = new Point(pbImg1.Size.Width + pbImg1.Location.X, pbImg2.Location.Y);
pbImg2.Size = new Size(totalSize.Width - pbImg1.Size.Width, 240);
lpbImg1Size.Text = pbImg1.Size.ToString();
lpbImg2Size.Text = pbImg2.Size.ToString();
lpbImg1Location.Text = pbImg1.Location.ToString();
lpbImg2Location.Text = pbImg2.Location.ToString();
}
private void pbImg2_MouseMove(object sender, MouseEventArgs e)
{
pbImg1.Image = CropImage(array[0], new Rectangle(0, 0, totalSize.Width - pbImg2.Size.Width, 240));
pbImg1.Size = new Size(pbImg1.Width + e.X, 240);
lpbImg1Size.Text = pbImg1.Size.ToString();
lpbImg2Size.Text = pbImg2.Size.ToString();
lpbImg1Location.Text = pbImg1.Location.ToString();
lpbImg2Location.Text = pbImg2.Location.ToString();
}
public Bitmap CropImage(Bitmap source, Rectangle section)
{
// An empty bitmap which will hold the cropped image
//TRY CATCH
Bitmap bmp = new Bitmap(section.Width, section.Height);
Graphics g = Graphics.FromImage(bmp);
// Draw the given area (section) of the source image
// at location 0,0 on the empty bitmap (bmp)
g.DrawImage(source, 0, 0, section, GraphicsUnit.Pixel);
return bmp;
}
And here you can see the behavior of the program:
https://gfycat.com/VillainousReadyAmazonparrot
You need two images imageLeft, imageRight with the same size as the picturebox:
private int pos = 0; //x coordinate of mouse in picturebox
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if(pos == 0)
{
e.Graphics.DrawImage(Properties.Resources.imageRight, new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height));
}
else
{
e.Graphics.DrawImage(Properties.Resources.imageLeft, new Rectangle(0, 0, pos, pictureBox1.Height),
new Rectangle(0, 0, pos, pictureBox1.Height), GraphicsUnit.Pixel);
e.Graphics.DrawImage(Properties.Resources.imageRight, new Rectangle(pos, 0, pictureBox1.Width - pos, pictureBox1.Height),
new Rectangle(pos, 0, pictureBox1.Width - pos, pictureBox1.Height), GraphicsUnit.Pixel);
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
pos = e.X;
pictureBox1.Invalidate();
}
Am developing a paint application in C# , VS2010
The start-up interface is a blank pictureBox ,
I did a mouseDown and a mouseMove event Handler for brush tool paint
and it works fine
When i try to save the new picture (After painting on the blank pictureBox)
I enter the file , and it's only a blank picture.
The problem is that the code is not saving the effects.
why?
mouseDown event handler
private void mouseDown(object sender, MouseEventArgs e)
{
if (CurrentFunction == "DrawFree")
{
if (e.Button == MouseButtons.Left)
ReleaseFlag = true;
StartPoint = e.Location;
}
}
mouseMove event handler
private void mouseMove(object sender, MouseEventArgs e)
{
if (CurrentFunction == "DrawFree")
{
if (ReleaseFlag)
{
EndPoint = e.Location;
g = pictureBox1.CreateGraphics();
g.DrawLine(p, StartPoint, EndPoint);
}
StartPoint = EndPoint;
}
}
Save code
private void savePhotoToolStripMenuItem_Click(object sender, EventArgs e)
{
using (Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width,
pictureBox1.ClientSize.Height))
{
using (Graphics g = Graphics.FromImage(bmp))
{
Image yourImage = pictureBox1.Image;
Bitmap yourBitmap = new Bitmap(yourImage);
g.DrawImage(yourBitmap,
new Rectangle(0, 0, bmp.Width, bmp.Height),
new Rectangle(0, 0, yourImage.Width, yourImage.Height),
GraphicsUnit.Pixel);
}
bmp.Save(#"d:\yourfile.png", ImageFormat.Png);
}
}
Since you Bitmapped "yourBitmap" with yourImage, try replacing bmp.Save with yourBitmap.Save
yourBitmap.Image.Save(#"d:\yourfile.png", ImageFormat.Png);
I'm working on a winforms project that involves cropping an image. My goal is to do this by using a fixed-size draggable picturebox control, allowing the user to select the area they want to preserve.
My problem is when I crop the image; it "works", but the crop area offsets a little. Here's the result I get:
To clarify, I'm not talking about the zooming, that's per design. Notice the orange box is mostly focusing on the eye of the storm, but the cropped image is not.
This is my code for the crop operation:
private void tsbRecortar_Click(object sender, EventArgs e)
{
Rectangle recorte = new Rectangle(pbxSeleccion.Location.X, pbxSeleccion.Location.Y, pbxSeleccion.Width, pbxSeleccion.Height);
foto = recortarImagen(foto, recorte);
pbxImagen.Image = foto;
}
private Image recortarImagen(Image imagen, Rectangle recuadro)
{
try
{
Bitmap bitmap = new Bitmap(imagen);
Bitmap cropedBitmap = bitmap.Clone(recuadro, bitmap.PixelFormat);
return (Image)(cropedBitmap);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
return null;
}
}
pbxSeleccion is the draggable orange rectangle; its parent is pbxImage (I re-parent it on form's load).
As you can see, I'm using the coordinates of pbxSeleccion to define the starting point of the crop area, but is not working as expected... sometimes, I even get an "Out of Memory" exception.
I think this has to do with how the image loads in the parent picturebox, something about how the margin is handled "under the hood", but nothing I tried fixes it... just changes the magnitude of the offset.
Searching the web and SO has helped me a lot, but for this particular issue, I can't seem to find an answer... please, feel free to point out improvements to my code, I haven't been coding for long and I'm new to C# and .NET
Any help is highly appreciated. Cheers!
Suppose your original image is displayed in a PictureBox. You passed in the wrong location of the orange cropping window. Here is the corrected code for you:
private void tsbRecortar_Click(object sender, EventArgs e){
Point p = yourPictureBox.PointToClient(pbxSelection.PointToScreen(Point.Empty));
Rectangle recorte = new Rectangle(p.X, p.Y, pbxSeleccion.Width, pbxSeleccion.Height);
foto = recortarImagen(foto, recorte);
pbxImagen.Image = foto;
}
I use PointToClient and PointToScreen here because I think it's the best way to do. You can then change the container of your pictureBox safely without having to modify the code. If you use the code like the following, it's not dynamically enough when you want to place your pictureBox in another container:
Rectangle recorte = new Rectangle(pbxSeleccion.X + yourPictureBox.Left,
pbxSeleccion.Y + yourPictureBox.Top,
pbxSeleccion.Width, pbxSeleccion.Height);
NOTE: you can also use RectangleToClient and RectangleToScreen like this:
private void tsbRecortar_Click(object sender, EventArgs e){
Rectangle recorte = yourPictureBox.RectangleToClient(pbxSeleccion.RectangleToScreen(pbxSeleccion.ClientRectangle));
foto = recortarImagen(foto, recorte);
pbxImagen.Image = foto;
}
Try This Code for Cropping the Image in picturebox
public static Image Fit2PictureBox(this Image image, PictureBox picBox)
{
Bitmap bmp = null;
Graphics g;
// Scale:
double scaleY = (double)image.Width / picBox.Width;
double scaleX = (double)image.Height / picBox.Height;
double scale = scaleY < scaleX ? scaleX : scaleY;
// Create new bitmap:
bmp = new Bitmap(
(int)((double)image.Width / scale),
(int)((double)image.Height / scale));
// Set resolution of the new image:
bmp.SetResolution(
image.HorizontalResolution,
image.VerticalResolution);
// Create graphics:
g = Graphics.FromImage(bmp);
// Set interpolation mode:
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw the new image:
g.DrawImage(
image,
new Rectangle( // Ziel
0, 0,
bmp.Width, bmp.Height),
new Rectangle( // Quelle
0, 0,
image.Width, image.Height),
GraphicsUnit.Pixel);
// Release the resources of the graphics:
g.Dispose();
// Release the resources of the origin image:
image.Dispose();
return bmp;
}
public static Image Crop(this Image image, Rectangle selection)
{
Bitmap bmp = image as Bitmap;
// Check if it is a bitmap:
if (bmp == null)
throw new ArgumentException("Kein gültiges Bild (Bitmap)");
// Crop the image:
Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat);
// Release the resources:
image.Dispose();
return cropBmp;
}
Write The Following Code For Mouse Event on PictureBox
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_selecting = true;
_selection = new Rectangle(new Point(e.X, e.Y), new Size());
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && _selecting)
{
// Create cropped image:
try
{
Image img = pictureBox1.Image.Crop(_selection);
// Fit image to the picturebox:
pictureBox1.Image = img.Fit2PictureBox(pictureBox1);
}
catch { }
_selecting = false;
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
// Update the actual size of the selection:
if (_selecting)
{
_selection.Width = e.X - _selection.X;
_selection.Height = e.Y - _selection.Y;
// Redraw the picturebox:
pictureBox1.Refresh();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (_selecting)
{
// Draw a rectangle displaying the current selection
Pen pen = Pens.LightSkyBlue;
e.Graphics.DrawRectangle(pen, _selection);
}
}
Output Screen
Before Cropping
After Cropping
i have one picture showing of the human body and i want to use shapes to locate the injuries of the patient. all the shapes will shows off when the user click button. right now im testing with only one shape.
here is my code.
private void button7_Click_4(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
g.Clear(this.BackColor);
Image img = Image.FromFile("C:\\Users\\HDAdmin\\Pictures\\humanbody\\effect2.png");
g.DrawImage(img, 0, 0, img.Height, img.Width);
g.Dispose();
}
right now, the shape appear at the back of the image. so how i want to make the shape appear in front of the picture?
Couple of issues.
1) Painting should happen in a paint event. Do not use CreateGraphics since that will only be a temporary drawing.
2) Your DrawImage width and height arguments are reversed.
3) It doesn't look like you are painting the PictureBox control that you have on the form:
private Image img;
public Form1() {
InitializeComponent();
button1.Click += button1_Click;
pictureBox1.Paint += pictureBox1_Paint;
}
void button1_Click(object sender, EventArgs e) {
img = = Image.FromFile("C:\\Users\\HDAdmin\\Pictures\\humanbody\\effect2.png");
pictureBox1.Invalidate();
}
void pictureBox1_Paint(object sender, PaintEventArgs e) {
e.Graphics.Clear(pictureBox1.BackColor);
if (img != null) {
e.Graphics.DrawImage(img, 0, 0, img.Width, img.Height);
//Draw test shape:
e.Graphics.DrawRectangle(Pens.Red, new Rectangle(10, 10, 20, 60));
}
}
I think you should first get graphics of human image and then draw shape image on it. Some thing like that :
Image img = Image.FromFile("C:\\Users\\HDAdmin\\Pictures\\humanbody\\effect2.png");
Graphics g = Graphics.FromImage ( img );
g.DrawImage(ShapeImage, 0, 0, 30, 30); // you can set your required x,y,width,height