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!
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.
Related
I want to upgrade from iTextSharp to iText7.
I cant set the image of PdfButtonField to an System.Drawing.Image in the past.
But now in iText7, the PdfButtonFormField.SetImage(string sImagePah) can only acccept file path.
I create an System.Drawing.Image the fly, How can I set the image the an AcroField in iText7.NET ?
You can use SetValue method and provide Base64-encoded image value there.
Example code to covert System.Drawing.Image to a Base64 string:
public static string ImageToBase64(System.Drawing.Image image)
{
using (MemoryStream ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Png);
byte[] imageBytes = ms.ToArray();
return Convert.ToBase64String(imageBytes);
}
}
Example code to set the image to the form field:
PdfButtonFormField field = ...;
field.SetValue(ImageToBase64(image));
I need to convert a JBIG1 image to another image format, such as JPEG or PNG, but I can't seem to find anything related to this.
This JBIG1 image is received encoded in Base64.
I've tried using System.Drawing in .NET to accomplish this, but a "System.ArgumentException: Parameter is not valid" exception is thrown on calling Image.FromStream() using the JBIG1 byte array data.
See code below:
byte[] binData = ConvertFromBase64StringToArray("BASE64 ENCODED JBIG1 IMAGE GOES HERE");
Image img = binData.ConvertToImage();
img.Save("C:/Images/converted-from-jbig.jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
Functions used:
public static byte[] ConvertFromBase64StringToArray(string base64String)
{
byte[] data = Convert.FromBase64String(base64String);
using (var stream = new MemoryStream(data, 0, data.Length))
{
data = stream.ToArray();
}
return data;
}
public static Image ConvertToImage(this byte[] byteArrayIn)
{
var ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms); //exception thrown in this line
return returnImage;
}
Does anyone have any knowledge to share about this topic?
You'll probably need a third party library to work with JBig files. It looks like https://github.com/dlemstra/Magick.NET has support for that.
I'm using this function to convert base64 to image.
public Image Base64ToImage(string base64String)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(base64String);
using (var ms = new MemoryStream(imageBytes, 0,imageBytes.Length))
{
// Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
//Image image = Image.FromStream(ms, true);
Image image = Image.FromStream(ms,true,true);
return image;
}
}
but it is not working. please help me.
I don't thik the ms write call is needed here.
using (var ms = new MemoryStream(imageBytes, 0,imageBytes.Length))
{
// Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
Your are efectively constructing the stream from your byteArray so the ms.Write call will append the data twice in the stream. This might cause issues for your Image object. Either use the default constructor for the stream or delete the Write and test again.
Edit:
Zey deleted his answer but i think he had a good point in there. You might consider dropping the using block as well. My memory might fail me but i think Image objects need the source stream to be kept open. Dispose the Image object when not needed anymore.
I am working on a project where I load 12 long blob images from a database and save them in a list.
In the html page, i have to display the images but i am getting errors when trying to convert a blob to an image.
I get the error Parameter is not valid when using memory stream. No matter whatever change I make, unable to get rid of that error.
Below is the code:
public Image getProduct_Image(byte[] imagebytes)
{
byte[] byteArray = new byte[imagebytes.Length];
MemoryStream ms = new MemoryStream(byteArray);
ms.Position = 0;
ms.Read((byteArray, 0, byteArray.Length);
ms.ToArray();
ms.Seek(0, SeekOrigin.Begin);
System.Drawing.Image returnImage = Image.FromStream((Stream) ms);
Bitmap bmp = new Bitmap(returnImage);
return bmp;
}
Expanding on my comment:
You can write images from bytes into HTML in a few lines of code with an .ashx handler, but since you're using MVC, it's actually really easy.
First you just set up a controller action - assume your image is identifiable based on an integer ID. It's just a single line to return those bytes as content.
public FileContentResult SomeImage(int id)
{
byte[] bytes = GetImageBytesFromDatabase(id);
return File(bytes, "image/jpeg");
}
Your markup is just an image tag with the source as this controller action:
<img src="#Url.Action("SomeImage", "Home", new { id = 123 })" />
This actually creates the following, depending on whether you're doing anything special with your routing:
<img src="/Home/SomeImage/123" />
or possibly
<img src="/Home/SomeImage?id=123" />
I dont see you actually filling your byteArray with data anywhere!
Also, why do you create the byteArray variable in the first place? you already have the blob data as a byte[] in the input variable imagebytes. Remove byteArray and use imagebytes.
public Image getProduct_Image(byte[] imagebytes)
{
try
{
if(imagebytes == null || imagebytes.Length == 0)
throw new InvalidDataException("The blob does not contain any data");
MemoryStream ms = new MemoryStream(imagebytes);
ms.Position = 0;
ms.Read((imagebytes, 0, imagebytes.Length);
ms.ToArray();
ms.Seek(0, SeekOrigin.Begin);
System.Drawing.Image returnImage = Image.FromStream((Stream) ms);
return new Bitmap(returnImage);
}
catch(Exception ex)
{
// deal with the exception
}
}
Is there a way in C# to do this conversion and back?
I have a WPF app which has a Image control. I'm trying to save the image in that control to a SQL Database.
In my Entity Model, the datatype of the picture column in my database is a byte[]. So I found a method to convert a System.Drawing.Image to a byte[] and back. But I haven't found a method to convert from System.Windows.Controls.Image to a byte[].
So that's why I now need to do the above conversion.
If you have a byte array that represents a file that WPF can decode (bmp, jpg, gif, png, tif, ico), you can do the following:
BitmapSource LoadImage(Byte[] imageData)
{
using (MemoryStream ms = new MemoryStream(imageData))
{
var decoder = BitmapDecoder.Create(ms,
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
return decoder.Frames[0];
}
}
Likewise, to convert it back, you can do the following:
byte[] SaveImage(BitmapSource bitmap)
{
using (MemoryStream ms = new MemoryStream())
{
var encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(ms);
return ms.GetBuffer();
}
}
Well, one is an image and one is a control that shows an image, so I don't think that there's a conversion between the two. But, you could set the Source of the ...Controls.Image to be your ...Drawing.Image.
Edit based on update
Does this do what you need - http://msdn.microsoft.com/en-us/library/ms233764%28VS.100%29.aspx