Error with conversion codes from object to image [duplicate] - c#

Why am I getting the exception "Parameter not valid" in my code:
MemoryStream ms = new MemoryStream(byteArrayIn);
System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);
The length of byteArrayIn is 169014. I am getting this exception despite the fact that no value in it is greater than 255.

I had the same problem and apparently is solved now, despite this and some other gdi+ exceptions are very misleading, I found that actually the problem was that the parameter being sent to a Bitmap constructor was not valid. I have this code:
using (System.IO.FileStream fs = new System.IO.FileStream(inputImage, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite))
{
try
{
using (Bitmap bitmap = (Bitmap)Image.FromStream(fs, true, false))
{
try
{
bitmap.Save(OutputImage + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp);
GC.Collect();
}
catch (Exception ex)
{
throw ex;
}
}
}
catch (ArgumentException aex)
{
throw new Exception("The file received from the Map Server is not a valid jpeg image", aex);
}
}
The following line was causing an error:
Bitmap bitmap = (Bitmap)Image.FromStream(fs, true, false)
The file stream was built from the file downloaded from the Map Server. My app was sending the request incorrectly to get the image, and the server was returning something with the jpg extension, but was actually a html telling me that an error ocurred. So I was taking that image and trying to build a Bitmap with it.
The fix was to control/ validate the image for a valid jpeg image.
Hope it helps!

My guess is that byteArrayIn doesn't contain valid image data.
Please give more information though:
Which line of code is throwing an exception?
What's the message?
Where did you get byteArrayIn from, and are you sure it should contain a valid image?

byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}
ImageConverter imageConverter = new System.Drawing.ImageConverter();
System.Drawing.Image image = imageConverter.ConvertFrom(fileData) as System.Drawing.Image;
image.Save(imageFullPath, System.Drawing.Imaging.ImageFormat.Jpeg);

