C# Image outofboundmemory exception - c#

I have tried to convert binary data to Image. here is my code:
Byte[] bytes = (byte[])(reader["Avatar"]);
fs1.Write(bytes, 0, bytes.Length);
pictureBox1.Image = Image.FromFile("image.jpg");
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Refresh();
but the wrong is out of bound memory exception in line : "pictureBox1.Image = Image.FromFile("image.jpg");"
I do not know why this happen, please help me

Try with this method:
public Image ImageFromBytes(byte[] bytes)
{
using(var ms = new MemoryStream(bytes))
{
return Image.FromStream(ms);
}
}

If fs1 is a stream you probably should close it before you access that file in the next line.
Note that you can also create the image in memory and avoid the file system completely.

You mast Close and Dispose your stream:
fs1.Write(bytes, 0, bytes.Length);
//Make sure you closed your stream
fs1.Close();
// You should call Dispose too.
fs1.Dispose();
pictureBox1.Image = Image.FromFile("image.jpg");
or enclose your writing file procces in using block:
using (Stream fs1 ...)
{
...
fs1.Write(bytes, 0, bytes.Length);
}

Related

How to save an Image to Clients System using .Net Core

I have an Image I am retrieving from the database as a byte array. I want to save it outside the Project i.e on the Clients System. I would appreciate if the code aspect can be assisted with. Here is a sample method I have so far:
public Image byteArrayToImage2()
{
var filePath = "C:\\cat.jpg";
byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
Image returnImage = null;
using (MemoryStream ms = new MemoryStream(fileBytes))
{
returnImage = Image.FromStream(ms);
returnImage.Save("cat2.jpg", ImageFormat.Jpeg);
}
return returnImage;
}
Try the below approach
PS: make sure your fileBytes is of type byte Array.
MemoryStream imageStream = new MemoryStream();
imageStream.Write(fileBytes, 0, fileBytes.Length);
// Include the file name along with extension (Eg: 'C:\TestImage.JPEG')
FileStream fs = File.Create("Give the path where you want to save the image");
imageStream.WriteTo(fs);
fs.Close();
imageStream.Close();

convert binary to bitmap using memory stream

Hi I wanna convert binary array to bitmap and show image in a picturebox. I wrote the following code but I got exception that says that the parameter is not valid .
public static Bitmap ByteToImage(byte[] blob)
{
MemoryStream mStream = new MemoryStream();
byte[] pData = blob;
mStream.Write(pData, 0, Convert.ToInt32(pData.Length));
Bitmap bm = new Bitmap(mStream);
mStream.Dispose();
return bm;
}
It really depends on what is in blob. Is it a valid bitmap format (like PNG, BMP, GIF, etc?). If it is raw byte information about the pixels in the bitmap, you can not do it like that.
It may help to rewind the stream to the beginning using mStream.Seek(0, SeekOrigin.Begin) before the line Bitmap bm = new Bitmap(mStream);.
public static Bitmap ByteToImage(byte[] blob)
{
using (MemoryStream mStream = new MemoryStream())
{
mStream.Write(blob, 0, blob.Length);
mStream.Seek(0, SeekOrigin.Begin);
Bitmap bm = new Bitmap(mStream);
return bm;
}
}
Don't dispose of the MemoryStream. It now belongs to the image object and will be disposed when you dispose the image.
Also consider doing it like this
var ms = new MemoryStream(blob);
var img = Image.FromStream(ms);
.....
img.Dispose(); //once you are done with the image.
System.IO.MemoryStream mStrm = new System.IO.MemoryStream(your byte array);
Image im = Image.FromStream(mStrm);
im.Save("image.bmp");
Try this. If you still get any error or exception; please post your bytes which you are trying to convert to image. There should be problem in your image stream....

Bitmap Conversion

I'm trying to stream a webcam across from a client to a server but I'm having difficulty at the conversion from the byte array back to the bitmap on the server.
Here's the code:
public void handlerThread()
{
Socket handlerSocket = (Socket)alSockets[alSockets.Count-1];
NetworkStream networkStream = new
NetworkStream(handlerSocket);
int thisRead=0;
int blockSize=1024;
Byte[] dataByte = new Byte[blockSize];
lock(this)
{
// Only one process can access
// the same file at any given time
while(true)
{
thisRead=networkStream.Read(dataByte,0,blockSize);
pictureBox1.Image = byteArrayToImage(dataByte);
if (thisRead==0) break;
}
fileStream.Close();
}
lbConnections.Items.Add("File Written");
handlerSocket = null;
}
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn); //here is my error
Image returnImage = Image.FromStream(ms);
return returnImage;
}
At the point marked above I get "Parameter is not valid" when trying to convert back to the image and crash. Any suggestions as to what I'm doing wrong?
Note this bit:
Image.Save(..) throws a GDI+ exception because the memory stream is closed
You can create an extension method or remove the "this" for a traditional method. This looks the same as your code so I wonder if you have some type of encoding or other issue relatd to creating your underlying byte array?
public static Image ToImage(this byte[] bytes)
{
// You must keep the stream open for the lifetime of the Image.
// Image disposal does clean up the stream.
var stream = new MemoryStream(bytes);
return Image.FromStream(stream);
}

