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)
Related
I am working on a MS paint like program that is programmed entirely in c#. It's very basic, but I have stumbled upon a problem. So I saw another SO post regarding MS paint mock ups. It was about how to save the end result as a .bmp file. I tried using the solutions and answers provided and it worked.
The file saved. However when it saved, it only saved the blank panel ( im making a forms app) . I have only seen one SO post that deals with this issue but I couldn't incorporate to allow the user to interact. The following is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Paint
{
public partial class Form1 : Form
{
Graphics g;
Pen p = new Pen(Color.Black, 1);
Point sp = new Point(0, 0);
Point ep = new Point(0, 0);
int k = 0;
public Form1()
{
InitializeComponent();
}
private void pictureBox2_Click(object sender, EventArgs e)
{
p.Color = red.BackColor;
default1.BackColor = red.BackColor;
}
private void blue_Click(object sender, EventArgs e)
{
p.Color = blue.BackColor;
default1.BackColor = blue.BackColor;
}
private void green_Click(object sender, EventArgs e)
{
p.Color = green.BackColor;
default1.BackColor = green.BackColor;
}
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
sp = e.Location;
if (e.Button == MouseButtons.Left)
k = 1;
}
private void panel2_MouseUp(object sender, MouseEventArgs e)
{
k = 0;
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (k == 1)
{
ep = e.Location;
g = panel2.CreateGraphics();
g.DrawLine(p, sp, ep);
}
sp = ep;
}
private void panel2_MouseLeave(object sender, EventArgs e)
{
k = 0; }
private void panel2_Paint(object sender, PaintEventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
SaveFileDialog dialog = new SaveFileDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
int width = Convert.ToInt32(panel2.Width);
int height = Convert.ToInt32(panel2.Height);
Bitmap bmp = new Bitmap(width, height);
panel2.DrawToBitmap(bmp, new Rectangle(0, 0, width, height));
bmp.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Bmp);
}
}
}
}
So my question is... How do I Succesfully save a .bmp image in my c# forms app , as in how do i not make it save blank. Thanks in advance :)
edit
So I have tried the first answer and also im trying the ideas suggested by the individual in the comments and some how, instead of just saving a blank canvas. the application literally just saves a black image. Here is the code I ended up with. Where did I go wrong?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Paint
{
public partial class Form1 : Form
{
Graphics g;
Graphics h;
Pen p = new Pen(Color.Black, 1);
Point sp = new Point(0, 0);
Point ep = new Point(0, 0);
int k = 0;
Bitmap bmp =null;
public Form1()
{
InitializeComponent();
}
private void pictureBox2_Click(object sender, EventArgs e)
{
p.Color = red.BackColor;
default1.BackColor = red.BackColor;
}
private void blue_Click(object sender, EventArgs e)
{
p.Color = blue.BackColor;
default1.BackColor = blue.BackColor;
}
private void green_Click(object sender, EventArgs e)
{
p.Color = green.BackColor;
default1.BackColor = green.BackColor;
}
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
sp = e.Location;
if (e.Button == MouseButtons.Left)
k = 1;
}
private void panel2_MouseUp(object sender, MouseEventArgs e)
{
k = 0;
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (k == 1)
{
ep = e.Location;
int width = Convert.ToInt32(panel2.Width);
int height = Convert.ToInt32(panel2.Height);
Bitmap bmp = new Bitmap(width, height);
g = Graphics.FromImage(bmp);
g.DrawLine(p, sp, ep);
h = panel2.CreateGraphics();
h.DrawLine(p, sp, ep);
}
sp = ep;
}
private void panel2_MouseLeave(object sender, EventArgs e)
{
k = 0; }
private void panel2_Paint(object sender, PaintEventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
SaveFileDialog dialog = new SaveFileDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
/*
Bitmap bmp = Bitmap.FromHbitmap(panel2.CreateGraphics().GetHdc());
panel2.DrawToBitmap(bmp, new Rectangle(0, 0, width, height));*/
int width = panel2.Width;
int height = Convert.ToInt32(panel2.Height);
if (bmp == null)
bmp = new Bitmap(width, height);
bmp.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
}
Here is a revised version, pretty much what I told you in the comments..:
public partial class Form2 : Form
{
Graphics g;
Graphics h;
Pen p = new Pen(Color.Black, 1);
Point sp = new Point(0, 0);
Point ep = new Point(0, 0);
int k = 0;
Bitmap bmp =null;
public Form2()
{
InitializeComponent();
bmp = new Bitmap(panel2.ClientSize.Width, panel2.ClientSize.Height);
g = Graphics.FromImage(bmp);
g.Clear(panel2.BackColor);
}
private void pictureBox2_Click(object sender, EventArgs e)
{
p.Color = red.BackColor;
default1.BackColor = red.BackColor;
}
private void color_Click(object sender, EventArgs e)
{
Control ctl = sender as Control;
p.Color = ctl.BackColor;
default1.BackColor = ctl.BackColor;
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ep = e.Location;
g.DrawLine(p, sp, ep);
h = panel2.CreateGraphics();
h.DrawLine(p, sp, ep);
}
sp = ep;
}
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
sp = e.Location;
}
private void button1_Click(object sender, EventArgs e)
{
SaveFileDialog dialog = new SaveFileDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
bmp.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
A few notes:
I mapped all the clicks of the palette control into one.
I have eliminated the flag k by doing the button test in the move.
I have kept the cached Graphics g; this is usually not recommended, but as we keep drawing into one and the same bitmap is is ok.
I have remove all duplicate declaration of the bitmap bmp.
I don't know what the picturebox does, so I didn't touch the code.
Drawbacks of the soution:
Since you don''t keep track of all the moves you can't do a good undo.
Since all lines are drawn separately you can't get good results with broader and/or semi-transparent Pens because the overlapping endpoints will look bad.
For a better solution of simple doodeling see here and after you have studied it you can tackle the even better solution, which will allow you to use all sort of drawing tools here..
Use Graphics.GetHdc Method and save it like this:
Bitmap bitMap = Bitmap.FromHbitmap(g.GetHdc());
bitMap.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Bmp);
I have 2 images, using the else-if method, how do I make it so that when I click on image A, it turns to image B and if its image B, turn back to image A? Here is my codes:
private void Smalltubbutton1_Click(object sender, EventArgs e)
{
if(System.Drawing.Bitmap bitmap1 =
WindowsFormsApplication21.Properties.Resources.smalltub)
{
System.Drawing.Bitmap bitmap1 =
WindowsFormsApplication21.Properties.Resources.GRAYSCALEsmalltub;
}
else
{
System.Drawing.Bitmap bitmap1 =
WindowsFormsApplication21.Properties.Resources.smalltub
}
}
You can use a PictureBox and change the image property with your proper image and change a boolean property or variable each time you click on that.
private void pictureBox1_Click(object sender, EventArgs e)
{
if (flag)
pictureBox1.Image = WindowsFormsApplication21.Properties.Resources.GRAYSCALEsmalltub;
else
pictureBox1.Image = WindowsFormsApplication21.Properties.Resources.smalltub;
flag=!flag;
}
I hope this would solve your problem. Good Luck.
You could do that someway like this:
private bool flag;
private void Smalltubbutton1_Click(object sender, EventArgs e)
{
System.Drawing.Bitmap bitmap1;
if (flag)
{
bitmap1 = WindowsFormsApplication21.Properties.Resources.GRAYSCALEsmalltub;
}
else
{
bitmap1 = WindowsFormsApplication21.Properties.Resources.smalltub
}
flag = !flag;
}
i'm doing a C# project with my friend. We have to take a signature and save it to a JPG file. We don't have much idea of how doing this, but at least we are trying. We have 2 problems:
1.
When drawing the Graphics, if the mouse moves too fast, not all the points are caught by the mousemove Event and the result image are separated points. How can i improve this?
Here is my code:
private void ingresoFirma_Load(object sender, EventArgs e)
{
myBrush = new SolidBrush(Color.Black);
myGraphics = panel1.CreateGraphics();
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
isDrawing = true;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (isDrawing)
{
myGraphics.FillEllipse(myBrush, e.X, e.Y, 10, 10);
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
isDrawing = false;
}
The second problem is that we have no idea of how to save the Graphics to a .jpg image. We used something like this:
private void saveSign_Click(object sender, EventArgs e)
{
Bitmap signature = new Bitmap(100,100,myGraphics);
signature.Save("c:\\myBitmap.bmp");
}
But it saves a blank image.
Here's something to get you started...
public partial class ingresoFirma : Form
{
private List<Point> stroke = null;
private List<List<Point>> Strokes = new List<List<Point>>();
public ingresoFirma()
{
InitializeComponent();
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
stroke = new List<Point>();
stroke.Add(new Point(e.X, e.Y));
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
stroke.Add(new Point(e.X, e.Y));
if (stroke.Count == 2)
{
Strokes.Add(stroke);
}
panel1.Refresh();
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
stroke = null;
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
foreach(List<Point> curStroke in Strokes)
{
e.Graphics.DrawLines(Pens.Black, curStroke.ToArray());
}
}
private void btnClear_Click(object sender, EventArgs e)
{
Strokes.Clear();
panel1.Refresh();
}
private void btnSave_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "JPG Files(*.JPG)|*.JPG";
if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Bitmap bmp = new Bitmap(panel1.Width, panel1.Height);
panel1.DrawToBitmap(bmp, panel1.ClientRectangle);
bmp.Save(sfd.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
With the DrawToBitmap() method of Control, you can save the image:
Bitmap theBitmap = new Bitmap(panel1.Width, panel1.Height)) ;
panel1.DrawToBitmap(theBitmap, new Rectangle(0, 0, bmp.Width, bmp.Height));
theBitmap.Save("c:\\myBitmap.bmp");
I have a Panel which the user of the application. The panel allows the user to enter their signature digitally. I would like to take the drawing from the panel and copy it to the very end of the richTextBox.
My current code for the panel is as follows:
public partial class Signature : Form
{
SolidBrush color;
float width;
List<List<Point>> _lines;
Boolean _mouseDown;
public Signature()
{
InitializeComponent();
_lines = new List<List<Point>>();
color = new SolidBrush(Color.Black);
_mouseDown = false;
}
private void clear_Click(object sender, EventArgs e)
{
_lines.Clear();
sign.Invalidate();
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
_mouseDown = true;
_lines.Add(new List<Point>());
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (_mouseDown)
{
_lines.Last().Add(e.Location);
sign.Invalidate();
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
foreach (var lineSet in _lines)
{
if (lineSet.Count > 1)
{
e.Graphics.DrawLines(new Pen(Color.Black, 4.0F), lineSet.ToArray());
}
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
_mouseDown = false;
}
private void use_Click(object sender, EventArgs e)
{
MessageBox.Show("Signature successfully imported!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
Basic_Word_Processor.Instance.richTextBoxPrintCtrl1.SelectedText = "";
this.Close();
}
}
}
How can I take the drawing from the Panel and insert it to the end of the richTextBox?
You could first draw the signature to the Bitmap and then copy that bitmap through Clipboard into RichTextBox. You could try this but I must say that it is not tested:
Bitmap bmp = new Bitmap(panel1.Width, panel1.Height);
Rectangle rect = new Rectangle(0, 0, panel1.Width, panel1.Height);
panel1.DrawToBitmap(bmp, rect);
Clipboard.SetImage(bmp);
richTextBox1.Paste();
Or alternatively, you could draw Lines into the Bitmap
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));
}