Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / .NET SDK / November 2005

Tip: Looking for answers? Try searching our database.

Getting exception in Image.Save()

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
David Thielen - 03 Nov 2005 23:39 GMT
Hi;

I am doing the following:
// note data is a .bmp file read it to a byte[]
System.IO.Stream file = new System.IO.MemoryStream(data, false);
System.Drawing.Image img = new System.Drawing.Bitmap(file);

// get 64.4 for dpi - image is good
xDpi = img.get_HorizontalResolution();
yDpi = img.get_VerticalResolution();

// save it to a byte[]
System.IO.MemoryStream mem = new System.IO.MemoryStream();
img.Save(mem, System.Drawing.Imaging.ImageFormat.get_Bmp());

the save throws an exception
{"A generic error occurred in GDI+."}    System.Exception
{System.Runtime.InteropServices.ExternalException}

I am calling this in J# if that makes a difference (it shouldn't).

Any ideas?

Signature

thanks - dave

"Peter Huang" [MSFT] - 04 Nov 2005 07:44 GMT
Hi

Did the problem persists with all the image?
Have you tried to load another bitmap from file directly and call save to
stream to see if the problem persists.
So far I can not  reproduce the problem.
Here is my reproduce code.

    private void button1_Click (Object sender, System.EventArgs e)
    {
        System.Drawing.Image img = new System.Drawing.Bitmap("C:\\test.bmp");
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        img.Save(ms,System.Drawing.Imaging.ImageFormat.get_Bmp());
        Image i = Image.FromStream(ms);
        this.pictureBox1.set_Image(i);
        System.IO.MemoryStream mms = new System.IO.MemoryStream();
        i.Save(mms,System.Drawing.Imaging.ImageFormat.get_Bmp());
    }

Best regards,

Peter Huang
Microsoft Online Partner Support

Signature

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

justin.creasy@gmail.com - 07 Nov 2005 20:56 GMT
Hello, I was having a very similar problem myself. I'm not sure if you
have found the solution you required yet, but if you have not let me
tell you what helped me. There's a group posting at

http://groups.google.com/group/microsoft.public.dotnet.framework.drawing/browse_
frm/thread/90667827ea17b47e/8ad839debcae8055?lnk=st&q=System.Runtime.InteropServ
ices.ExternalException:+A+generic+error+occurred+in+GDI%2B&rnum=15&hl=en#8ad839d
ebcae8055


that I found very helpful. There it's explained that the lifetime of
the stream has a lot to do with saving the image. Try reading through
that post and the MSDN document linked to in the post. It helped me get
my program working. Good luck
David Thielen - 08 Nov 2005 20:12 GMT
Thank you to Justin for the solution. The below code work - not the Close on
a no longer needed stream is commented out. If that comment is removed, the
save will fail.

Can someone either explain to me why this happens or if it's a bug, report
it to the .net team?

        File filename = new File("../../Image1.bmp");
        System.out.println("reading file " + filename.getCanonicalPath());
        FileInputStream fis = new FileInputStream(filename);
        byte[] data = new byte[fis.available()];
        fis.read(data);
        fis.close();
        System.out.println("file read, " + data.length + " bytes");

        // get the image
        System.out.println("Create a bitmap from the file image");
        System.IO.Stream file = new System.IO.MemoryStream(toUbyteArray(data),
false);
        System.Drawing.Image img = new System.Drawing.Bitmap(file);
//**this makes it fail        file.Close();
        System.out.println("Image size is " + img.get_Width() + "x" +
img.get_Height());
        System.out.println("Image dpi is " + img.get_HorizontalResolution() + "x"
+ img.get_VerticalResolution());

        System.out.println("Save image in bmp format to a MemoryStream");
        System.IO.MemoryStream mem = new System.IO.MemoryStream();
        img.Save(mem, System.Drawing.Imaging.ImageFormat.get_Bmp());
        System.out.println("Image saved!");

Signature

thanks - dave

"Peter Huang" [MSFT] - 09 Nov 2005 02:35 GMT
Hi

Thanks for your experience sharing.

Best regards,

Peter Huang
Microsoft Online Partner Support

Signature

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

David Thielen - 09 Nov 2005 03:17 GMT
Hi;

Can someone either explain to me why this happens or if it's a bug, report
it to the .net team?

Signature

thanks - dave

