2

I have an image converted to a base64 string that I need to convert back to an image and attach to a MailMessage.

Here is the relevant code converting it from base64 string to image (I think I can skip the Image object and do this using one memory stream, but had some issues implementing that). Attempting to save the Image to a MemoryStream throws a generic GDI+ error:

Image image = ImageHelper.Base64ToImage(attachment.FieldData);

if (image != null)
{
    using (var ms = new MemoryStream())
    {
        image.Save(ms, ImageFormat.Png); // Throws a generic GDI+ error on Save

        ms.Position = 0;

        var imageAttachment = new Attachment(ms, "image.png", "image/png");

        message.Attachments.Add(imageAttachment);
    }
}

public static class ImageHelper
{
    public static Image Base64ToImage(string base64String)
    {
        if (string.IsNullOrEmpty(base64String))
        {
            return null;
        }

        byte[] imageBytes = Convert.FromBase64String(base64String);

        using (var ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
        {
            ms.Write(imageBytes, 0, imageBytes.Length);

            Image image = Image.FromStream(ms, true);

            return image;
        }
    }
}

I'm able to serve up the raw base64 string elsewhere using an img tag and it works fine so I'm confident that the problem isn't with the base64 string itself:

<img src="data:image/png;base64,<myBase64StringHere>" alt="My Image" width="500" />

I must be doing something wrong in converting it back, but I haven't been able to figure out the issue. Thanks for any help with this!

4
  • Are you sure the image has, "color management information embedded in the data stream"? Maybe you only wanted to "validate the image", in which case use this overload with false for the embedded color stuff: Image.FromStream(ms, false, true);. Commented Oct 24, 2016 at 22:41
  • I tried both Image.FromStream(ms, false, true) and Image.FromStream(ms), but still get the same A generic error occurred in GDI+. error on Image.Save(ms, ImageFormat.Png) Commented Oct 24, 2016 at 23:03
  • 1
    Think I found your problem from reading here, you are not using Bitmap, but the same thing occurs with Image.FromStream(): "You must keep the stream open for the lifetime of the Image". You however are using the MemoryStream so it is disposed as the image is returned, and once that happens the Image is no longer usable. Maybe your static class needs to return Tuple<Image, MemoryStream>. Commented Oct 25, 2016 at 15:51
  • That was indeed the problem, thank you so much! If you post this as an answer, I can accept it. Commented Oct 25, 2016 at 16:40

1 Answer 1

2

Image.FromStream(Stream) says, "You must keep the stream open for the lifetime of the Image", but your using statement disposes the stream as the Image is returned. A workaround would be to return both the image and the stream together as a tuple and without the using:

public static Tuple<Image, MemoryStream> Base64ToImage(string base64String)
{
    if (string.IsNullOrEmpty(base64String))
    {
        return null;
    }

    byte[] imageBytes = Convert.FromBase64String(base64String);
    var ms = new MemoryStream(imageBytes, 0, imageBytes.Length)        
    ms.Write(imageBytes, 0, imageBytes.Length);
    Image image = Image.FromStream(ms, true);

    return new Tuple<Image, MemoryStream>(image, ms);
}

Also note to take care and view each overload on the MSDN pages. Normally I would say, "view the most encompassing overload to get all the remarks and notes", but in this case that is not true. The MSDN page for the biggest overload, Image.FromStream Method (Stream, Boolean, Boolean) does not mention that you need to keep the stream open, but I am fairly certain that is a mistake on that particular page.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.