How to show preview of image using handler - c#

I m using a handler to display images on my page from database
public void ProcessRequest (HttpContext context)
{
SqlConnection con = new SqlConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["XYZ"].ConnectionString;
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "Select Image from EmployeeInfo where Emp_Id = #ID";
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
SqlParameter ImageID = new SqlParameter("#ID", System.Data.SqlDbType.Int);
ImageID.Value = context.Request.QueryString["ID"];
int height = Convert.ToInt32(context.Request.QueryString["Ht"]);
int width = Convert.ToInt32(context.Request.QueryString["Wt"]);
cmd.Parameters.Add(ImageID);
con.Open();
SqlDataReader dReader = cmd.ExecuteReader();
if (dReader.HasRows)
{
dReader.Read();
byte[] imagethumbnail = null;
try
{
imagethumbnail = MakeThumbnail((byte[])dReader["Image"], width, height);
}
catch
{
}
context.Response.BinaryWrite(imagethumbnail);
}
dReader.Close();
con.Close();
}
public static byte[] MakeThumbnail(byte[] myImage, int thumbWidth, int thumbHeight)
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
using (Image thumbnail = Image.FromStream(new MemoryStream(myImage)).GetThumbnailImage(thumbWidth, thumbHeight, null, new IntPtr()))
{
thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms.ToArray();
}
}
This code works fine when displaying images from database.
Now What I want to do is to Show image preview using a different Handler.
Now if u look at the above code then you can see we have image data in byte[] form.
I m uploading a image and I m able to get the data in byte[] but this data of mine is on .cs page.
context.Response.BinaryWrite(imagethumbnail);
If I use this command converting data into bytes from page, it shows me the image on page nothing else.
Can you give me any idea how to show this data into image?
There is nothing much change in the datastream
This is what I want to use but how to get byte[] from .cs page to handler.
imagethumbnail = MakeThumbnail((byte[])dReader["Image"], width, height);
context.Response.BinaryWrite(imagethumbnail);

You can seperate your database image logic into a Generic Handler (ASHX) and then use the handler as your image's src e.g.
<img src="GetImage.ashx?id=1"/>
You'd need to create GetImage.ashx and handle your id's (or whatever your using) appropriately. Then you can do a simple write back to the page.
This will allow you to dynamically pull an image from the database while using it as a seperate element on your page.

Related

Decoded bitmap images aren't set in the photoboxes correctly