> Hi
>
[quoted text clipped - 7 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "AS IS" with no warranties, and confers no rights.
"Peter Huang" [MSFT] - 10 Nov 2005 05:16 GMT
Hi

I think this is by design.
Because you create the bitmap from the underlying Stream, but the data is
still in the Stream, if you close the stream then the Save will fail due to
it can not get the data.

        System.IO.Stream file = new System.IO.MemoryStream(toUbyteArray(data),
false);
        System.Drawing.Image img = new System.Drawing.Bitmap(file);
//**this makes it fail        file.Close();
        System.out.println("Image size is " + img.get_Width() + "x" +
img.get_Height());
        System.out.println("Image dpi is " + img.get_HorizontalResolution() + "x"
+ img.get_VerticalResolution());

        System.out.println("Save image in bmp format to a MemoryStream");
        System.IO.MemoryStream mem = new System.IO.MemoryStream();
        img.Save(mem, System.Drawing.Imaging.ImageFormat.get_Bmp());
        System.out.println("Image saved!");
Best regards,

Peter Huang
Microsoft Online Partner Support

Signature

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

David Thielen - 10 Nov 2005 14:19 GMT
Isn't the data read in to the Bitmap object? The Bitmap object does have the
size, dpi, etc of the passed in bitmap so it has to have parsed at least some
of it.

At what point is it safe to close the Stream passed to the Bitmap object? I
don't want to leave the Stream open forever but if I am keeping a Bitmap in
memory, I need to know until what point I have to keep the Stream open too.

Signature

thanks - dave

> Hi
>
[quoted text clipped - 23 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "AS IS" with no warranties, and confers no rights.
Willy Denoyette [MVP] - 10 Nov 2005 20:29 GMT
> Isn't the data read in to the Bitmap object? The Bitmap object does have
> the
[quoted text clipped - 8 lines]
> memory, I need to know until what point I have to keep the Stream open
> too.

No Peter is right, the Bitmap or Image object is constructed from the Stream
(the file or whatever), and you must keep the Stream open for the lifetime
of the Bitmap (or Image).
The reason for this is that GDI+ (System.Drawing) must have access to the
source bits for the Image for the lifetime of the Bitmap or the Image
object, the source may not be modified during that time, that's why the file
is kept locked for the lifetime of the Bitmap or Image.
A possible work-arround is to create a new Bitmap from the first and Dispose
the first when done, when calling Dispose on the Bitmap the File stream will
automatically be closed.
Creating a new Bitmap from an existing Bitmap can be done in two ways:
1. Create an Non-Indexed Image. Here you use Graphics.FromImage and
Graphics.drawImage to copy a Bitmap to anther one.
2. Create an Indexed Image, this uses Blimap.LockBits to lock the pixel data
of both images and marshal.Copy to copy bitmapdata from one to another
Bitmap object bitmapdata.
Here is a sample of the latter...

     Bitmap im1 = new Bitmap(@"xxxxx.bmp", true);
     Bitmap im2 = new Bitmap(im1, im1.Size);

     Rectangle rect = new Rectangle(0, 0, im1.Width, im1.Height);
     BitmapData im1Data = im1.LockBits(rect, ImageLockMode.ReadWrite,
im1.PixelFormat);
     BitmapData im2Data = im2.LockBits(rect, ImageLockMode.ReadWrite,
im2.PixelFormat);
     // Get the address of the first pixel data line.
     IntPtr im1ptr = im1Data.Scan0;
     IntPtr im2ptr = im2Data.Scan0;
     // Declare an array to hold the bytes of the bitmap.
     // This code is for a bitmap with 24 bits per pixels bmp
     int bytes = im1.Width * im1.Height * 3;
     byte[] rgbValues = new byte[bytes];

     Marshal.Copy(im1ptr, rgbValues, 0, bytes);
     Marshal.Copy(rgbValues, 0, im2ptr, bytes);
   // Unlock the bits.
     im1.UnlockBits(im1Data);
     im2.UnlockBits(im2Data);
     im1.Dispose();
// Now the Filestream if unlocked (Closed), you can do whatever you want
with the second bitmap f.i overwrite the sfile holding the first image.

Willy.
David Thielen - 10 Nov 2005 23:01 GMT
Hi;

Ok, I guess I will create a class that holds a bitmap and stream and just
close them as a pair.

Signature

thanks - dave

> > Isn't the data read in to the Bitmap object? The Bitmap object does have
> > the
[quoted text clipped - 53 lines]
>
> Willy.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.