This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
“Parameter not valid” exception loading System.Drawing.Image
I am inserting a image in the DB.
Here's my code
public class ImageUtils
{
const int sizeThumb = 69;
public static int uploadImage(int memberid, Image thumbimage)
{
MemoryStream stream = new MemoryStream();
thumbimage.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
Byte[] thumbbytes = stream.ToArray();
//int length = Convert.ToInt32(data.Length);
//byte[] thumbimage = new byte[length];
//data.Read(thumbimage, 0, length);
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["FMMImages"].ConnectionString);
SqlCommand command = new SqlCommand("update Images_temp set thumbimage = #thumbimage where memberid=#memberid", connection);
SqlParameter param0 = new SqlParameter("#thumbimage", SqlDbType.Image);
param0.Value = thumbbytes;
command.Parameters.Add(param0);
connection.Open();
object result = command.ExecuteScalar();
connection.Close();
if (result != null)
{
return System.Convert.ToInt32(result);
}
else
{
return 0;
}
}
aspx.cs where I'm calling the uploadimage
image CroppedWaterMarkImage
......
ImageUtils.uploadImage(memberid, CroppedWaterMarkImage);
Error in the uploadimage function:
MemoryStream stream = new MemoryStream();
thumbimage.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
Byte[] thumbbytes = stream.ToArray();
System.ArgumentException: Parameter is not valid.
Thanks
Sun
These guys encountered a similar problem with Images and MemoryStream() because of a memory leak:
http://blog.lavablast.com/post/2007/11/29/The-Mysterious-Parameter-Is-Not-Valid-Exception.aspx
This link was resolved by calling System.Drawing.Bitmap instead of System.Drawing.Image:
http://forums.asp.net/t/1705636.aspx/1
http://msdn.microsoft.com/en-us/library/ms524632%28v=vs.90%29.aspx
Either (memory leak/corruption and/or choice of API) could be applicable to your scenario.
Also make sure the image file is valid.
Related
I'm facing an issue when trying to select an image field from the SQL server.
Here's the select code:
string cmd = String.Format("SELECT TOP 1 * FROM {0}", DefTableNames.Employees.ToString());
DataTable data = SQLDataQueryToTable(FullServerPath(), cmd);
CurrentEditingIndex = int.Parse(data.Rows[0][0].ToString());
empNameDropDown.SelectedItem = empNameDropDown.Items[0];
empNameTxt.Texts = data.Rows[0][1].ToString();
empIdTxt.Texts = data.Rows[0][2].ToString();
empPhoneTxt.Texts = data.Rows[0][3].ToString();
empEducationTxt.Texts = data.Rows[0][4].ToString();
empJobNameTxt.Texts = data.Rows[0][5].ToString();
TextTools.Currencize(data.Rows[0][6].ToString(), empTotalAllTxt);
empAboutTxt.Texts = data.Rows[0][7].ToString();
empBirthDatePicker.Value = DateTime.Parse(data.Rows[0][8].ToString(), CultureInfo.InvariantCulture);
empJobDatePicker.Value = DateTime.Parse(data.Rows[0][9].ToString(), CultureInfo.InvariantCulture);
Console.WriteLine(data.Rows[0][10]);
image_employeeimage.Image = byteArrayToImage((byte[])data.Rows[0][10], null);
if (image_employeeimage.Image != null)
{
buttonDeleteImage.Enabled = true;
buttonDeleteImage.BackColor = Color.Brown;
}
else
{
buttonDeleteImage.Enabled = false;
buttonDeleteImage.BackColor = AColors.DisabledColor;
}
empUserDropDown.SelectedItem = data.Rows[0][11].ToString();
The code fills everything in properly, however, it keeps stopping at the method for conversion of the data to an image.
Here's the conversion code:
public static Image byteArrayToImage(byte[] byteArrayIn, Image defaultImage = null)
{
if (byteArrayIn == null)
{
return defaultImage;
}
Image returnImage;
using (MemoryStream ms = new MemoryStream(byteArrayIn))
{
returnImage = Image.FromStream(ms);
}
return returnImage;
}
The code stops exactly at here:
Here's the code that converts to byte[]:
public static byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
When I try to do a Console.WriteLine for the value of the image, I get the proper value. Which is System.Byte[].
The type of column in the database is set to VarBinary.
What exactly am I doing wrong?
I found my problem. The issue was pretty dumb:
public static byte[] imageToByteArray(Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
I was saving the image as a gif. Which when I changed to this:
public static byte[] imageToByteArray(Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, imageIn.RawFormat);
return ms.ToArray();
}
Fixed the entire issue.
And I also found a big problem in the save code. I was defining the size of the data as 255. This also led to the images not loading at times or loading as null. This was in the original code that I didn't share:
if(image_employeeimage.Image == null)
{
sqlParams.Add(new SqlParameter("#image", SqlDbType.VarBinary, 255)); sqlParams[9].Value = DBNull.Value;
}
else
{
sqlParams.Add(new SqlParameter("#image", SqlDbType.VarBinary, 255)); sqlParams[9].Value = imageToByteArray(image_employeeimage.Image);
}
I simply removed 255.
Everything seems fine now. Thanks a lot for the help everyone, and thanks for the tips on my code.
If there are any comments on my fix, please share them.
private void Msg1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
string SaveFileTo = "D:\\DA.jpg";
// string SaveFileTo = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
// string filename = "jmk.jpg";
// SaveFileTo = Path.Combine(SaveFileTo, filename);
CN.Open();
SqlCommand cmd = new SqlCommand("select photo from edistindata where enrollno='" + CboEnroll.Text + "' ", CN);
DR = cmd.ExecuteReader();
byte[] data = null;
while (DR.Read())
{
data = (byte[])DR["Photo"];
}
using (var fs = new FileStream(SaveFileTo, FileMode.Create, FileAccess.Write))
{
fs.Write(data,0,data.Length);
}
MessageBox.Show("Success");
}
I have run the code in the question, even it has some of not good coding practices, if the data in the photo column is not corrupted it should produce the image file.
so I have put down your code with proper enhancements that will flag you early before saving corrupted data.
private void Msg1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
ImageCodecInfo theJpgCodecInfo = ImageCodecInfo.GetImageEncoders()
.FirstOrDefault(encoder => encoder.MimeType == "image/jpeg");
var myEncoder = Encoder.Quality;
var myEncoderPrams = new EncoderParameters(1);
myEncoderPrams.Param[0] = new EncoderParameter(myEncoder, 100L);
string SaveFileTo = "D:\\DA";
// string SaveFileTo = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
// string filename = "jmk.jpg";
// SaveFileTo = Path.Combine(SaveFileTo, filename);
CN.Open();
SqlCommand cmd = new SqlCommand("select photo from edistindata where
enrollno=#Enrol;", CN);
cmd.Parameters.AddWithValue("#Enrol", CboEnroll.SelectedItem.ToString());
DR = cmd.ExecuteReader();
byte[] data = null;
int idx = 0;
while (DR.Read())
{
data = (byte[])DR["Photo"];
Image tempImage;
try
{
tempImage = ByteArrayToImage(data);
}
catch (Exception exc)
{
MessageBox.Show(exc.GetType().ToString()
+Environment.NewLine+exc.Message);
continue;
}
var tempBitmap = new Bitmap(tempImage);
var tempFname = "D:\\DA"+(idx++).ToString()+".jpg";
tempBitmap.Save(tempFname, theJpgCodecInfo, myEncoderPrams);
}
}
public static Image ByteArrayToImage(byte[] byteArrayIn)
{
using (MemoryStream ms = new MemoryStream(byteArrayIn))
{
Image returnImage = Image.FromStream(ms);
return returnImage;
}
}
The enhancements that I suggested as follow:
As #derpirscher mentioned in his comment use parameters not string concatenation when building SQL commands and the easiest most lazy way to do it is Parameters.AddWithValue().
Use CboBox.SelectedItem.ToString in place of the .Text as been in your code.
instead of dumping the byte[] directly through a FileStream.Write() I transferred the byte array into Image() then into Bitmap().
this way if the byte[] (and hence the data in the db column photo) is not one of the binary formats the the class Image() can handle it will throw exception and I used that to show the related error.
Also, this way we over came some issues that may rise if we used Bitmap() directly if the data byte[] contains PNG format.
No matter what image format is stored in the photo column it will be legitimately re-encoded as Jpeg then saved.
I know this question has been asked many times, but my problem is not being solved.
I inserted image to database and data type of my field is image. But I am trying to display the image in picture box this exception occurs.
Parameter is not valid.
Here is my code:
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
byte[] Img = (byte[])dr["imgImage"];
MemoryStream MS = new MemoryStream(Img);
MS.Seek(0, SeekOrigin.Begin);
//System.Drawing.ImageConverter converter = new System.Drawing.ImageConverter();
//System.Drawing.Image img = (System.Drawing.Image)converter.ConvertFrom(Img);
pictureBox1.Image = Image.FromStream(MS);
}
i guess it works.
PCT.Image= Image.FromStream(ms);
is that works?
edit1:
////sql connection codes here
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
byte[] picture = (byte[])dr[0];
MemoryStream ms = new MemoryStream(picture, 0, picture.Length);
ms.Write(picture, 0, picture.Length);
RegPicture = Image.FromStream(ms, true);
pictureBox1.Image = RegPicture;
}
////sql connection codes here
I looked around everywhere and we stucked (Since 2 days we are googleing, so pls dont "lmgty"). We want to Convert an image to byte[], in c#.NET, found this method:
public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.ToArray();
}
It says:
Thrown: "Cannot access a closed Stream." (System.ObjectDisposedException) Exception Message = "Cannot access a closed Stream.", Exception Type = "System.ObjectDisposedException"
For fixing it i tryed:
ms.Flush();
Our goal is to save the byte[] into the database. We also tried this:
var parameter = new SqlParameter("#Value", SqlDbType.Image)
{
Value = Image
};
cmd.Parameters.Add(parameter);
It says that Bitmap to Byte[] has failed.
The whole insterting command is:
private void CreateEntry()
{
var conn = new SqlConnection(ConfigurationManager.ConnectionStrings[Connectionstring].ConnectionString);
var cmd = new SqlCommand("INSERT INTO _FH_Picture ID, Value, BindItem, Owner, McItemRelated, UploadTime VALUES #ID, #Value, #BindItem, #Owner, #McItemRelated, #UploadTime", conn) { CommandType = CommandType.Text };
cmd.Parameters.AddWithValue("#ID", ID.ToString());
cmd.Parameters.AddWithValue("#Value", imageToByteArray(value));
cmd.Parameters.AddWithValue("#Owner", _owner);
cmd.Parameters.AddWithValue("#BindItem", _bindtitem);
cmd.Parameters.AddWithValue("#McItemRelated", _mcitemrelated);
cmd.Parameters.AddWithValue("#UploadTime", _uploadtime);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
I have a following problem:
I am using c# and .aspx pages. On .aspx page i have a GridView. I set a GridView datasource to be:
GridView1.DataSource = PictureInfo.PictureInfoList;
My "PictureInfo" class looks like this:
public class PictureInfo
{
public static List<PictureInfo> PictureInfoList = new List<PictureInfo>();
public string PictureDescription { get; set; }
public byte[] Picture { get; set; }
}
Is it possible and how to show a picture which is in "byte[] Picture" in a GridView? Or which way it is possible? I'm saving data in this way before i send it to a database. And i would like to show it in a GridView before i send it to a database. As you can see I'm a beginner but i would be very happy if i could make this work. My head hearts already from reading some solutions online, none helped until now.
thank you very much
I suggest you a solution for: Converting byte[] to Bitmap (may it will be useful for you):
public BitmapSource ByteArrayToBitmap(byte[] byteArray) {
BitmapSource res;
try {
using (var stream = new MemoryStream(byteArray)) {
using (var bmp = new Bitmap(stream)) {
res = ToBitmap(bmp);
}
}
} catch {
res = null;
}
return res;
}
public BitmapSource ToBitmap(Bitmap bitmap) {
using (var stream = new MemoryStream()) {
bitmap.Save(stream, ImageFormat.Bmp);
stream.Position = 0;
var result = new BitmapImage();
result.BeginInit();
result.CacheOption = BitmapCacheOption.OnLoad;
result.StreamSource = stream;
result.EndInit();
result.Freeze();
return result;
}
}
Next, you should adapt, and include the Bitmap in your GridView.
on your handler.ashx
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/jpeg";
string ImageID=request["ID"];
//byte[] ImageByte=pictureInfo.Picture;//local imageByte
byte[] ImageByte=getImage(ImageId);//image byte from any other sour,e.g database
Stream strm = new MemoryStream(ImageByte));
long length = strm.Length;
byte[] buffer = new byte[length];
int byteSeq = strm.Read(buffer, 0, 2048);
while (byteSeq > 0)
{
context.Response.OutputStream.Write(buffer, 0, byteSeq);
byteSeq = strm.Read(buffer, 0, 2048);
}
}
now set image url for your asp:image inside your gridview as follows
Image1.ImageUrl = "somthing.ashx?ID="+userImageID;
i hope you have unique id for your image to be visible. I hope you have all set now. Comments and query are well comed.
retrieve image byte from database
public byte[] GetImage(string ImageId)
{ byte[] img = null;
DataTable dt = new DataTable();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "SlikaHendler";
cmd.Parameters.AddWithValue("#Id", ImageId);
cmd.Connection = yourConnection();
SqlDataReader dr = null;
dr = cmd.ExecuteReader();
if (dr.Read())
{
img = (byte[])dr[0];
}
dr.Close();
return img;//returns array of byte
}
I know pictures are recorded as binaries to databases. In this aspect, your problem turns to a "converting binary to byte".
If you can reach your picture info as binary data, you can convert it as taking 3 digits for 1 byte, and convert & show as bytes.
http://en.wikipedia.org/wiki/ASCII