A generic error occurred in GDI+ Drawings.AddPicture using EPPlus - c#

I want to add a picture in Excel. I use the library EPPLus. It is necessary to obtain an image of the BASE64 format and inserted into the cell in Excel
My Code:
using (System.Drawing.Image img = Base64ToImage(base64String))
{
ExcelPicture excelImage = null;
if (img != null)
{
ERROR HERE excelImage = worksheet.Drawings.AddPicture("Title", img);
excelImage.From.Column = 1;
excelImage.From.Row = 1;
excelImage.SetSize(100, 100);
}
}
public Image Base64ToImage(string base64String)
{
// Convert base 64 string to byte[]
byte[] imageBytes = Convert.FromBase64String(base64String);
// Convert byte[] to Image
using (var ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
Image image = Image.FromStream(ms, true);
return image;
}
}

From MSDN:
You must keep the stream open for the lifetime of the Image.
I don't think you need to enclose MemoryStream in using

Related

Android Xamarin - retrieve the image stored in an imageview

I retrieve an image as a byte arrary stored in a database convert it to a bitmap and display it in an Imageview. I want to be able to retrieve that image from the Imageview and store it back to the database. My database retrieval code is:
TheService myService = new TheService.DataInterface();
DataSet MyPhoto = myService.GetPhoto(id);
byte[] imageBytes = (byte[])MyPhoto.Tables[0].Rows[0][0];
Bitmap bitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
imageview.SetImageBitmap(bitmap);
At some point the image is changed and I need to store it back in the database. How would I get the image out of the imageview? Everything I've seen thus far deals with an attached drawable, there is no drawable in this case.
There doesn't seem to be a method like:
Bitmap photo = imageview.GetCurrentImage();
Any assistance would be appreciated.
**** UPDATED ****
Once I get the image I need to convert it into a byte array to save it into the database. I've tried several different methods with no success, the latest is:
using Java.Nio;
public static byte[] ImageToByte(Bitmap bitmap)
{
var bytes = new Byte[30000];
try
{
var byteBuffer = ByteBuffer.Allocate(bitmap.ByteCount);
bitmap.CopyPixelsToBuffer(byteBuffer);
bytes = byteBuffer.ToArray<byte>();
return bytes;
}
catch (Exception ex)
{
var message = ex.Message;
return bytes;
}
}
This generates an exception "Unable to cast from 'java/nio/HeapByteBuffer' to '[B'"
What you need to do is something like below:
BitmapDrawable bitmapDrawable = ((BitmapDrawable) imageView.Drawable);
Bitmap bitmap;
if(bitmapDrawable==null){
imageView.BuildDrawingCache();
bitmap = imageView.GetDrawingCache();
imageView.BuildDrawingCache(false);
}else
{
bitmap = bitmapDrawable .Bitmap;
}
Where imageView is the imageView control from which you want your bitmap
Update:
Convert from bitmap to byteArray something like this:
byte[] bitmapData;
using (var stream = new MemoryStream())
{
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
bitmapData = stream.ToArray();
}

C# Image to base64

I have a base64 image and i have to convert it into Image. I am doing this using this code:
public static Image ConvertBase64StringToImage(string imageBase64String)
{
var imageBytes = Convert.FromBase64String(imageBase64String);
var imageStream = new MemoryStream(imageBytes, 0, imageBytes.Length);
imageStream.Write(imageBytes, 0, imageBytes.Length);
var image = Image.FromStream(imageStream, true);
return image;
}
Then i have to convert this Image into base64 again. Im using this code:
public static string ConvertImageToBase64String(Image image)
{
var imageStream = new MemoryStream();
image.Save(imageStream, ImageFormat.Png);
imageStream.Position = 0;
var imageBytes = imageStream.ToArray();
return Convert.ToBase64String(imageBytes);
}
After converting the original base64Image to image and again to base64, it loses quality.The Original base64 image is 1676 in length and after conversion it has 1660 in length.
I need the same image after conversion because i have to compare it. Any ideas how to do it without losing quality?
According to this page although PNG files are lossless, you can specify how much file compression to use when storing. IMO, as long as the Image comes out the same (you can compare them using some sort of MD5 tool), it doesn't matter if the size of the file is different when you save it, as the actual image is still the same as the original.
This is how to convert and compare your images, if the result from CompareImages is zero, it means that they are equal or very similar.
static void Main(string[] args)
{
Image img = new Bitmap("Koala.jpg");
string img64Bit = ConvertImageToBase64String(img);
Image newImg = ConvertBase64StringToImage(img64Bit);
newImg.Save("KoalaCopy.jpg");
Console.WriteLine(CompareImages(img, newImg));
Console.ReadLine();
}
public static string ConvertImageToBase64String(Image image)
{
using (MemoryStream ms = new MemoryStream())
{
image.Save(ms, image.RawFormat);
return Convert.ToBase64String(ms.ToArray());
}
}
public static Image ConvertBase64StringToImage(string image64Bit)
{
byte[] imageBytes = Convert.FromBase64String(image64Bit);
return new Bitmap(new MemoryStream(imageBytes));
}
public static int CompareImages(Image i1, Image i2)
{
string img1 = ConvertImageToBase64String(i1);
string img2 = ConvertImageToBase64String(i2);
return String.Compare(img1, img2);
}

