Reputation: 1122
I have a very simple method that takes a signature as a list of points and draws them as lines on a bitmap. And I want to take that bitmap and save it to a file, but when I call the Save method Im getting "A generic error occured in GDI+" and no Inner Exception.
This seems like pretty straight forward code so Im not sure what the problem is.
using (var b = new Bitmap(width, height))
{
var g = Graphics.FromImage(b);
var lastPoint = points[0];
for (int i = 1; i < points.Length; i++)
{
var p = points[i];
// When the user takes the pen off the device, X/Y is set to -1
if ((lastPoint.X >= 0 || lastPoint.Y >= 0) && (p.X >= 0 || p.Y >= 0))
g.DrawLine(Pens.Black, lastPoint.X, lastPoint.Y, p.X, p.Y);
lastPoint = p;
}
g.Flush();
pictureBox.Image = b;
b.Save("C:\\test.bmp");
}
I've tried saving with all the possible ImageFormats, put the graphics object in a using statement, and as a long shot I even tried:
using (var ms = new MemoryStream())
{
b.Save(ms, ImageFormats.Bmp); // And b.Save(ms, ImageFormats.MemoryBmp);
Image.FromStream(ms).Save("C:\\test.bmp");
}
The strange thing is, if I remove the b.Save (or ignore the exception), the pictureBox displays the image perfectly.
Any help would be appreciated.
Upvotes: 0
Views: 1592
Reputation: 54433
Your code has two issues, one hiding the other:
C:
, so the Save
fails.PictureBox
display a Bitmap
which you then destroy in the using
block.So you should change the code to something like this:
var b = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(b))
{
var lastPoint = points[0];
for (int i = 1; i < points.Length; i++)
{
var p = points[i];
// When the user takes the pen off the device, X/Y is set to -1
if ((lastPoint.X >= 0 || lastPoint.Y >= 0) && (p.X >= 0 || p.Y >= 0))
g.DrawLine(Pens.Black, lastPoint.X, lastPoint.Y, p.X, p.Y);
lastPoint = p;
}
// g.Flush(); not necessary
pictureBox1.Image = b;
b.Save("C:\\temp\\test.bmp");
}
You also should include a check on the Length
of the array and consider using a List<Points>
instead, also checking its Count
and using DrawLines
on points.ToArray()
for better line joins, especially with thick, semi-transparent lines!
Upvotes: 1
Reputation: 13188
I would draw to the PictureBox
using the corresponding Graphics
from the Paint
event and then save to a bitmap:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
MyDrawing(e.Graphics);
Bitmap b = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.DrawToBitmap(b, pictureBox1.ClientRectangle);
b.Save(@"C:\test.bmp");
}
private void MyDrawing(Graphics g)
{
var lastPoint = points[0];
for (int i = 1; i < points.Count; i++)
{
var p = points[i];
// When the user takes the pen off the device, X/Y is set to -1
if ((lastPoint.X >= 0 || lastPoint.Y >= 0) && (p.X >= 0 || p.Y >= 0))
g.DrawLine(Pens.Black, lastPoint.X, lastPoint.Y, p.X, p.Y);
lastPoint = p;
}
g.Flush();
}
Saved BMP:
Upvotes: 2