Adding Text on Image

I am trying to add some text on top of a photo take by the camera, and here is the method I am using, but unfortunately I either get a closedStream error, or that there is cross-thread access when I try use the dispatcher. Could someone please explain me what is going wrong?
void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
DateTime dt = DateTime.Now;
string fileName = dt.Year.ToString() + dt.Month.ToString() + dt.Day.ToString() + dt.Hour.ToString() + dt.Minute.ToString() + dt.Second.ToString() + ".jpg";
try
{
// Save picture to the library camera roll.
library.SavePictureToCameraRoll(fileName, e.ImageStream);
// Set the position of the stream back to start
e.ImageStream.Seek(0, SeekOrigin.Begin);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// load photo to writable bitmap
WriteableBitmap writeableBitmap = PictureDecoder.DecodeJpeg(e.ImageStream);
writeableBitmap.Invalidate();
var renderText = new TextBlock
{
Text = "Hello World",
FontSize = 72,
Foreground = new SolidColorBrush(Colors.White),
FontWeight = FontWeights.Black,
Width = 500,
Height = 100
};
writeableBitmap.Render(renderText, new TranslateTransform() { X = 100, Y = 300 });
writeableBitmap.Invalidate();
using (var ms = new MemoryStream())
{
writeableBitmap.SaveJpeg(ms, 1024, 768, 0, 100);
ms.Seek(0, SeekOrigin.Begin);
library.SavePicture("x" + fileName, ms);
}
// e.ImageStream.Close();
});
// Save picture as JPEG to isolated storage.
using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
{
// Initialize the buffer for 4KB disk pages.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the image to isolated storage.
while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}
With the code above I get the following error: Cannot access a closed Stream.
If i remove the Dispatcher, I get this error: Invalid cross-thread access.
Thanks.
place ui less code outside dispatcher scope.
or save your e.ImageStream to other stream can be gotted in dispatcher scope.
First, what is occurring?
Dispatcher.BeginInvoke postpones your code and tells the UI thread to execute it whenever it's available. Therefore, your e.ImageStream.Close(); line is executed before the code inside of the BeginInvoke. So when you're trying to read the contents of the stream, it's already closed.
Two ways to solve that:
Remove the e.ImageStream.Close(); from the finally block. But I don't know if the stream will remain open anyway.
If 1. doesn't work, copy the contents of the stream to a MemoryStream, then use this stream to create the WriteableBitmap:
var stream = new MemoryStream();
e.ImageStream.CopyTo(stream);
In both case, don't forget to close the stream when you're done creating the WriteableBitmap.

A generic error occurred in GDI+