Changing image size from stream

I've searched here for help with this, but nothing quite matches what I need. I have an image that gets uploaded, and I'd like to change the size before it gets saved to azure.
So currently my code is:
public ActionResult UserDetails(HttpPostedFileBase photo)
{ var inputFile = new Photo()
{
FileName = photo.FileName,
Data = () => photo.InputStream
};
//then I save to Azure
How would I change the photo.InputStream to 100x 100 px for example?
Here is how I do it:
byte[] imageBytes;
//Of course image bytes is set to the bytearray of your image
using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
using (Image img = Image.FromStream(ms))
{
int h = 100;
int w = 100;
using (Bitmap b = new Bitmap(img, new Size(w,h)))
{
using (MemoryStream ms2 = new MemoryStream())
{
b.Save(ms2, System.Drawing.Imaging.ImageFormat.Jpeg);
imageBytes = ms2.ToArray();
}
}
}
}
From there, I use a MemoryStream to upload. I use blob storage and use the UploadFromStreamAsync to load to blob.
This is a basic view of it.

Convert raw images to bitmap in c#

My code currently looks like this:
if (fe == "CR2")
{
Image img = null;
byte[] ba = File.ReadAllBytes(open.FileName);
using (Image raw = Image.FromStream(new MemoryStream(ba)))
{
img = raw;
}
Bitmap bm = new Bitmap(img);
pictureBox1.Image = bm;
statusl.Text = fe;
}
When I open a RAW image the program stops and Visual Studio says:
Parameter is not valid: Image raw = Image.FromStream(new MemoryStream(ba))
Please help! How can I get a RAW file to show in a PictureBox ?
Create the bitmap like this:
Bitmap bmp = (Bitmap) Image.FromFile(open.FileName);
or without using bitmap:
this.pictureBox1.Image = Image.FromFile(open.FileName);
Example WPF:
BitmapDecoder bmpDec = BitmapDecoder.Create(new Uri(origFile),
BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
BitmapEncoder bmpEnc = new BmpBitmapEncoder();
bmpEnc.Frames.Add(bmpDec.Frames[0]);
Stream ms = new MemoryStream();
bmpEnc.Save(ms);
Image srcImage = Bitmap.FromStream(ms);
You're actually disposing an Image by specifying using (Image raw = Image.FromStream(new MemoryStream(ba))) later assigning the Disposed instance of image to picturebox which leads to this exception. To make to work you've to either don't dispose or clone the image.
Bitmap raw = Image.FromStream(new MemoryStream(ba) as Bitmap;
pictureBox1.Image = raw;
Or simply Clone
using (Image raw = Image.FromStream(new MemoryStream(ba)))
{
img = raw.Clone() as Bitmap;
}
Both of the above should work
you try this code :
private static void SaveImageToRawFile(string strDeviceName, Byte[] Image, int nImageSize)
{
string strFileName = strDeviceName;
strFileName += ".raw";
FileStream vFileStream = new FileStream(strFileName, FileMode.Create);
BinaryWriter vBinaryWriter = new BinaryWriter(vFileStream);
for (int vIndex = 0; vIndex < nImageSize; vIndex++)
{
vBinaryWriter.Write((byte)Image[vIndex]);
}
vBinaryWriter.Close();
vFileStream.Close();
}
private static void LoadRawFile(string strDeviceName, out Byte[] Buffer)
{
FileStream vFileStream = new FileStream(strDeviceName, FileMode.Open);
BinaryReader vBinaryReader = new BinaryReader(vFileStream);
Buffer = new Byte[vFileStream.Length];
Buffer = vBinaryReader.ReadBytes(Convert.ToInt32(vFileStream.Length));
vBinaryReader.Close();
vFileStream.Close();
}

Converting image to base64

I have the following code to convert image to base64:
private void btnSave_Click(object sender, RoutedEventArgs e)
{
StreamResourceInfo sri = null;
Uri uri = new Uri("Checked.png", UriKind.Relative);
sri = Application.GetResourceStream(uri);
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(sri.Stream);
WriteableBitmap wb = new WriteableBitmap(bitmap);
MemoryStream ms = new MemoryStream();
wb.SaveJpeg(ms, bitmap.PixelWidth, bitmap.PixelHeight, 0, 100);
byte[] imageBytes = ms.ToArray();
base64 = System.Convert.ToBase64String(imageBytes);
}
And the following code to get Bitmap image form base 64:
public static BitmapImage base64image(string base64string)
{
byte[] fileBytes = Convert.FromBase64String(base64string);
using (MemoryStream ms = new MemoryStream(fileBytes, 0, fileBytes.Length))
{
ms.Write(fileBytes, 0, fileBytes.Length);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(ms);
return bitmapImage;
}
}
So when i convert and deconvert it is blank.
I know that deconverter works, because, when i give him exact string:
string base64="iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAQAAABLCVATAAACH0lEQVR42q3WoZKrMBQGYGRkIpHEoY9DMrh1nUGtzxPcGV7gCsTaK3iBCqa2ipmrVqLrWrmytjL3nBwoEGD30ja/6JaSj/wp3SEIXjpUoB+Oeg0zpoR+NsyoDVOgi39cbYHAy4MQTc0wOYZepxRBUkn9UxxEiNnXxyYwd6w/438hSddHJilv1tqv664Shle1DeJaJihPV9uNQ+NWBRK2QVSr+GjtaFzOIpdjKFShnoY+Gv0N0u0OVLexY48NQ+68JchdpQu/o1piVMu6faJdwjNWIAYyl55bqGUtbndO53TzCIpUpCkdlEm+V3J3Ir8r3uops2+FkTmvx832IGJwN97xS/5Ti0LQ/WLwtbxMal2ueAwvc2c8CAgSJip5U4+tKHECMlUzq2UcA9EyROuJi6/71dtzWAfVcq0Jw1CsYh13kDDteVoirE+zWtLVinQ8ZAS5YlVlvRHWfi3pakUQL0OOwmp/W/vN6Gt5zBIkzEezxnCtMJsxDIECTYmhp3bej4HHzaalNMyAnzE0UBKp6Z1Do2pwd3JkAH6CxlTs/bZOZ661yMwhohDLQqREMWz8UAvWoUQleggehG5dSPUbv28GJlnKHGJsqPi7vuG/MGTyCGslOtkCOayrGOa/indajdudb6FUpXoepgiLHIIMriddyzrkMBhGAqlOH4U2hKCT2j0NdU8jFbzpZ3LQlh9srPqEQ1Y9lEP2CVa99KHvH8mnrGGdl9V9AAAAAElFTkSuQmCC";
Which is my Checked.png converted in online converter. It decompreses perfectly.
And this is my base64, which i get by converting:
"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"
My problem is that string which i get as base64 from my code - is incorrect *What i did wrong?*
What about trying:
public static BitmapImage base64image(string base64string)
{
byte[] fileBytes = Convert.FromBase64String(base64string);
using (MemoryStream ms = new MemoryStream(fileBytes))
{
Image streamImage = Image.FromStream(ms);
context.Response.ContentType = "image/jpeg";
streamImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
return streamImage;
}
}
I agree with Alexei that your code for reading the image in does look a little strange. I've recently written some code for a similar task that I was doing which might point you in the right direction:
string fileContent = null;
/* Check the file actually has some content to display to the user */
if (uploadFile != null && uploadFile.ContentLength > 0)
{
byte[] fileBytes = new byte[uploadFile.ContentLength];
int byteCount = uploadFile.InputStream.Read(fileBytes, 0, (int)uploadFile.ContentLength);
if (byteCount > 0)
{
fileContent = CreateBase64Image(fileBytes);
}
}
private string CreateBase64Image(byte[] fileBytes)
{
Image streamImage;
/* Ensure we've streamed the document out correctly before we commit to the conversion */
using (MemoryStream ms = new MemoryStream(fileBytes))
{
/* Create a new image, saved as a scaled version of the original */
streamImage = ScaleImage(Image.FromStream(ms));
}
using (MemoryStream ms = new MemoryStream())
{
/* Convert this image back to a base64 string */
streamImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return Convert.ToBase64String(ms.ToArray());
}
}
not an answer: more of a long comment ... OP states that decoding code works perfectly fine, also it looks suspicios. Also code assumed to be verified to work on PNG images, but saving code explicitly produces valid JPG with SaveJpeg call...
Your code that creates stream for reading looks strange - you create stream over existing byte array, than write the same bytes into that stream, and that pass that stream without seeking back to 0 to some method.
Potential fix (assuming BitampImage can accept JPG stream):
don't call Write at all as stream already have the bytes you want
set ms.Position = 0 after writing to the stream.
Note: I'm not sure if it is OK to dispose stream that is a source for BitmapImage, you may need to remove using too.

Categories

Resources