I want to move a string after scrolling Trackbar. Problem is, the previous string stays with the new one. So the resultant Image gets an unreadable string.
Image img;
readonly Image _originalImg;
Graphics imgScale;
public Form(){
InitializeComponent();
_originalImg = Image.FromFile("d:\\a.jpg");
img = _originalImg;
imgScale = Graphics.FromImage(img);
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
img = null;
pictureBox1.Image = null;
imgScale = null;
img = _originalImg;
x = trackBar1.Value;
imgScale = Graphics.FromImage(img);
imgScale.DrawString(str, font, color, new PointF(x, 0));
pictureBox1.Image = img;
}
Can anybody please edit my code so that _originalImg stays as new and I can see a clear string on the Image.
Thanks in advance.
This should work for you:
readonly Image _originalImg;
public Form(){
InitializeComponent();
_originalImg = Image.FromFile("d:\\a.jpg");
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
private void pictureBox1_paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(_originalImg, 0, 0);
e.Graphics.DrawString(str, font, color, new PointF( trackBar1.Value, 0));
}
Roughly what we are doing here, is drawing your image onto the picturebox, and also drawing the text onto the picturebox. This means the original image will never get modified.
We also only update the image if something changes (or the form gets told to repaint by windows etc). To ensure the image updates, we call pictureBox1.Invalidate(); when the trackbar value changes.
Edit:
As you don't want to save the image with the text else where, we can simplify this greatly:
public Form(){
InitializeComponent();
pictureBox1.Image = Image.FromFile("d:\\a.jpg");
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
private void pictureBox1_paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawString(str, font, color, new PointF( trackBar1.Value, 0));
}
This will draw the image zoomed onto the picturebox, and then over the top of that, we draw the text. This means the image is zoomed, but the text remains at whatever font size you specify.
Related
I'm making a little C# project which requires me to move an image that has already been drawn into the form. Here is the drawing algorithm:
public void DrawImagePoint(PaintEventArgs e)
{
// Create image.
newImage = A_Worm_Nightmare.Properties.Resources.Worm;
// Create Point for upper-left corner of image.
Point ulCorner = new Point(50, 50);
// Draw image to screen.
e.Graphics.DrawImage(newImage, ulCorner);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
DrawImagePoint(e);
}
Question: How do you flip an already drawn object in WinForms, since implementing this method in a timer is not possible? (timer_Tick does not support PaintEventArgs) The fliping is by Cursor.Position.X. Here is the algorithm for a normal `Picturebox":
private void timer1_Tick(object sender, EventArgs e)
{
bool Ok = true;
if (Cursor.Position.X <= 135 && Ok)
{
image.RotateFlip(RotateFlipType.RotateNoneFlipY);
Ok = false;
}
else if (Cursor.Position.X >= 135 && !Ok)
{
Ok = true;
}
}
Thank you in advance
I see what you are trying to do.
You must Call
this.Refresh();
on the timer event.
this will trigger the paint event.
You definitely need a timer. Just change the location in Timer's Tick and call Invalidate, it will make your form to repaint.
private Point location = Point.Empty;
private Image newImage;
private void OnTimerTick(object sender, EventArgs e)
{
location.Offset(1,1);
//Do flipping here
newImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
this.Invalidate();//Makes form to repaint
}
public void DrawImagePoint(PaintEventArgs e)
{
if(newImage == null)
{
newImage = A_Worm_Nightmare.Properties.Resources.Worm;
}
e.Graphics.DrawImage(newImage, location);
}
You can setup a timer with whatever frequency, and that should work.
also note that Resources.Image will create new Image every time you query it. So you should cache the image somewhere to avoid that overhead.
I want to create two picture boxes, overlapping.
The first Picturebox is used as the background, the picture of the screen.
using this method:
public void BckShow()
{
Rectangle rect = Screen.GetBounds(this);
gBackImg = Graphics.FromImage(bBackImg);
gBackImg.CopyFromScreen(0,0,0,0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
}
The second picturebox is above the first one, a transparent picture box that can be drawn using this mouse event:
public void Draw(bool draw, Point sp, Point ep)
{
if (draw)
{
gCanvas.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
pen = new Pen(new SolidBrush(ColorName), BrushSize);
if (toolPen.Checked)
{
gCanvas.DrawLine(pen, sp, ep);
}
else if (toolEreser.Checked)
{
Rectangle rect = new Rectangle(ep.X, ep.Y, BrushSize*5, BrushSize*5);
gCanvas.DrawEllipse(pen, rect);
gCanvas.FillEllipse(new SolidBrush(ColorName), rect);
}
bCanvas.MakeTransparent(Color.White);
pbxCanvas.Refresh();
dirty = true;
toolSave.Enabled = true;
}
}
private void pbxCanvas_MouseDown(object sender, MouseEventArgs e)
{
sp = e.Location;
if (e.Button == MouseButtons.Left)
{
ActivePaint = true;
}
}
private void pbxCanvas_MouseUp(object sender, MouseEventArgs e)
{
ActivePaint = false;
}
private void pbxCanvas_MouseMove(object sender, MouseEventArgs e)
{
ep = e.Location;
Draw(ActivePaint, sp, ep);
sp = ep;
}
but when i run the program, the second PictureBox does not draw anything when the mouse event was fired. how i can fix this?
I do this because I just want to save the image in the second picture box. Unlike PrintScreen but seemed to make notes on the screen and save the image apart from the screen image.
Is there another way to do this? like using controls other than picture box, or may directly use the screen as a background but still can save the image in the transparent PictureBox separately.
This is the example I want to achieve:
when drawing:
results stored images:
I hope you all will help me to fix this. sorry for poor explanation.
this the document outline window for more detail:
It's likely that your surface being overdrawn by refresh. You should be tracking what you want to draw, and then drawing it in the picture box's Paint event. That way, you get handed a Graphics object and every refresh, you're drawing.
That's assuming, of course, that you have a valid, and correct, Graphics object in the first place.
BTW: passing a form-scope variable to Draw is confusing, just use it.
Check your gCanvas initializer, if it is used from within Paint event (e.Graphics), then your changes are lost when you call the Refresh() method. Refresh() causes a new Paint event to be fired, creating a new Graphics object and therefore invalidating yours.
Create a new graphics object from your PictureBox's Image to persist your changes permanently.
private List<Point> points = new List<Point>();
private void pbxCanvas_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
ActivePaint = true;
}
}
private void pbxCanvas_MouseUp(object sender, MouseEventArgs e) {
ActivePaint = false;
points.Clear();
}
private void pbxCanvas_MouseMove(object sender, MouseEventArgs e) {
if (ActivePaint) {
points.Add(e.Location);
Refresh();
}
}
private void pbxCanvas_Paint(object sender, PaintEventArgs e) {
using (var graphics = Graphics.FromImage(pbxCanvas.Image)) {
for (int i = 0; i < points.Count - 1; i++) {
graphics.DrawLine(Pens.Black, points[i], points[i + 1]);
}
}
}
I have loaded an image in my panel.I want to erase the parts of that image by using the mouse(dragging on the panel).Here is my code to load my image:
private void drawP_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(myImage, new Point(0, 0));
}
How can I do it?
Thanks in advance.
Updated:
sorry not to say earlier,I have set another image(image2) as background of the panel and I want it to be seen after erasing myImage(image loaded with the code above).
Hi I'm going to assume that you want this feature to work like the eraser on paint.
there are 3 events you are going to need
1.mousedown - to call the first erase and open up the mousemove event method.
2.mouseup - to stop the mousemove event method
3.mousemove - just to call the erase method
Code: //part pseudo as im not in visual studio right now :(
//global vars
bool enable = false;
void erase(Point mousepoint)
{
Point f = (mousepoint.X - yourpanel.left?, mousepoint.Y - yourpanel.top?);
//gets mouse position on accual picture;
yourImageGraphics.fillreactangle( f.X - 10, f.Y+10, 20,20 ,Color.White)
// int X , int Y, width , height, color
}
void mousedown(?)
{
enable=true;
erase(Cursor.Position //but you get this from e?);
}
void mouseup(?);
{
enable=false;
}
void mousemove(?)
{
if (enable)
erase(e.Position?);
}
Also it looks like you are going to have to make a graphics object for your panel :(
I hope this helps because question was a bit vague.
Here I created simple example. Of course it can be done better, but I just wondering how to do it... so sharing my results.
public partial class mainForm : Form
{
private Bitmap image;
private Rectangle imgRect;
public mainForm()
{
InitializeComponent();
BackColor = Color.Chartreuse;
image = new Bitmap(#"C:\image.jpg");
imgRect = new Rectangle(0,0,image.Width, image.Height);
}
private void main_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(image, 0, 0);
}
private void main_MouseMove(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left && e.X < image.Width && e.Y < image.Height)
{
image.SetPixel(e.X, e.Y, Color.Magenta);//change pixel color;
image.MakeTransparent(Color.Magenta);//Make image transparent
Invalidate(imgRect);
}
}
}
...and lets test
Ha! scared that I deleted his eye :)
A TextureBrush on a pen can be used for erasing.
Working example (image1 and image2 are the same size images):
Bitmap bmp1;
TextureBrush tb;
Point _LastPoint;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
bmp1 = new Bitmap(#"c:\image1.png");
tb = new TextureBrush(new Bitmap(#"c:\image2.png"));
}
private void Form1_MouseMove(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
if (!_LastPoint.IsEmpty) {
using (Graphics g = Graphics.FromImage(bmp1))
using (Pen p = new Pen(tb, 15)) {
p.StartCap = LineCap.Round;
p.EndCap = LineCap.Round;
g.DrawLine(p, _LastPoint, e.Location);
}
}
_LastPoint = e.Location;
this.Invalidate();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e) {
_LastPoint = Point.Empty;
}
private void Form1_Paint(object sender, PaintEventArgs e) {
e.Graphics.DrawImage(bmp1, new Point(0, 0));
}
First I load an image in a picturebox. Then I measure the areas in it and create a new picture. Now I want to load the image in a panel and draw a line by mouse.
I added to my form:
private Image imag;
I also added to my project:
private void drawP_Paint(object sender, PaintEventArgs e)
{
Graphics g = drawP.CreateGraphics();
g.DrawImage(imag, new Point(0,0));
}
I set the image in a function:
imag = (Image)bm;
// or
imag = picturebox1.Image; // the made picture
drawP.Invalidate();
But nothing appears when running the project.
You should place your code in panel Paint event.
private void panel1_Paint(object sender, PaintEventArgs e)
{
Image imag = Image.FromFile(filename);
e.Graphics.DrawImage(imag, new Point(0,0));
}
This makes you sure that everytime panel is redrawn (after beeing invalidated for any reason) your image is visible.
Try changing it to this:
private void drawP_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(imag, new Point(0,0));
}
Also, from your comments, it sounds like you may not have the event wired up. Example:
public Form1()
{
InitializeComponent();
drawP.Paint += drawP_Paint;
}
To draw a line on that image:
private void button1_Click(object sender, EventArgs e) {
using (Graphics g = Graphics.FromImage(imag)) {
g.DrawLine(Pens.Red, new Point(0, 0), new Point(32, 32));
}
drawP.Invalidate();
}
I have made a program that allows users to draw lines onto a picturebox image but now need to save these lines to be opened at a later date. This is my current code for drawing the lines:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
}
int Drawshape;
private Point p1, p2;
List<Point> p1List = new List<Point>();
List<Point> p2List = new List<Point>();
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Drawshape = 5;
}
private void button2_Click(object sender, EventArgs e)
{
Drawshape = 2;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (Drawshape == 5)
{
if (p1.X == 0)
{
p1.X = e.X;
p1.Y = e.Y;
}
else
{
p2.X = e.X;
p2.Y = e.Y;
p1List.Add(p1);
p2List.Add(p2);
pictureBox1.Invalidate();
p1.X = 0;
}
}
}
private void pictureBox1_ParentChanged(object sender, EventArgs e)
{
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics G = Graphics.FromImage(pictureBox1.Image);
if (Drawshape == 5)
{
using (var p = new Pen(Color.Blue, 4))
{
for (int x = 0; x < p1List.Count; x++)
{
G.DrawLine(p, p1List[x], p2List[x]);
}
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
pictureBox1.Invalidate();
}
private void Save_Click(object sender, EventArgs e)
{
}
}
}
I don't know how to save these lines and also open them again at a later time when the user wants to. I have put in open and save filedialogs but not sure how to make them do the job i want them to do. Please Help.
Thanks
If you want to save the image that is displayed in the picture box, complete with any lines that may have been drawn on top of it during run-time, you can use the Control.DrawToBitmap method.
I can't tell for sure if you're also asking how to use a SaveFileDialog to determine where the user wants to save the file or if you've already got that part figured out, but it's very simple.
Here's an example of a complete solution. First, the user is prompted by a save dialog (entitled "Save Image" and filtering to bitmap images (*.bmp) by default). If they click OK, the image displayed in the picture box is drawn to a temporary bitmap, and that temporary bitmap is saved to the location they specified. If they click Cancel, the file is not saved and the method simply exits.
private void Save_Click(object sender, EventArgs e)
{
//Show a save dialog to allow the user to specify where to save the image file
using (SaveFileDialog dlgSave = new SaveFileDialog())
{
dlgSave.Title = "Save Image";
dlgSave.Filter = "Bitmap Images (*.bmp)|*.bmp|All Files (*.*)|*.*";
if (dlgSave.ShowDialog(this) == DialogResult.OK)
{
//If user clicked OK, then save the image into the specified file
using (Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height))
{
picturebox1.DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
bmp.Save(dlgSave.FileName);
}
}
}
}
Have a look at
PictureBox.Image Property
and
Image.Save Method (String, ImageFormat)
and
Image.FromFile Method (String, Boolean)
It's not clear what you want... do you want to save the resulting image, or the list of points ?
If you want to save the image, just use pictureBox1.Image.Save(fileName).
If you want to save the list of points, you could use serialization (it should work with either binary or XML serialization)