The "parameter is not valid" exception thrown by Image.FromStream() tells you that the stream is not a 'valid' or 'recognised' format. Watch the memory streams, especially if you are taking various offsets of bytes from a file.
// 1. Create a junk memory stream, pass it to Image.FromStream and
// get the "parameter is not valid":
MemoryStream ms = new MemoryStream(new Byte[] {0x00, 0x01, 0x02});
System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);`
// 2. Create a junk memory stream, pass it to Image.FromStream
// without verification:
MemoryStream ms = new MemoryStream(new Byte[] {0x00, 0x01, 0x02});
System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms, false, true);
Example 2 will work, note that useEmbeddedColorManagement must be false for validateImageData to be valid.
May be easiest to debug by dumping the memory stream to a file and inspecting the content.

Which line is throwing the exception? The new MemoryStream(...)? or the Image.FromStream(...)? And what is the byteArrayIn? Is it a byte[]? I only ask because of the comment "And none of value in it is not greater than 255" - which of course is automatic for a byte[].
As a more obvious question: does the binary actually contain an image in a sensible format?
For example, the following (although not great code) works fine:
byte[] data = File.ReadAllBytes(#"d:\extn.png"); // not a good idea...
MemoryStream ms = new MemoryStream(data);
Image img = Image.FromStream(ms);
Console.WriteLine(img.Width);
Console.WriteLine(img.Height);

This error is caused by binary data being inserted into a buffer.
To solve this problem, you should insert one statement in your code.
This statement is:
obj_FileStream.Read(Img, 0, Convert.ToInt32(obj_FileStream.Length));
Example:
FileStream obj_FileStream = new FileStream(str_ImagePath, FileMode.OpenOrCreate, FileAccess.Read);
Byte[] Img = new Byte[obj_FileStream.Length];
obj_FileStream.Read(Img, 0, Convert.ToInt32(obj_FileStream.Length));
dt_NewsFeedByRow.Rows[0][6] = Img;

all the solutions given doesnt work.. dont concentrate only on the retrieving part. luk at the inserting of the image. i did the same mistake. I tuk an image from hard disk and saved it to database. The problem lies in the insert command. luk at my fault code..:
public bool convertImage()
{
try
{
MemoryStream ms = new MemoryStream();
pictureBox1.Image.Save(ms, ImageFormat.Jpeg);
photo = new byte[ms.Length];
ms.Position = 0;
ms.Read(photo, 0, photo.Length);
return true;
}
catch
{
MessageBox.Show("image can not be converted");
return false;
}
}
public void insertImage()
{
// SqlConnection con = new SqlConnection();
try
{
cs.Close();
cs.Open();
da.UpdateCommand = new SqlCommand("UPDATE All_students SET disco = " +photo+" WHERE Reg_no = '" + Convert.ToString(textBox1.Text)+ "'", cs);
da.UpdateCommand.ExecuteNonQuery();
cs.Close();
cs.Open();
int i = da.UpdateCommand.ExecuteNonQuery();
if (i > 0)
{
MessageBox.Show("Successfully Inserted...");
}
}
catch
{
MessageBox.Show("Error in Connection");
}
cs.Close();
}
The above code shows succesfully inserted... but actualy its saving the image in the form of wrong datatype.. whereas the datatype must bt "image".. so i improved the code..
public bool convertImage()
{
try
{
MemoryStream ms = new MemoryStream();
pictureBox1.Image.Save(ms, ImageFormat.Jpeg);
photo = new byte[ms.Length];
ms.Position = 0;
ms.Read(photo, 0, photo.Length);
return true;
}
catch
{
MessageBox.Show("image can not be converted");
return false;
}
}
public void insertImage()
{
// SqlConnection con = new SqlConnection();
try
{
cs.Close();
cs.Open();
//THIS WHERE THE CODE MUST BE CHANGED>>>>>>>>>>>>>>
da.UpdateCommand = new SqlCommand("UPDATE All_students SET disco = #img WHERE Reg_no = '" + Convert.ToString(textBox1.Text)+ "'", cs);
da.UpdateCommand.Parameters.Add("#img", SqlDbType.Image);//CHANGED TO IMAGE DATATYPE...
da.UpdateCommand.Parameters["#img"].Value = photo;
da.UpdateCommand.ExecuteNonQuery();
cs.Close();
cs.Open();
int i = da.UpdateCommand.ExecuteNonQuery();
if (i > 0)
{
MessageBox.Show("Successfully Inserted...");
}
}
catch
{
MessageBox.Show("Error in Connection");
}
cs.Close();
}
100% gurantee that there will be no PARAMETER NOT VALID error in retrieving....SOLVED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Most of the time when this happens it is bad data in the SQL column. This is the proper way to insert into an image column:
INSERT INTO [TableX] (ImgColumn) VALUES (
(SELECT * FROM OPENROWSET(BULK N'C:\....\Picture 010.png', SINGLE_BLOB) as tempimg))
Most people do it incorrectly this way:
INSERT INTO [TableX] (ImgColumn) VALUES ('C:\....\Picture 010.png'))

Just Follow this to Insert values into database
//Connection String
con.Open();
sqlQuery = "INSERT INTO [dbo].[Client] ([Client_ID],[Client_Name],[Phone],[Address],[Image]) VALUES('" + txtClientID.Text + "','" + txtClientName.Text + "','" + txtPhoneno.Text + "','" + txtaddress.Text + "',#image)";
cmd = new SqlCommand(sqlQuery, con);
cmd.Parameters.Add("#image", SqlDbType.Image);
cmd.Parameters["#image"].Value = img;
//img is a byte object
** /*MemoryStream ms = new MemoryStream();
pictureBox1.Image.Save(ms,pictureBox1.Image.RawFormat);
byte[] img = ms.ToArray();*/**
cmd.ExecuteNonQuery();
con.Close();

Related

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();

Invalid Parameter error while retrieving image from database using memory stream

I am working on a Window Form application in C# using VS2012. I am getting error in the below code:
if (dt.Rows[0]["Photo"] != System.DBNull.Value) //Retrieve image into PictureBox from database
{
photo_aray = (byte[])dt.Rows[0]["Photo"]; //where photo_aray is byte[] photo_aray;
MemoryStream ms = new MemoryStream(photo_aray);
ms.Seek(0, SeekOrigin.Begin);
Pic.Image = Image.FromStream(ms); //Where Pic is the pictureBox(Error is getting in this line of "Invalid Parameter")
}
I used below code to convert image into byte code and save into "Photo" column of database of image datatype:
if (Pic.Image != null)
{
ms = new MemoryStream();
Pic.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] photo_aray = new byte[ms.Length];
ms.Position = 0;
ms.Read(photo_aray, 0, photo_aray.Length);
}
sqlcommand cmd = new sqlcommand("INSERT into tbData (Photo) VALUES (photo_aray)",con);
cmd.ExecuteNonQuery();
Please help if anyone knows. Thank You

Reading Image from SQL Error in C#

I have a SQLite DB I have field called PersonalPic of Type BLOB
this is code in which I save image to SQLite
cm.CommandText = "insert into People(Name,FullName,FatherName,MotherName,NationalID,Mobile,Phone,Birth,Intma,Info,Address,CuAddress,PersonalPic,Pics) values('"+textBox1.Text+"','"+textBox2.Text+"','"+textBox3.Text+"','"+textBox4.Text+"','"+textBox5.Text+"','"+textBox6.Text+"','"+textBox7.Text+"','"+dateTimePicker1.Value.ToString("yyyy-MM-dd")+"','"+textBox8.Text+"','"+textBox9.Text+"','"+textBox10.Text+"','"+textBox11.Text+"','"+ConvertToString(personalpic)+"','"+ConvertToString(pic)+"')";
cm.ExecuteNonQuery();
public string ConvertToString(String path)
{
FileStream fs = new FileStream(path,
FileMode.OpenOrCreate, FileAccess.Read);
byte[] rawData = new byte[fs.Length];
fs.Read(rawData, 0, System.Convert.ToInt32(fs.Length));
fs.Close();
// Convert byte[] to Base64 String
string base64String = Convert.ToBase64String(rawData);
return base64String;
}
It`s saved without no problems when I try to retrieve image it gives me Parameter is no valid Exception
SQLiteDataReader reader = cm.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
textBox1.Text = reader["Name"].ToString();
textBox2.Text = reader["FullName"].ToString();
textBox3.Text = reader["FatherName"].ToString();
textBox4.Text = reader["MotherName"].ToString();
textBox5.Text = reader["NationalID"].ToString();
textBox6.Text = reader["Mobile"].ToString();
textBox7.Text = reader["Phone"].ToString();
dateTimePicker1.Value = DateTime.Parse(reader["Birth"].ToString());
textBox8.Text = reader["Intma"].ToString();
textBox9.Text = reader["Info"].ToString();
byte[] photoarray = (byte[])reader["PersonalPic"];
MemoryStream ms = new MemoryStream(photoarray);
MessageBox.Show(photoarray.Length.ToString());
ms.Position = 0;
pictureBox1.Image = Image.FromStream(ms);
}
}
reader.Close();
Exception is in the Line (pictureBox1.Image = Image.FromStream(ms))
Please Help!!
Aside from the horrendous sql inject insert statement, you're converting your picture byte array to a B64 string. And you're not converting it back on the other side. You're passing complete garbage data to your pictureBox. Either convert it back from byte[] -> B64 string and then decode it back to a byte[].. or just don't save it as a B64 string in the first place
Replace ConvertToString with ConvertToBlob
public byte[] ConvertToBlob(String path)
{
FileStream fs = new FileStream(path,
FileMode.OpenOrCreate, FileAccess.Read);
byte[] rawData = new byte[fs.Length];
fs.Read(rawData, 0, System.Convert.ToInt32(fs.Length));
fs.Close();
return rawData;
}
And pass the raw data Byte[] directly to your SQL Query (which you need to rewrite as a parameterised query).

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);

