How to convert BLOB to Image - c#

I have a problem in displaying the picture which is stored in my MySQL database.
I don't know if I have stored it successfully but using this function which converts image to a blob file, here is the function:
private byte[] imageToByteArray(Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
When I check my database, it says BLOB with blue highlight. Now, I would like to display the image in my picturebox. I have also a function to convert byte array to image..
private Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
ms.Position = 0;
Image returnImage = Image.FromStream(ms);
return returnImage;
}
When I run the application, it says:
ArgumentException was unheld, Parameter is not valid
I have tried using this syntax:
pictureBox1.Image = byteArrayToImage(dr["img"] as byte[]);
Or I'm thinking if I should convert BLOB to Byte Array first? then use the function to convert the byte array into Image?
when I click the name, it should display the information, unfortunately, I'm receiving the argument exception..
int i = dataGridView1.SelectedCells[0].RowIndex;
string firstname = dataGridView1.Rows[i].Cells[0].Value.ToString();
string lastname = dataGridView1.Rows[i].Cells[1].Value.ToString();
Connection connect = new Connection();
MySqlConnection mySqlConnect = new MySqlConnection(connect.connString());
mySqlConnect.Open();
string s = "SELECT * FROM tbl_contacts WHERE username = '" + label1.Text + "' and (fname = '" + firstname + "' and lname = '" + lastname + "')";
MySqlCommand mySQL = new MySqlCommand(s, mySqlConnect);
mySQL.ExecuteNonQuery();
MySqlDataReader dr = mySQL.ExecuteReader();
if (dr.HasRows)
{
dr.Read();
txtFname.Text = dr["fname"].ToString();
txtLname.Text = dr["lname"].ToString();
txtBday.Text = dr["birthday"].ToString();
txtEmail.Text = dr["email"].ToString();
txtMobile.Text = dr["mobile"].ToString();
txtAddress.Text = dr["address"].ToString();
txtNotes.Text = dr["notes"].ToString();
pictureBox1.Image = byteArrayToImage(dr["img"] as byte[]);
}

Try something like that :
byteArrayToImage(dr.GetSqlBytes(dr.GetOrdinal("img")).Buffer);

ArgumentException was unheld, Parameter is not valid is due to corrupt image. Your image did not save correctly. Save byte[] you have received in some file in the disk and try to rename it as .jpg or .png and try to open.
Corruption of binary data happens due to various reasons, Length of binary data wasn't saved or trimmed. If your database is configured to store 5kb someone wrote code to trim data to 5kb instead of raising exception or appending buffer wasn't coded correctly resulting in missing last few bytes.

Related

I want to save image in jpg format from SQL Server database but when I download it , it has only 1KB size and cannot be opened

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.

show image handler with resize

