BMP to byte[] and back = GDI error ???

G

Guest

I'm trying to convert an Image file to a byte[] array .
Later in my code I'm trying to create a new Image from this byte[] array as
a restored Image.
But when I try to save the restored Image to a Bitmap file I get a generic
DGI exception saying:
"A generic error occurred in GDI+".

Here is the code I'm using:

////// Loading a bitmap file to a byte[] array ////////////////////////
Bitmap bmpIn = Bitmap.FromFile("Picture.bmp", true) as Bitmap;
MemoryStream msIn = new MemoryStream();
bmpIn.Save(msIn,
System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[0], null);
msIn.Close();
byte[] buf = msIn.GetBuffer();

/////// Creating a new bitmap from the buf byte[] array /////////
Bitmap bmpOut;
MemoryStream msOut = new MemoryStream();
msOut.Write(buf, 0, buf.Length);
bmpOut = new Bitmap(msOut);
msOut.Close();
bmpOut.Save("ImageOut.bmp", System.Drawing.Imaging.ImageFormat.Bmp); //
ERROR: Throw the above exception !!!!


Can anybody tell what is the problem that causes the DGI error ?

Any help will be highly appreciated.
 
J

Jon Skeet [C# MVP]

Sharon said:
I'm trying to convert an Image file to a byte[] array .
Later in my code I'm trying to create a new Image from this byte[] array as
a restored Image.
But when I try to save the restored Image to a Bitmap file I get a generic
DGI exception saying:
"A generic error occurred in GDI+".

Can anybody tell what is the problem that causes the DGI error ?

You've got two problems:
1) By using GetBuffer to start with, you'll end up with padding on the
end (unless you're very lucky). Use ToArray instead.

2) You're not rewinding the memory stream you're using when loading the
bitmap - you've passed the bitmap constructor a stream with no data to
read! Use msOut.Position = 0 before passing it in for reading.
 
G

Guest

Thanks Jon for your reply.

I have changed the code using your remarks as follow:

////// Loading a bitmap file to a byte[] array ////////////////////////
Bitmap bmpIn = Bitmap.FromFile("Picture.bmp", true) as Bitmap;
MemoryStream msIn = new MemoryStream();
bmpIn.Save(msIn,
System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[0], null);
msIn.Close();
byte[] buf = msIn.ToArray();

/////// Creating a new bitmap from the buf byte[] array /////////
Bitmap bmpOut;
MemoryStream msOut = new MemoryStream();
msOut.Write(buf, 0, buf.Length);
msOut.Position = 0;
bmpOut = new Bitmap(msOut);
msOut.Close();
bmpOut.Save("ImageOut.bmp", System.Drawing.Imaging.ImageFormat.Bmp); //
ERROR: Throw the above exception !!!!

But I'm still getting the same error.

Any idea why?
 
J

Jon Skeet [C# MVP]

Sharon said:
Thanks Jon for your reply.

I have changed the code using your remarks as follow:

////// Loading a bitmap file to a byte[] array ////////////////////////
Bitmap bmpIn = Bitmap.FromFile("Picture.bmp", true) as Bitmap;
MemoryStream msIn = new MemoryStream();
bmpIn.Save(msIn,
System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[0], null);
msIn.Close();
byte[] buf = msIn.ToArray();

/////// Creating a new bitmap from the buf byte[] array /////////
Bitmap bmpOut;
MemoryStream msOut = new MemoryStream();
msOut.Write(buf, 0, buf.Length);
msOut.Position = 0;
bmpOut = new Bitmap(msOut);
msOut.Close();
bmpOut.Save("ImageOut.bmp", System.Drawing.Imaging.ImageFormat.Bmp); //
ERROR: Throw the above exception !!!!

But I'm still getting the same error.

Any idea why?

Not immediately. Are you sure it's the last line which is throwing the
exception, rather than the Bitmap constructor line?

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
G

Guest

Ok, here is the full post of the code:

// Loding the picture from a BMP file.
Bitmap bmpIn = Bitmap.FromFile(@"BlueLace.bmp", true) as Bitmap;
// Writing the image data to a MemoryStream.
MemoryStream msIn = new MemoryStream();
bmpIn.Save(msIn,
System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[0], null);
msIn.Close();
byte[] buf = msIn.ToArray();

MemoryStream msOut = new MemoryStream();
msOut.Write(buf, 0, buf.Length);
msOut.Position = 0;
Bitmap bmpOut = new Bitmap(msOut);
msOut.Close();
try
{
bmpOut.Save("ImageOut.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
catch( Exception exp )
{
MessageBox.Show(this, "Failed to save the image to file.\n\n" +
exp.Message + "\n\nTrace: \n" + exp.StackTrace,
"Bitmap Save Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
System.Diagnostics.Process.Start("ImageOut.bmp");
 
G

Guest

OK, I think I see what you mean. So here is the code again:

namespace BmpTest
{
using System;
using System.Drawing;
using System.IO;

class MyClass
{
[STAThread]
static void Main(string[] args)
{
Bitmap bmpIn = Bitmap.FromFile(@"C:\WINDOWS\Blue Lace 16.bmp",
true) as Bitmap;
MemoryStream msIn = new MemoryStream();
bmpIn.Save(msIn,
System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[0], null);
msIn.Close();

byte[] buf = msIn.ToArray();

MemoryStream msOut = new MemoryStream();
msOut.Write(buf, 0, buf.Length);
msOut.Position = 0;
Bitmap bmpOut = new Bitmap(msOut);
msOut.Close();

try
{
bmpOut.Save("ImageOut.bmp",
System.Drawing.Imaging.ImageFormat.Bmp);
}
catch( Exception exp )
{
Console.WriteLine("Failed to save the image to file.\n" +
exp.Message + "\n\nTrace: \n" + exp.StackTrace);
Console.ReadLine();
return;
}
System.Diagnostics.Process.Start("ImageOut.bmp");
}
}
}
 
M

Morten Wennevik

Hi Sharon,

You are closing the MemoryStream before the Bitmap is saved.
Move msOut.Close() down a few lines

MemoryStream msOut = new MemoryStream();
msOut.Write(buf, 0, buf.Length);
msOut.Position = 0;
Bitmap bmpOut = new Bitmap(msOut);
try
{
bmpOut.Save("ImageOut.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
catch( Exception exp )
{
MessageBox.Show(this, "Failed to save the image to file.\n\n" +
exp.Message + "\n\nTrace: \n" + exp.StackTrace,
"Bitmap Save Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
System.Diagnostics.Process.Start("ImageOut.bmp");
msOut.Close();
 
G

Guest

Amazingly it works.

I'm amazed because the msOut MemoryStream is not used when the Bitmap bmpOut
is doing the saving to a file.
 
M

Morten Wennevik

For some reason the Bitmap object keeps a lock on its source. If you use Image.FromFile the file is locked until you dispose of the Bitmap. Apparantly the same goes for Stream sources. Not sure why it does this.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top