Hello i am in problem with drawing in picturebox. I am trying to draw over a picturebox. picturebox contains an image.I draw a sine wave using drawline method. when the wave reaches the end of the width of picturebox then i use
g.Clear(pictureBox1.BackColor);
this clears the wave over the picturebox.But the problem is it also clears the image of the picturebox.I want draw a wave over a image and then clears it when it reaches the picturebox.width and again starts from the initial position. please help!
Graphics g;
g = pictureBox1.CreateGraphics();
g.DrawLine(System.Drawing.Pens.Crimson, ti, old_gval1, ti + trackBar1.Value, gval1);
usb.SpecifiedDevice.SendData(OUTBuffer);
old_gval1 = gval1;
ti = ti + trackBar1.Value;
if (ti > pictureBox1.Width) {
ti = 0;
g.Clear(pictureBox1.BackColor);
g.DrawLine(System.Drawing.Pens.Gray, 0, ((pictureBox1.Height - 1) - (gnd_val) * ((pictureBox1.Height - 10) / 1023f)), pictureBox1.Width, ((pictureBox1.Height - 1) - (gnd_val) * ((pictureBox1.Height - 10) / 1023f)));
g.DrawLine(System.Drawing.Pens.Gray, pictureBox1.Width / 2, 0, pictureBox1.Width/ 2,pictureBox1.Height);
}
You can use a special feature of the PictureBox:
It has not only the Image everybody is using but also a BackgroundImage usually overlooked.
You can paint freely on the Image and still keep a BackgroundImage untouched.
Obviosly you need to paint on a transparent Bitmap.
Here is some code:
// load the background image:
this.pictureBox1.BackgroundImage = new Bitmap(yourImageFileName);
// prepare the image:
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
using (Graphics g = Graphics.FromImage(bmp) )
{
g.FillRectangle(Brushes.Transparent, new Rectangle(Point.Empty, bmp.Size) );
}
pictureBox1.Image = bmp;
Now paint stuff:
Random R = new Random();
private void button1_Click(object sender, EventArgs e)
{
Image bmp = pictureBox2.Image;
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawEllipse(Pens.Blue, R.Next(33), R.Next(33), R.Next(500), R.Next(500));
g.DrawEllipse(Pens.Red, R.Next(33), R.Next(33), R.Next(500), R.Next(500));
g.DrawEllipse(Pens.White, R.Next(33), R.Next(33), R.Next(500), R.Next(500));
}
pictureBox2.Image = bmp;
}
When your plotting has reached the right edge you would use a call to FillRectangle(Brushes.Transparent,.. to clear the foreground image and reset your x value.
Sounds like the cheapest solution to your problem.
You have two options here.
You could create your graphics from the image using Graphics.FromImage, then assign the image from that to the picture box.
Draw the image into your new Graphics object using Graphics.DrawImage.
It sounds like the latter might be a bit more appropriate for you, since you aren't actually altering the in-memory image. So every time you clear the Graphics instance, just draw in the Image.
Related
I'm trying to draw a rectangle over an image, the rectangle is drawn but the image disappears.
My code:
private void button12_Click(object sender, EventArgs e)
{
currentBitmap = (Bitmap)pictureBox1.Image;
Bitmap temp1 = new Bitmap(currentBitmap.Height, currentBitmap.Width);
Bitmap bmap = (Bitmap)temp1.Clone();
Graphics gr = Graphics.FromImage(bmap);
Pen pen = new Pen(Color.Red);
gr.DrawRectangle(pen, 120, 120, 100, 100);
currentBitmap = (Bitmap)bmap.Clone();
pictureBox1.Image = currentBitmap;
}
Put your drawing methods inside the pictureBox1 onPaint Method. Then you call that using
pictureBox1.Paint += picturebox1_OnPaint;
I fixed this.
It was an error on my code which I didnt realize, i was just taking the width and height of the picturebox instead of the image data.
I changed
Bitmap temp1 = new Bitmap(currentBitmap.Height, currentBitmap.Width);
To
Bitmap temp1 = new Bitmap(pictureBox1.Image);
This is likely due to the fact that your image is set in pictureBox1. Try making a new pictureBox to overlay the old one:
pictureBox1 = image itself
pictureBox2 = bitmap
Good luck!
In c# and Visual Studio Windows forms I have loaded an image into a picture box (pictureBox2) and then cropped it and show in another picture box (pictureBox3).
Now I want to save what is inside pictureBox3 as an image file.
How can I do this?
private void crop_bttn_Click(object sender, EventArgs e)
{
Image crop = GetCopyImage("grayScale.jpg");
pictureBox2.Image = crop;
Bitmap sourceBitmap = new Bitmap(pictureBox2.Image,
pictureBox2.Width, pictureBox2.Height);
Graphics g = pictureBox3.CreateGraphics();
g.DrawImage(sourceBitmap, new Rectangle(0, 0,
pictureBox3.Width, pictureBox3.Height), rectCropArea, GraphicsUnit.Pixel);
sourceBitmap.Dispose();
}
Never use control.CreateGraphics! Either draw into a Bitmap bmp using a Graphics g = Graphics.FromImage(bmp) or in the Paint event of a control, using the e.Graphics parameter..
Here is a cropping code that draws into a new Bitmap and that makes use of your controls etc but changes a few things:
It uses a Graphics object that is created from a new Bitmap
It make use of using clauses to make sure it won't leak
It takes the size of the pictureBox3.ClientSize so it won't include any borders..
private void crop_bttn_Click(object sender, EventArgs e)
{
Image crop = GetCopyImage("grayScale.jpg");
pictureBox2.Image = crop;
Bitmap targetBitmap = new Bitmap(pictureBox3.ClientSize.Width,
pictureBox3.ClientSize.Height);
using (Bitmap sourceBitmap = new Bitmap(pictureBox2.Image,
pictureBox2.ClientSize.Width, pictureBox2.ClientSize.Height))
{
using (Graphics g = Graphics.FromImage(targetBitmap))
{
g.DrawImage(sourceBitmap, new Rectangle(0, 0,
pictureBox3.ClientSize.Width, pictureBox3.ClientSize.Height),
rectCropArea, GraphicsUnit.Pixel);
}
}
if (pictureBox3.Image != null) pictureBox3.Image.Dispose();
pictureBox3.Image = targetBitmap;
targetBitmap.Save(somename, someFormat);
}
The alternative would be to..:
move all your code to the Paint event
replace the Graphics g = pictureBox3.CreateGraphics(); be Graphics g = e.Graphics;
insert these two lines to the click event:
Bitmap targetBitmap = new Bitmap(pictureBox3.ClientSize.Width,
pictureBox3.ClientSize.Height);
pictureBox3.DrawToBitmap(targetBitmap, pictureBox3.ClientRectangle);
The method PictureBox.CreateGraphics() should not be used unless you know what you are doing because it can cause some not-so-obvious problems. For example, in you scenario, the image in pictureBox3 will disappear when you minimize or resize the window.
A better way is to draw to a bitmap, which you also can save:
var croppedImage = new Bitmap(pictureBox3.Width, pictureBox3.Height);
var g = Graphics.FromImage(croppedImage);
g.DrawImage(crop, new Point(0, 0), rectCropArea, GraphicsUnit.Pixel);
g.Dispose();
//Now you can save the bitmap
croppedImage.Save(...);
pictureBox3.Image = croppedImage;
Btw, please use more reasonable variable names, especially for pictureBox1..3.
I'm doing some draws that are repetitive, and each of them gives lot of work.
What i need to do is rotate the drawing half-way its definition, something like this:
using (Graphics g = Graphics.FromImage(bmp))
{
//define area do pictureBox e preenche a branco
Brush brush = new SolidBrush(Color.White);
Rectangle area = new Rectangle(0, 0, 520, 520);
g.FillRectangle(brush, area);
//rotate
g.RotateTransform(some angle, some reference point)
//draw some more lines on the top of the rotated previous ones.
}
I tried using g.RotateTransform(90) as there is that function in Winforms, but it didn't change anything. Why??
Any tip?
Edit: if it helps, i only need to rotate fixed angles, 180ยบ
RotateTransform certainly does change the subsequent drawing.
Note that you usually need a TranslateTransform before to set the rotation point. But it 'it didn't change anything' is certainly wrong. Try again! And yes you can rotate (or scale or move) at any point and move/turn it back or completely reset the Graphics object.
And yes, learning about Matrix and MultiplyTransform is also very helpful..
But: You need to understand the Graphics object does not contain any graphic, a common misconception! It is the tool which does the drawing on a Bitmap, most often the surface of a Control. So the rotation will happen but only for the things you draw after:
private void panel1_Paint(object sender, PaintEventArgs e)
{
Rectangle rect = new Rectangle(25, 25, 25, 25);
e.Graphics.TranslateTransform(25, 25);
e.Graphics.FillRectangle(Brushes.Red, rect);
for (int i = 0; i < 15; i++)
{
rect.Inflate(2, 2);
e.Graphics.TranslateTransform(5, 2);
e.Graphics.RotateTransform(2.5f);
e.Graphics.DrawRectangle(Pens.Blue, rect);
}
}
Try this:
use these references:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
I made windows application and put on form1 picturebox then this is the code in form_load:
//Load an image in from a file
Bitmap pImage = new Bitmap(Environment.CurrentDirectory + #"\Image.bmp", true);
//Set our picture box to that image
pictureBox1.Image = (Bitmap)pImage.Clone();
//Store our old image so we can delete it
Image oldImage = pictureBox1.Image;
//Pass in our original image and return a new image rotated 35 degrees right
pictureBox1.Image = RotateImage(pImage, 270);
if (oldImage != null)
{
oldImage.Dispose();
}
Then make static function with parameters of image and rotation angle return the rotated image and call it from form_load as mentioned before :
if (image == null)
{
throw new ArgumentNullException("image");
}
else
{
//create a new empty bitmap to hold rotated image
Bitmap rotatedBmp = new Bitmap(image.Width, image.Height);
rotatedBmp.SetResolution(image.HorizontalResolution, image.VerticalResolution);
//make a graphics object from the empty bitmap
Graphics g = Graphics.FromImage(rotatedBmp);
//move rotation point to center of image
g.TranslateTransform((float)image.Width / 2, (float)image.Height / 2);
//rotate
g.RotateTransform(angle);
//move image back
g.TranslateTransform(-(float)image.Width / 2, -(float)image.Height / 2);
//draw passed in image onto graphics object
g.DrawImage(image, new PointF(0, 0));
return rotatedBmp;
}
You can also use directly the code in form_load by using ready RotateFlipType (Enumeration type) but this with fixed angles like 90,270,.... but the previous method you can use any integer values to rotate the image :
private void Form1_Load(object sender, EventArgs e)
{
//Load an image in from a file
Bitmap pImage = new Bitmap(Environment.CurrentDirectory + #"\Image.bmp", true);
pImage.RotateFlip(RotateFlipType.Rotate90FlipXY);
pictureBox1.Image = pImage;
}
I have a PictureBox where I display an image (Let's call it Image1). There's a second image (Image2) which needs to be revealed as the user hovers the Image1 with the mouse. I only need to reveal part of Image2 (a 10X10 pixel size box), not the whole image as the mouse moves.
Both images are BMP.
How can I accomplish this task? I would think using overlays?
I display the Image1 in the picturebox and then I load the Image2 in memory, now I just need to display the portions of the Image2 over Image1 as the mouse moves.
Thank you,
Here is an example:
public Form1()
{
InitializeComponent();
pictureBox1.Image = Bitmap.FromFile(your1stImage);
bmp = (Bitmap)Bitmap.FromFile(your2ndImage);
pb2.Parent = pictureBox1;
pb2.Size = new Size(10,10);
/* this is for fun only: It restricts the overlay to a circle:
GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(pb2.ClientRectangle);
pb2.Region = new Region(gp);
*/
}
Bitmap bmp;
PictureBox pb2 = new PictureBox();
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Rectangle rDest= pb2.ClientRectangle;
Point tLocation = new Point(e.Location.X - rDest.Width - 5,
e.Location.Y - rDest.Height - 5);
Rectangle rSrc= new Rectangle(tLocation, pb2.ClientSize);
using (Graphics G = pb2.CreateGraphics() )
{
G.DrawImage(bmp, rDest, rSrc, GraphicsUnit.Pixel);
}
pb2.Location = tLocation;
}
It uses offsets the overly to the top left of the Cursor adding a little for smooth movement..
I have a panel on which I'm drawing lines using:
Point PreviousPoint = new Point (0,0);
Point NewPoint = new Point (10,10);
Pen MyPen = new Pen(Color.Black, 2);
Graphics MyGraphics = panel1.CreateGraphics();
MyGraphics.DrawLine(MyPen, PreviousPoint, NewPoint);
This all works fine. I obviously change the points to draw more lines, but that doesn't matter for this question. I want to export that panel as a jpg file. I'm using this code:
Bitmap bmp = new Bitmap(panel1.Width, panel1.Height);
panel1.DrawToBitmap(bmp, new Rectangle(0, 0, panel1.Width, panel1.Height));
bmp.Save("C:\\panel.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
This outputs a blank jpg. The background of my panel is gray, and the background of the jpg is the same gray, so I know it's actually exporting the panel. Also, I added a button into the panel just to see if it would get saved, and it did. So for some reason the jpg isn't saving the lines being drawn.
So I made a workaround that solves the core problem. I made an array of the points I plotted to draw the lines, then I did this:
// make sure you actually drew something
if (MyLines.Length > 0)
{
// instantiate the stuff you need
Image img = new Bitmap(panel1.Width, panel1.Height);
Graphics g = Graphics.FromImage(img);
Pen pen = new Pen(Color.Black, 2);
// draw every line (from every even index to the one after it)
for (int i = 0; i < MyLines.Length; i++)
{
if (i % 2 == 0)
{
g.DrawLine(pen, MyLines[i], MyLines[i + 1]);
}
}
img.Save("C:\\panel.png", System.Drawing.Imaging.ImageFormat.Png);
}
}