C# SQL Server image path cannot be null - c#

I got some problem here, so in case after I show the image, I don't want to change the image that shown but It get me some exception but when I choose the same images again, it works
System.ArgumentNullException: 'Path cannot be null.
Parameter name: path'
and when I change the image and saves the changes its fine properly. line 2 exception
byte[] imagebt = null;
FileStream fst = new FileStream(picUploadAdmin.ImageLocation, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fst);
imagebt = br.ReadBytes((int)fst.Length);
upcs.updateimageonclubs(txtEditClubNameAdmin.Text, imagebt);
This is how I show my image
if (dr.HasRows)
{
byte[] images = ((byte[])dr1["image"]);
if (images != null)
{
MemoryStream ms = new MemoryStream(images);
picUploadAdmin.Image = Image.FromStream(ms);
}
else
{
images = null;
}

Related

Image to byte array fails "A generic error occurred in GDI+."

let's assume I let the user choose an image from the computer. I load the file to a picture box. here is the conversion method:
public static Image LoadImageFromFile(string fileName)
{
Image result = null;
if (!File.Exists(fileName))
return result;
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
try
{
using (Image image = Image.FromStream(fs))
{
ImageManipulation.RotateImageByExifOrientationData(image);
result =(Image) image.Clone();
image.Dispose();
}
}
finally
{
fs.Close();
}
return result;
}
then, when the user clicks on the Save button, I convert the image into a byte array and save it into the database. here is the conversion code:
public static byte[] ImageToByteArray(Image image)
{
if (image == null)
return null;
using (var ms = new MemoryStream())
{
ImageFormat imageFormat = image.RawFormat;
ImageCodecInfo codec = ImageCodecInfo.GetImageDecoders().FirstOrDefault(c => c.FormatID == imageFormat.Guid);
var encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
if (codec != null)
image.Save(ms, codec, encoderParameters);
else
image.Save(ms, ImageFormat.Jpeg);
return ms.ToArray();
}
}
but the problem:
I have a jpg file on the disk. I can load it into my picture box without any problem. the picture is perfectly visible in it. but when I save it, the code gives me "A generic error occurred in GDI+." Error at 'image.Save(ms, codec,encoderParameters)' line.
more odd incident: I don't get this error all the time. it is happening with specific images. for example, I downloaded an image from the internet and crop it in "Paint" and saved it as jpg. error happened. open it in Paint again and save it as png. no error!!!! that is why I am really confused . and Yes I already have tried to don't dispose the image. not helping
I know it might be a stupid question but I am desperately stuck here :)
Thank you in Advanced
I didn't find out why my code is not working but I just substitute my loading method with the code below. it is releasing the file and at the same time works as it should.
public static Image LoadImageFromFile(string fileName)
{
using (Bitmap bmb = new Bitmap(fileName))
{
MemoryStream m = new MemoryStream();
bmb.Save(m, ImageFormat.Bmp);
return Image.FromStream(m);
}
}

SqlDataReader: Read varbinary into byte array

I have a SQL Server table with a varbinary(max) column. I use it to store images in it. The images are selected with an OpenFileDialog, translated into a byte[] like this
public byte[] ConvertImageToByteArray(String filepath)
{
try
{
return File.ReadAllBytes(filepath);
}
catch (Exception)
{
throw;
}
}
and then stored into the database using this line of code:
sqlCmd.Parameters.Add("#image", SqlDbType.VarBinary).Value = image;
It looks like this stored in the database, so I guess all seems to work like expected.
Unfortunately I am unable to load the images back from the datatable.
I am using a SqlDataReader to do so:
DbSql db = new DbSql();
SqlDataReader dr = db.GetDataReader(sqlCmd);
if (dr.Read())
{
if (!dr.IsDBNull(1))
productName = dr.GetString(1);
if (!dr.IsDBNull(2))
identNumber = dr.GetString(2);
[...]
if (!dr.IsDBNull(23))
comment = dr.GetString(23);
if (!dr.IsDBNull(24))
{
byte[] image = dr.GetSqlBytes(24).Value; // <- This is where I try to grab the image
}
}
It seems like I am not able to create a proper byte[] with
image = dr.GetSqlBytes(24).Value;
because my next step is not able to turn it into an image again:
public Image ConvertImageFromByteArray(byte[] array)
{
try
{
MemoryStream ms = new MemoryStream(array);
return Image.FromStream(ms);
}
catch (Exception) { throw; }
}
EDIT:
When trying something like
pictureBox.Image = ConvertImageFromByteArray(image)
I get an error saying "Invalid parameter" (self translated, saying "Ungültiger Parameter" in german)
Anyone able to offer a solution?
Once you cast your varbinary(MAX) to a byte array
image = (byte[])dr[24];
Try this..
MemoryStream ms = new MemoryStream(image);
imagePictureBox.Image = System.Drawing.Image.FromStream(ms);
This is how I create the byte array...
if (File.Exists(sLogoName) == false)
throw new Exception("File Not Found: " + sLogoName);
FileStream sourceStream = new FileStream(sLogoName, FileMode.Open, FileAccess.Read);
int streamLength = (int)sourceStream.Length;
Byte[] byLogo = new Byte[streamLength];
sourceStream.Read(byLogo, 0, streamLength);
sourceStream.Close();

