show image handler with resize - c#

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

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.

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

showing image in gridview from byte array

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

How to convert BLOB to Image

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.

NEED HELP.crop image while streaming it from IP cam

I have a monitoring system and I want to save a snapshot from a camera when alarm trigger. I have tried many methods to do that…and it’s all working fine.
string ImageName = #"E:\snapshot\pic" + imageid + ".jpg";
WebClient webclient = new WebClient();
webclient.Credentials = new NetworkCredential("admin", "pass");
Uri url = new Uri("http://" + ip + "/cgi-bin/cmd/encoder?SNAPSHOT");
webclient.DownloadFileAsync(url, ImageName);
webclient.Dispose();
the image coming from the cam is(1280*1024). i want to crop the image to get (500*500) Pixel
private void button2_Click(object sender, EventArgs e)
{
string ImageFrom = #"c:\3.jpg";
byte[] imageData = ReadFile(ImageFrom);
byte[] data = CropPicture(imageData, 500, 500);
SqlConnection cn = new SqlConnection("Data Source=.;Initial Catalog=test;Integrated Security=True");
string qry = "insert into val (id,img) values (#OriginalPath, #ImageData)";
SqlCommand SqlCom = new SqlCommand(qry, cn);
SqlCom.Parameters.Add(new SqlParameter("#OriginalPath",(object)"123"));
SqlCom.Parameters.Add(new SqlParameter("#ImageData", (object)data));
cn.Open();
SqlCom.ExecuteNonQuery();
}
byte[] ReadFile(string sPath)
{
byte[] data = null;
FileInfo fInfo = new FileInfo(sPath);
long numBytes = fInfo.Length;
FileStream fStream = new FileStream(sPath, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fStream);
data = br.ReadBytes((int)numBytes);
return data;
}
public static byte[] CropPicture(byte[] imgFile, int targetW, int targetH)
{
Image imgPhoto = Image.FromStream(new MemoryStream(imgFile));
int targetX = (imgPhoto.Width - targetW) / 2;
int targetY = (imgPhoto.Height - targetH) / 2;
Bitmap bmpPhoto = new Bitmap(targetW, targetH, PixelFormat.Format24bppRgb);
bmpPhoto.SetResolution(80, 60);
Graphics gfxPhoto = Graphics.FromImage(bmpPhoto);
gfxPhoto.SmoothingMode = SmoothingMode.AntiAlias;
gfxPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
gfxPhoto.PixelOffsetMode = PixelOffsetMode.HighQuality;
gfxPhoto.DrawImage(imgPhoto, new Rectangle(0, 0, targetW, targetH), targetX, targetY, targetW, targetH, GraphicsUnit.Pixel);
MemoryStream mm = new MemoryStream();
bmpPhoto.Save(mm, System.Drawing.Imaging.ImageFormat.Jpeg);
// Dispose of all the objects to prevent memory leaks
imgPhoto.Dispose();
bmpPhoto.Dispose();
gfxPhoto.Dispose();
return mm.GetBuffer();
}
then insert it in the sql database
i got a code to crop the image.and i know how to insert image into sql database
but it all need to read the image as a file in the pc.
i stream the image then save it
then get it and crop it and insert it into db
PLEASE can any one tell me how to get the stream without the need to save it
You should be able to use something like this... (not tested)
Image img = Image.FromStream((new WebClient()).OpenRead("a"));

Categories

Resources