before now, i save 2 size of image in database, real size and thumbnail, then show each of them when i need.
in ashx handler i set which type i need, here is my code:
string field = context.Request.QueryString["field"];
string table = context.Request.QueryString["table"];
string id = context.Request.QueryString["id"];
string conn = ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString;
SqlConnection myConnection = new SqlConnection(conn);
myConnection.Open();
string sql = "";
sql = "Select " + field + ", pictureType from " + table + " where id=#imageId";
SqlCommand cmd = new SqlCommand(sql, myConnection);
cmd.Parameters.Add("#imageId", SqlDbType.Int).Value = id;
cmd.Prepare();
SqlDataReader dr = cmd.ExecuteReader();
dr.Read();
context.Response.ContentType = dr["pictureType"].ToString();
context.Response.BinaryWrite((byte[])dr[field]);
dr.Close();
myConnection.Close();
and i use this way:
<img src="handlers/ShowPic.ashx?table=tblEnBackGrounds&field=image&id=1" alt="s" />
but now i decide to save just real size image, then in ashx file re size and show proper type(here real or thumbnail).
now i need first to now is it good or not? second i don't have any idea how to re size binary data before show in ashx handler
Use the great Image Resize lib http://imageresizing.net/.
You need to resize images proportionally and keep their aspect ratio. Using the Image resize lib, something like this could be the function to do the job:
public static byte[] resizeProportionaly(byte[] imageFile, int pWidth, int pHeight, string crop = "&crop=auto")
{
MemoryStream stream = new MemoryStream(imageFile);
stream.Seek(0, SeekOrigin.Begin);
ResizeSettings resizeCropSettings = new ResizeSettings(string.Format("bgcolor=FFFFFF&width={0}&height={1}&format=jpg" + crop, pWidth, pHeight));
Image originalImage = Image.FromStream(stream, true, false);
Image resizedImage = ImageBuilder.Current.Build(originalImage, resizeCropSettings);
MemoryStream ms = new MemoryStream();
resizedImage.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.ToArray();
}
and in your handler something like this:
public void ProcessRequest (HttpContext context) {
// some init code...take care of your query strings here etc.
string cropString = "x1,y1,x2,y2"; // if you need croping?
// change height and width based on your picture type
int outWidth = 640; // whatever you need here
int outHeight = 480;
System.Data.DataRow data = GetDBPhotoRecord(photoId);
byte[] photoStream = (byte[])data[mxmPhotos.Photo];
// if you dont need cropping just remove the last cropString parameter
byte[] outStream = resizeProportionaly(photoStream, outWidth, outHeight, cropString);
// ...
context.Response.Buffer = true;
context.Response.Clear();
context.Response.ContentType = "image/jpeg";
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(7));
context.Response.BinaryWrite(outStream);
}

Retrieving image from database not showing up on page

I have been able to upload an image to sql server, in binary format. This is the code that I am using to upload it..
protected void Button2_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
string filename = FileUpload1.FileName;
Stream imgStream = FileUpload1.PostedFile.InputStream;
int imgLen = FileUpload1.PostedFile.ContentLength;
byte[] imgBinaryData = new byte[imgLen];
string strCm = "s_PictInsert";
SqlCommand cm = new SqlCommand(strCm, Cn);
cm.CommandType = CommandType.StoredProcedure;
cm.Parameters.Add(new SqlParameter("#TheImage", SqlDbType.Image)).Value = imgBinaryData;
Cn.Open();
cm.ExecuteNonQuery();
Cn.Close();
}
}
When I look at the database, all I see in the database, of the pic I uploaded, is 0x00000000000000 etc...I don't know why it looks like that...
Then I am using this code to retrieve the image..
protected void Button3_Click(object sender, EventArgs e)
{
string strCm = "select TheImage from [Pictures] where PictureID = 2";
SqlCommand cm = new SqlCommand(strCm, Cn);
cm.CommandType = CommandType.Text;
Cn.Open();
SqlDataReader dr = cm.ExecuteReader();
if (dr.Read())
{
Response.ContentType = "image/jpg";
Response.BinaryWrite((byte[])dr["TheImage"]);
}
Cn.Close();
}
when I click the button it doesn't show me the image it just writes the markup out to the page.
What I want to do is retrieve the image and put it to an asp image, the thing is the images that I upload can be .png format.
I only used response.binarywrite is because that is what I was shown to do. But it doesn't work the way I was told it would.
Thanks
The problem is with your upload function, you are not setting imgBinaryData with the data from the file stream, you are only settings the size to match, so it will default to all zeros.
Instead of this part:
byte[] imgBinaryData = new byte[imgLen];
Replace it with this:
byte[] imgBinaryData = null;
using (var reader = new BinaryReader(FileUpload1.PostedFile.InputStream))
{
imgBinaryData = reader.ReadBytes(FileUpload1.PostedFile.ContentLength);
}
Then check to see what your database data looks like.
On a side note, I would recommend always storing file name and MIME type when storing files in a database, you never know when you will need them!
try this:
var length = FileUpload1.PostedFile.ContentLength;
Byte[] imgBinaryData = new Byte[length];
var stream = FileUpload1.FileContent;
stream.Read(imgBinaryData, 0, length);
then insert the binary object. Your code does not read the image into the stream for insertion. The above code should read the image into the byte array, then your db code should insert actual data instead of the placeholder.
You are storing image in binary format to the database, you will retrieve the same. You need to use MemoryStream to get the image from the byte array that you retrieved.
See this :
Retrieve image from database and display on ASP.NET without httphandler