Retrieve Images from sql server database

i am storing images to the database. How to retrieve all the images from the database.
Eg: select images from imagetable
Problem:
Data Logic:
while (dr.Read())
{
///Check for null
if (!dr.IsDBNull(0))
{
try
{
///Converting the image into bitmap
byte[] photo = (byte[])dr[0];
ms = new MemoryStream(photo);
Bitmap bm = new Bitmap(ms);
bmp[i] = bm;
ms.Close();
}
catch (Exception ex)
{
}
}
ASpx.CS page:
Bitmap[] bm= photos.GetImage();
for (int i = 0; i < bm.Length; i++)
{
MemoryStream ms = new MemoryStream();
**bm[i].Save(ms, ImageFormat.Jpeg);**(Error : A generic error occurred in GDI+.)
htmlCode.Append("<li><img ImageUrl=\\\"");
htmlCode.Append(**ms.GetBuffer()**);
htmlCode.Append("\" alt=\"\" width=\"100\" height=\"100\"></li>");
}
Image not getting displayed
Geetha
this is an example from Sql Server
connection.Open();
SqlCommand command1 = new SqlCommand("select imgfile from myimages where imgname=#param", connection);
SqlParameter myparam = command1.Parameters.Add("#param", SqlDbType.NVarChar, 30);
myparam.Value = txtimgname.Text;
byte[] img = (byte[])command1.ExecuteScalar();
MemoryStream str = new MemoryStream();
str.Write(img, 0, img.Length);
Bitmap bit = new Bitmap(str);
connection.Close();
look here
http://www.akadia.com/services/dotnet_read_write_blob.html
For SQL Server 2008 onwards, FILESTREAM is almost certainly the way to go.
Please see: SQL Server 2005 - How do I convert image data type to character format
You need to get the binary data from the DB, and then stream the binary data to the browser as image.
You are setting the Url of the image to be the byte stream - you need to save the image to the hard drive and provide the location.
A much better way would be to set the image url to be a resource handler with parameters that could then retrieve the image from the database and return it as a stream to the browser.

Categories