Save image over existing image

I am working on a C# application wherein the first thing I want to do is to rotate images based upon the metadata in the file. This part works just fine. But saving the image over top of the existing image is where I'm having trouble. I delete the original file, close the stream and try to save the image as the name of the original image but it's not working. I get the following exception:
'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dllAdditional information: A generic error occurred in GDI+.
This is the code I'm using. Its a little different than what my working version was so forgive me if I missed something. In my original version I just saved the
using (FileStream fs = new FileStream(item, FileMode.Open)) {
im = Image.FromStream(fs);
sourceFormat = im.RawFormat;
// Get the image orientation from the image metadata
PropertyItem pi = im.GetPropertyItem(274);
int orientation = pi.Value[0];
switch (orientation) {
// TODO: Set rotation and flips for all orientations
// case 1 - 5 & 7 removed for clarity
// break;
case 6:
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Transformation, (long)EncoderValue.TransformRotate90);
edited = true;
pi.Value[0] = 1;
im.SetPropertyItem(pi);
fs.Close();
File.Delete(item);
im.Save(item, GetEncoder(sourceFormat), encoderParameters);
break;
case 8:
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Transformation, (long)EncoderValue.TransformRotate270);
pi.Value[0] = 1;
im.SetPropertyItem(pi);
fs.Close();
File.Delete(item);
im.Save(item, GetEncoder(sourceFormat), encoderParameters);
break;
}
}
im.Dispose();
if (encoderParameters != null)
encoderParameters.Dispose();
}
I modified your code to test this solution (proof only, not reworking your implementation)
encoderParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Transformation, (long)System.Drawing.Imaging.EncoderValue.TransformRotate90);
//edited = true;
pi.Value[0] = 1;
im.SetPropertyItem(pi);
// Added new memorystream
System.IO.MemoryStream ms = new MemoryStream();
// Read into memorystream
im.Save(ms, GetEncoder(sourceFormat), encoderParameters);
fs.Close();
File.Delete(item);
// Read from memorystream into byte array
byte[] ni = ms.ToArray();
// Save out using new filestream.
using (FileStream nfs = new FileStream(item, FileMode.Create, FileAccess.ReadWrite)){
nfs.Write(ni, 0, ni.Length);
}
//im.Save(item, GetEncoder(sourceFormat), encoderParameters);
Try to set the filestream to ReadWrite. Also, try not to Dispoose. I believe that is your main problem. Also, do not close fs till you are finished with it. I suggest you close fs and the image after you are done using it. Maybe at the end of the function.

Loading image into panel from database

My application saves image data in database and when loading information into form, it loads image into panel. This is working fine. But in case if user doesn't want to save image, I've inserted '0' in image field (varbinary) in database. While loading this information (0x00000000) from database it throws the following exception:
"Parameter is not valid."
Here I am giving some pieces of code:
Saving image in database:
if(user has selected an image)
{
Byte[] imageBytes = File.ReadAllBytes(imagePatient);
sqlCommand.Parameters.AddWithValue("Img", imageBytes); //Img is database column for images
}
else
{
sqlCommand.Parameters.AddWithValue("Img", 0);
}
Loading image from database:
Byte[] imageData = new Byte[0];
imageData = (Byte[])(dataSet.Tables["Patients"].Rows[0]["Img"]);
MemoryStream stream = new MemoryStream(imageData);
panelImage.BackgroundImage = Image.FromStream(stream);
I've tried to put some check which will allow to load BackgroundImage if and only if data is not of the zeros form.
Please tell me how can I solve this issue?
I would store a NULL instead of 0.
if(user has selected an image)
{
Byte[] imageBytes = File.ReadAllBytes(imagePatient);
sqlCommand.Parameters.AddWithValue("Img", imageBytes); //Img is database column for images
}
else
{
sqlCommand.Parameters.Add("Img", SqlDbType.VarBinary, -1 );
sqlCommand.Parameters["Img"].Value = DbNull.Value;
}
And then use an if statement to check if it's non-null:
Byte[] imageData = new Byte[0];
imageData = (Byte[])(dataSet.Tables["Patients"].Rows[0]["Img"]);
if(imageData != null)
{
MemoryStream stream = new MemoryStream(imageData);
panelImage.BackgroundImage = Image.FromStream(stream);
}
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparametercollection.addwithvalue.aspx

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