private void BTN_Save_Click(object sender, EventArgs e)
{
string DBpath = #"Data Source=.\StudentDB.db;Version=3;";
Bitmap[] PictureBoxesBitmaps = {FirstPictureBitmap, SecondPictureBitmap, ThirdPictureBitmap };
using SQLiteConnection connection = new(DBpath);
using SQLiteCommand cmd = new(DBpath, connection);
connection.Open();
cmd.CommandText = #"DELETE FROM PictureBoxes";
cmd.ExecuteNonQuery();
foreach (Bitmap bitmap in PictureBoxesBitmaps)
{
System.IO.MemoryStream ms = new();
bitmap?.Save(ms, ImageFormat.Png);
byte[] BitmapByteArray = ms.ToArray();
var PictureBox64 = Convert.ToBase64String(BitmapByteArray);
cmd.CommandText = #"INSERT INTO PictureBoxes(Encoded) VALUES('" + PictureBox64 + "')";
cmd.ExecuteNonQuery();
}
connection.Close();
}
I'm using this first code to encode three bitmap images into a base64 string, then I'm storing them in a SQLite database.
public Form1()
{
InitializeComponent();
RefreshData();
using SQLiteConnection PicCheckerConnection = new(DBpath);
using var cmd = new SQLiteCommand(DBpath, PicCheckerConnection);
PicCheckerConnection.Open();
for (int i = 0; i <= 4; i++)
{
cmd.CommandText = "SELECT * FROM (PictureBoxes) Limit "+ i +"," + i;
cmd.ExecuteNonQuery();
using (SQLiteDataReader read = cmd.ExecuteReader())
{
while (read.Read())
{
string Base64Image = read.GetString(0);
byte[] bytes = Convert.FromBase64String(Base64Image);
Stream stream = new MemoryStream(bytes);
if (i == 1) { pictureBox1.Image = Image.FromStream(stream);}
if (i == 2) { pictureBox2.Image = Image.FromStream(stream);}
if (i == 3) { pictureBox3.Image = Image.FromStream(stream);}
}
read.Close();
}
}
Then I wrote this code where it selects all three base64 strings from the SQLite database, decodes them and puts them in their pictureboxes respectively, the first base64 string --> the first picture box, second base64 string --> second picture box, and third base64 string --> third picture box.
However, when the program decodes the base64 strings and applies the images to the pictureboxes, the order is messed up.
The second decoded image is set in the first picturebox, and the third decoded image is set in the second picturebox and the first decoded image is not set in any of the pictureboxes.
I have tried debugging and changing the value of i, but sadly they did not help.
Add a column for sorting with images to the table to store them, and sort them with the order by clause.

Converting stored images in DB to string and back to byte?

So I have a couple tabs in a tabcontrol which do the task of registering and modifying info about a client. The first one among other info, saves a picture using OpenFileDialog and then store it into 'lblImagePath.Text' to use bitmap with it so I can save it into de DB, which can be seen in this code:
public partial class form : Form
{
String strDBFilePath = "";
String strFilePath = "";
Image DefaultImage;
byte[] ImageByteArray;
byte[] ImageByteArrayMod;
private void btnAddUser_Click(object sender, EventArgs e)
{
if (txtEmailPersonal.Text != "")
{
try
{
Image temp = new Bitmap(strFilePath);
MemoryStream ms = new MemoryStream();
temp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ImageByteArray = ms.ToArray();
SqlConnection con = new SqlConnection();
con.ConnectionString = CONEXION.CONEXIONMAESTRA.conexion;
con.Open();
SqlCommand cmd = new SqlCommand();
cmd = new SqlCommand("insert_user", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#email", txtEmailPersonal.Text);
cmd.Parameters.AddWithValue("#password", txtPasswordPersonal.Text);
cmd.Parameters.AddWithValue("#profile_picture", ImageByteArray);
cmd.Parameters.AddWithValue("#imageFile_name", lblImagePath.Text);
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
mostrar();
}
}
}
Everything goes smooth, register form works and I'm using a datagridview to visualize it. When I double click a row from the dgv, all the info loads into the second tab and let's me modify all the info except the profile picture, which can be previewed in a picturebox but doesnt load any other information about it, so when I hit the 'save changes' button, it won't let me proceed with it until I re-upload a profile picture, since path is non existant prior to that action. This is the code for user modifying:
private void btnGuardarCambiosPersonal_Click(object sender, EventArgs e)
{
if (txtEmailPersonalMod.Text != "")
{
try
{
Image temp = new Bitmap(strDBFilePath);
MemoryStream ms = new MemoryStream();
temp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ImageByteArrayMod = ms.ToArray();
SqlConnection con = new SqlConnection();
con.ConnectionString = CONEXION.CONEXIONMAESTRA.conexion;
con.Open();
SqlCommand cmd = new SqlCommand();
cmd = new SqlCommand("modify_user", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#correo", txtEmailPersonalMod.Text);
cmd.Parameters.AddWithValue("#password", txtPasswordPersonalMod.Text);
cmd.Parameters.AddWithValue("#profile_picture", ImageByteArrayMod);
cmd.Parameters.AddWithValue("#imageFile_name", lblFilePathMod.Text);
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
mostrar();
}
}
Some of the stuff I have in there might actually be useless to accomplish what I want. So I'll try to be as clear as possible, I want to be able to keep the current profile picture if another profile picture isn't uploaded to replace it.
As you might also see, instead of doing the query directly on the code, I'm using stored procedures, the idea is to keep those stored procedures and try to do the adjusting in the code.
After reading #Llama 's comments, I realized solution was very simple, over the modifying code, I added this at the beginning of the try/catch:
Image tempy = new Bitmap(picPerfilMod.Image);
MemoryStream mems = new MemoryStream();
tempy.Save(mems, System.Drawing.Imaging.ImageFormat.Jpeg);
ImageByteArrayMod = mems.ToArray();
so I could turn image from picturebox back to array and without the need to modify it.
I will keep reading about varbinary column type use for this cases, since it clearly looks like a better/simpler idea.

C# retrieving image in db. Get Error Parameter in not valid

I don't know what's wrong with my code in retrieving image in db. I insert image without using image path file cause the image provide by the cam.
Here's my code in inserting image in db
Image img = pictureBox1.Image;
MemoryStream memStream = new MemoryStream();
img.Save(memStream, ImageFormat.Bmp);
byte[] imageBt = memStream.ToArray();
query = "";
query += "INSERT INTO table(picture) VALUES ('" + imageBt + "')";
cmd = new MySqlCommand(query, con);
cmd.ExecuteNonQuery();
con.close();
Here's my code in retrieving image in db
query = "";
query += "SELECT picture FROM table WHERE id = '1'";
cmd = new MySqlCommand(query, con);
con.Open();
MemoryStream ms = new MemoryStream();
byte[] image = (byte[])cmd.ExecuteScalar();
ms.Write(image, 0, image.Length);
con.Close();
Bitmap bmp = new Bitmap(ms)
pictureBox1.Image = bmp; //Still get the Error here parameter is not valid
Is there anywrong process in saving image in database. Btw my image type in db is Blob. I don't know why it doesn't work in retrieving image it always thrown error. Thanks
When reading, you haven't rewound the stream. If you Write, you must set ms.Position = 0; afterwards. Or simpler: create the stream from the data, then you don't need to:
byte[] image = ...
var ms = new MemoryStream(image);
When writing, you seem to have injected the data directly. That... almost certainly won't work - in fact, you're probably writing System.Byte[] to the command. Ideally, use a parameter:
query = "INSERT INTO table(picture) VALUES (#blob)";
cmd = new MySqlCommand(query, con);
cmd.Parameters.AddWithValue("blob", imageBt);
cmd.ExecuteNonQuery();
(the exact syntax may change between RDBMS implementations)

Read Image from SQL Server VarBinary(Max)

I have a SQL Server Database. I have stored an image in there which is a varbinary(max). I inserted the image the following way :
string consString = ConfigurationManager.ConnectionStrings["connection"].ConnectionString;
SqlConnection con = new SqlConnection(consString);
con.Open();
String filePath = fuImage.PostedFile.FileName;
String naam = Path.GetFileName(filePath);
String extension = Path.GetExtension(naam);
Stream stream = fuImage.PostedFile.InputStream;
BinaryReader br = new BinaryReader(stream);
Byte[] imgByte = br.ReadBytes((Int32)stream.Length);
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "spAddImage";
cmd.Parameters.AddWithValue("#FOTO", imgByte);
cmd.Parameters.AddWithValue("#ARTIEST", ddlArtiest.SelectedValue);
cmd.Connection = con;
cmd.ExecuteNonQuery();
con.Close();
The image now looks like this in the database :
It is stored as a varbinary.
http://puu.sh/ikF83/6a03b52520.png <--- database
Now I want to display my image on my asp.net page that I have inserted.
But I have no idea how I can achieve this.
You could use SqlDataReader to go over the results and get back what you need
var reader = cmd.ExecuteReader();
while (reader.Read())
{
byte[] myImage = (byte[])reader["MyImageColumn"];
}
This is from top of my head so make your adjustments as required. But it should give you the basic idea.
Furthermore, It's strongly recommended to use the using block as it ensures the object is disposed correctly.
So you could change your code to
using(var connection = new SqlConnection(connectionString))
{
//Your command
connection.Open();
//Datareader here
}//Object disposed here
Reference to SqlDataReader
Reference to using block
Extending the answer provided by Izzy, below is how we have implemented the same.
public HttpResponseMessage RenderImage(RenderRequest renderRequest, HttpRequestMessage request)
{
var httpResponse = new HttpResponseMessage();
try
{
var reader = cmd.ExecuteReader();
while (reader.Read())
{
byte[] imagebytes = (byte[])reader["MyImageColumn"];
}
return httpResponse = request.CreateResponse<byte[]>(HttpStatusCode.OK, imagebytes, new ImageMediaFormatter("image/png"));
}
catch ()
{
throw;
}
}

populate list with images from database

I want to retrieve the images from SQL table and save it in the list and show it in my listview. But I don't know how to do this. I need your help.
I am using SQL Server 2008, Visual Studio 2008, C# Window Application.
Here is my code:
cmd = new SqlCommand("Select ScanImage from ScanDocuments", con);
dr = cmd.ExecuteReader();
List<ImageList> lstitem = new List<ImageList>();
while (dr.Read())
{
ImageList _image = new ImageList();
byte[] data = (byte[])dr["ScanImage"];
MemoryStream ms = new MemoryStream(data);
Image bmp = new Bitmap(ms);
lstitem.Add(bmp);
}
Your code has several flaws - you need to use something like this instead:
// define connection string and select statement
// I used AdventureWorks 2012 database - change to match *YOUR* environment
string connectionString = "server=.;database=AdventureWorks2012;integrated security=SSPI;";
string query = "SELECT ThumbNailPhoto FROM Production.ProductPhoto";
// define a list of "Image" objects
List<Image> listOfImages = new List<Image>();
// using the SqlConnection and SqlCommand ....
using(SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand selectCmd = new SqlCommand(query, conn))
{
// open connection
conn.Open();
// execute SqlCommand to return a SqlDataReader
using (SqlDataReader rdr = selectCmd.ExecuteReader())
{
// iterate over the reader
while (rdr.Read())
{
// load the bytes from the database that represent your image
var imageBytes = (byte[]) rdr[0];
// put those bytes into a memory stream and "rewind" the memory stream
MemoryStream memStm = new MemoryStream(imageBytes);
memStm.Seek(0, SeekOrigin.Begin);
// create an "Image" from that memory stream
Image image = Image.FromStream(memStm);
// add image to list
listOfImages.Add(image);
}
}
conn.Close();
}
This works just fine for me - it loads the 101 ThumbNailPhoto from the AdventureWorks2012 database

Categories