store a blob string in database table

Hi I'm new to azure storage blob. I have a project in WPF and I have created a container in azure storage blob that I can send /upload images to on button click. Can anyone tell me if I can store a string form the blob into my sql database that will allow me to access/use/display the image in my WPF project.
Maybe someone could direct me to an example! Thanks!
private void btnSAVE_Click(object sender, RoutedEventArgs e)
{
try
{
byte[] photo = GetPhoto(filePath);
sc.Open();
cmd = new SqlCommand("Insert into Rewards (Name, Picture, ) values'" + txtName.Text+ "','" + txtPicture.Text + "')", sc);
cmd.Parameters.Add("#Picture", SqlDbType.Image, photo.Length).Value = photo;
cmd.ExecuteNonQuery();
MessageBox.Show("Inserted");
sc.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
displayAll();
}
private byte[] GetPhoto(string filePath) {
{
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
byte[] photo = br.ReadBytes((int)fs.Length);
br.Close();
fs.Close();
return photo;
}
}
You can just store URL of that blob and use that URL to display image
CloudBlockBlob blockBlob = new CloudBlockBlob();
using (var fileStream = System.IO.File.OpenRead(path + "/" + up.GetName().ToString()))
{
blockBlob.UploadFromStream(fileStream);
}
string URL = blockBlob.Uri.OriginalString;
Refer to this link Writing BLOB values to a database.
From MSDN:
To write a BLOB value to your database, issue the appropriate INSERT
or UPDATE statement and pass the BLOB value as an input parameter. If
your BLOB is stored as text, such as a SQL Server text field, you can
pass the BLOB as a string parameter. If the BLOB is stored in binary
format, such as a SQL Server image field, you can pass an array of
type byte as a binary parameter.

Saving and retrieving image in SQL database from C# problem

I used this code for inserting records in a person table in my DB
System.IO.MemoryStream ms = new System.IO.MemoryStream();
Image img = Image_Box.Image;
img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
this.personTableAdapter1.Insert(NIC_Box.Text.Trim(), Application_Box.Text.Trim(), Name_Box.Text.Trim(), Father_Name_Box.Text.Trim(), DOB_TimePicker.Value.Date, Address_Box.Text.Trim(), City_Box.Text.Trim(), Country_Box.Text.Trim(), ms.GetBuffer());
but when i retrieve this with this code
byte[] image = (byte[])Person_On_Application.Rows[0][8];
MemoryStream Stream = new MemoryStream();
Stream.Write(image, 0, image.Length);
Bitmap Display_Picture = new Bitmap(Stream);
Image_Box.Image = Display_Picture;
it works perfectly fine but if i update this with my own generated Query like
System.IO.MemoryStream ms = new System.IO.MemoryStream();
Image img = Image_Box.Image;
img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
Query = "UPDATE Person SET Person_Image ='"+ms.GetBuffer()+"' WHERE (Person_NIC = '"+NIC_Box.Text.Trim()+"')";
the next time i use the same code for retrieving the image and displaying it as used above . Program throws an exception
alt text http://www.freeimagehosting.net/image.php?3bb5f0d4b3.jpg][img]http://www.freeimagehosting.net/uploads/th.3bb5f0d4b3.jpg
So can any one tell me why i can't figure it out.
Query = "UPDATE Person SET Person_Image =#pic WHERE (Person_NIC = '" + NIC_Box.Text.Trim() + "')";
SqlCommand cmd = new SqlCommand(Query);
SqlParameter picparameter = new SqlParameter();
picparameter.SqlDbType = SqlDbType.Image;
picparameter.ParameterName = "pic";
picparameter.Value = ms.GetBuffer();
cmd.Parameters.Add(picparameter);
db.ExecuteSQL(Query);
This thing worked with this code hurray lolz

Categories

Resources