I loaded an image into a Picture Box using:
picturebox1.Image = Image.FromFile()
and I save it by using:
Bitmap bm = new Bitmap(pictureBox1.Image);
bm.Save(FileName, ImageFormat.Bmp);
It works perfectly fine when creating a new file, but when I try to replace the existing image, I get thrown the following runtime error:
A generic error occurred in GDI+
So what can I do to solve this problem??
That because the image file is used by your picturebox1.Image, try to save it to different file path instead:
picturebox1.Image = Image.FromFile(FileName);
Bitmap bm = new Bitmap(pictureBox1.Image);
bm.Save(#"New File Name", ImageFormat.Bmp);
Edit: You could also add a copy from the image at the first place like:
picturebox1.Image = new Bitmap(Image.FromFile(FileName));
Bitmap bm = new Bitmap(pictureBox1.Image);
bm.Save(FileName, ImageFormat.Bmp);//no error will occurs here.
The FromFile method locks the file, so use the Image.FromStream() method for reading the image:
byte[] bytes = System.IO.File.ReadAllBytes(filename);
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
pictureBox1.Image = Image.FromStream(ms);
Then save like you were before.
This can also happen if the path does not exist.
You could create the dir with:
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(FileName));
When either a Bitmap object or an Image object is constructed from a file, the file remains locked for the lifetime of the object. As a result, you cannot change an image and save it back to the same file where it originated. http://support.microsoft.com/?id=814675
A generic error occurred in GDI+, JPEG Image to MemoryStream:
Image.Save(..) // throws a GDI+ exception because the memory stream is closed
http://alperguc.blogspot.in/2008/11/c-generic-error-occurred-in-gdi.html
EDIT: Just writing from memory. Saving to an 'intermediary' MemoryStream should work:
For example, replace this:
Bitmap newBitmap = new Bitmap(thumbBMP);
thumbBMP.Dispose();
thumbBMP = null;
newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);
with something like:
string outputFileName = "...";
using (MemoryStream memory = new MemoryStream())
{
using (FileStream fs = new FileStream(outputFileName, FileMode.Create, FileAccess.ReadWrite))
{
thumbBMP.Save(memory, ImageFormat.Jpeg);
byte[] bytes = memory.ToArray();
fs.Write(bytes, 0, bytes.Length);
}
}
try this.
picturebox1.Image = Image.FromFile(FileName);
Bitmap bm = new Bitmat(pictureBox1.Image);
Image img = (Image)b;
img.Save(FileName, ImageFormat.Bmp);
Just like #Jalal Aldeen Saa'd said, the picture box is using the file and locked from file replacement.
//unlock file by clearing it from picture box
if (picturebox1.Image != null)
{
picturebox1.Image.Dispose();
picturebox1.Image = null;
}
//put back the picture inside the pictureBox?
try this it will work
public void SavePicture()
{
Bitmap bm = new Bitmap(this.myBitmap)
bm.Save("Output\\out.bmp" ,System.Drawing.Imaging.ImageFormat.Bmp );
}
This can also happen if you forget to add the filename:
bm.Save(#"C:\Temp\Download", System.Drawing.Imaging.ImageFormat.Png);
And can be fixed by adding the file name:
bm.Save(#"C:\Temp\Download\Image.png", System.Drawing.Imaging.ImageFormat.Png);
Note: You don't actually have to add the extension for it to work.
Try this:
private void LoadPictureBoxWithImage( string ImagePath)
{
Stream objInputImageStream = null;
BitmapData bmdImageData = null;
Bitmap bmpSrcImage = null, bmTemp = null;
byte[] arrImageBytes = null;
int bppModifier = 3;
try
{
objInputImageStream = new MemoryStream();
using (FileStream objFile = new FileStream(ImagePath, FileMode.Open, FileAccess.Read))
{
objFile.CopyTo(objInputImageStream);
}
bmpSrcImage = new Bitmap(objInputImageStream);
bppModifier = bmpSrcImage.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4;
//reda from byte[] to bitmap
bmdImageData = bmpSrcImage.LockBits(new Rectangle(0, 0, bmpSrcImage.Width, bmpSrcImage.Height), ImageLockMode.ReadOnly, bmpSrcImage.PixelFormat);
arrImageBytes = new byte[Math.Abs(bmdImageData.Stride) * bmpSrcImage.Height];
System.Runtime.InteropServices.Marshal.Copy(bmdImageData.Scan0, arrImageBytes, 0, arrImageBytes.Length);
bmpSrcImage.UnlockBits(bmdImageData);
pbSetup.Image = (Bitmap)bmpSrcImage.Clone();
pbSetup.Refresh();
}
catch (Exception ex)
{
throw new Exception("Error in Function " + System.Reflection.MethodInfo.GetCurrentMethod().Name + "; " + ex.Message);
}
finally
{
if (objInputImageStream != null)
{
objInputImageStream.Dispose();
objInputImageStream = null;
}
if (bmdImageData != null)
{
bmdImageData = null;
}
if (bmpSrcImage != null)
{
bmpSrcImage.Dispose();
bmpSrcImage = null;
}
if (bmTemp != null)
{
bmTemp.Dispose();
bmTemp = null;
}
if (arrImageBytes != null)
{
arrImageBytes = null;
}
}
}
A generic error occurred in GDI+
I also faced the same issue. I tried so many ways to fix this issue. Finally, I found a place where I have gone wrong. The problem is that I used space in the file path, which is not acceptable. Now it is working fine after removing the space in front of C after the apostrophe:
"SupplyItems":"C:\\inetpub\\HIBMS_Ver1\\BarcodeImages\\Supply\\"
instead... I used below one.
"SupplyItems":" C:\\inetpub\\HIBMS_Ver1\\BarcodeImages\\Supply\\"
Minor mistake but took a long time to find and to fix it.
Note that images created by Image.Clone() will still cause GDI+ errors as shown by the BAD code below, you must use the Image.FromStream() method for reading the image as shown in the solution on this page.
//BAD CODE: the image we will try to save AFTER the original image has been cloned and disposed
Image clonedImage;
//load image from file, clone it then dispose
using (var loadedFromDiskImage = Image.FromFile(filePath))
{
clonedImage = (Image) loadedFromDiskImage.Clone();
}
//you might think the new image can be saved given the original is disposed
//but this doesn't seem to be the way Clone() works
//expect GDI+ error in line below:
clonedImage.Save(filePath);

Categories