Reputation: 993
I save my image like this:
//This is in my ImageConverter class:
public static byte[] ConvertImageToByteArray(Image userImage) //Get bytes of the image
{
using (MemoryStream ms = new MemoryStream())
using (Bitmap tempImage = new Bitmap(userImage))
{
tempImage.Save(ms, userImage.RawFormat);
return ms.ToArray();
}
}
//this is in my save button:
sqlCmd.Parameters.Add("@user_image", SqlDbType.VarBinary, 8000).Value =
ImageConverter.ConvertImageToByteArray(pictureBox1.Image);
I retrieve my image by clicking on the datagridview like this:
private void dgvEmpDetails_CellClick(object sender, DataGridViewCellEventArgs e)
{
try
{
if (e.RowIndex != -1)
{
//Display user image
using (SqlConnection con = new SqlConnection(connectionStringConfig))
using (SqlCommand sqlCmd = new SqlCommand(
"SELECT user_image FROM dbo.Employee_Image
WHERE employee_id=@employee_id", con))
{
con.Open();
sqlCmd.Parameters.Add("@employee_id",
SqlDbType.NVarChar).Value = EmployeeId;
using (SqlDataReader reader = sqlCmd.ExecuteReader())
{
if (reader.HasRows)
{
reader.Read();
pictureBox1.Image = ImageConverter.
ConvertByteArrayToImage((byte[])(reader.GetValue(0)));
}
else
{
pictureBox1.Image = null;
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show($"Something is wrong with the selected record!
\nError: { ex.Message }");
}
}
//This is in my ImageConverter class:
public static Image ConvertByteArrayToImage(byte[] buffer) //Get image from database
{
using (MemoryStream ms = new MemoryStream(buffer))
{
return Image.FromStream(ms);
}
}
NOTE: I don't display my image's binary data in my datagridview.
Saving and updating the image (with the users records) works fine.
After saving an image to the database, it does not display properly. But when I load it using OpenFileDialog the image displays just fine.
Loading the image using OpenFileDialog:
When I click a datagridview row to view a user record this is what the pictureBox looks like:
Why is this split in some sort? I have not seen any similar problem/solution about this. Most of them is about "Loading image from the database to pictureBox". But I have already done that.
Upvotes: 1
Views: 1196
Reputation: 1408
This is my approach for getting images from database
// This method use to update the form.
private void loadFormWithID(int ID)
{
dbServer conn = new dbServer(sysController.getConn);
DataTable tbl = conn.getQueryList("SELECT * FROM Products WHERE ID = " + ID);
DataRow row = tbl.Rows[0];
// This is how i update the Picture Box
pictureBoxItem.Image = row["Image"] == DBNull.Value ? pictureBoxItem.InitialImage : ImageController.bytesToImage((byte[])row["Image"]);
}
This is my dbserver class which communicates with database.
public class dbServer
{
public string _connectionLink;
public dbServer(string connectionString)
{
_connectionLink = connectionString;
}
public DataTable getQueryList(string sqlQuery)
{
DataTable tbl = new DataTable();
using (SqlConnection conn = new SqlConnection(_connectionLink))
{
using (SqlCommand cmd = new SqlCommand(sqlQuery, conn))
{
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
tbl.Load(reader);
}
}
return tbl;
}
}
This is what I used for my database image retriever.
class ImageController
{
public static byte[] ImageToBytes(PictureBox pb)
{
MemoryStream ms = new MemoryStream();
pb.Image.Save(ms, pb.Image.RawFormat);
return ms.GetBuffer();
}
public static byte[] ImageToBytes(Image pb)
{
MemoryStream ms = new MemoryStream();
pb.Save(ms, pb.RawFormat);
Console.WriteLine(ms.Length);
return ms.GetBuffer();
}
public static Image bytesToImage(byte[] imageRaw)
{
MemoryStream ms = new MemoryStream(imageRaw);
return Image.FromStream(ms);
}
}
Upvotes: 0
Reputation: 5009
Here's a complete solution, which seems to work with SQL Server Express/SQL Server:
Note: When the table in the database is created, column User_Image
should be created as varbinary(MAX)
Read image from file and return as byte[]:
Note: I've included 3 different ways to read an image file and return a byte[]. GetImageFromFile
seems to produce a byte array that has the same number of bytes as the original (tested with .jpg), whereas, GetImageFromFilev2
and GetImageFromFilev3
, have fewer bytes. See How to convert image to byte array for more information.
public static byte[] GetImageFromFile(string filename)
{
byte[] rawData = null;
try
{
if (!String.IsNullOrEmpty(filename) && System.IO.File.Exists(filename))
{
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
//get length of file - in bytes
int fileLength = (int)fs.Length;
//create new byte array
rawData = new byte[fileLength];
//read data into byte array (rawData)
fs.Read(rawData, 0, fileLength);
fs.Flush();
Debug.WriteLine("rawData.Length: " + rawData.Length);
}
}
}
catch (Exception ex)
{
//ToDo: log message
throw ex;
}
return rawData;
}
public static byte[] GetImageFromFilev2(string filename)
{
byte[] rawData = null;
try
{
if (!String.IsNullOrEmpty(filename) && System.IO.File.Exists(filename))
{
using (Image image = Image.FromFile(filename))
{
using (MemoryStream ms = new MemoryStream())
{
image.Save(ms, image.RawFormat);
rawData = ms.ToArray();
}
}
}
}
catch (Exception ex)
{
//ToDo: log message
throw ex;
}
return rawData;
}
public static byte[] GetImageFromFilev3(string filename)
{
byte[] rawData = null;
try
{
if (!String.IsNullOrEmpty(filename) && System.IO.File.Exists(filename))
{
using (Image image = Image.FromFile(filename))
{
ImageConverter ic = new ImageConverter();
rawData = (byte[])ic.ConvertTo(image, typeof(byte[]));
Debug.WriteLine("rawData.Length: " + rawData.Length);
}
}
}
catch (Exception ex)
{
//ToDo: log message
throw ex;
}
return rawData;
}
Read image data from database:
public static System.Drawing.Bitmap GetImageFromTblEmployeeImageBitmap(string employee_id)
{
System.Drawing.Bitmap image = null;
byte[] imageData = GetImageFromTblEmployeeImageByte(employee_id);
//convert to Bitmap
if (imageData != null)
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(imageData))
{
image = new System.Drawing.Bitmap(ms);
ms.Flush();
}
}
return image;
}
public static byte[] GetImageFromTblEmployeeImageByte(string employee_id)
{
byte[] imageData = null;
try
{
using (SqlConnection cn = new SqlConnection(ConnectStr))
{
string sqlText = "Select user_image from Employee_Image where employee_id = @employee_id";
//open connection to db
cn.Open();
using (SqlCommand cmd = new SqlCommand(sqlText, cn))
{
cmd.Parameters.Add("@employee_id", SqlDbType.NVarChar).Value = employee_id;
//execute
SqlDataReader dr1 = cmd.ExecuteReader();
bool result = dr1.Read();
if (result)
{
imageData = (byte[])dr1["User_Image"];
}
Debug.WriteLine("result: " + result);
}
}
}
catch (SqlException ex)
{
//ToDo: log message
throw ex;
}
catch (Exception ex)
{
//ToDo: log message
throw ex;
}
return imageData;
}
Save image data to database
public static string SaveImageToTblEmployeeImage(string employee_id, string filename)
{
return SaveImageToTblEmployeeImage(employee_id, GetImageFromFile(filename));
}
public static string SaveImageToTblEmployeeImage(string employee_id, byte[] user_image)
{
string status = string.Empty;
using (SqlConnection cn = new SqlConnection(ConnectStr))
{
string sqlText = "INSERT INTO Employee_Image(Employee_Id, User_Image) VALUES (@employee_id, @user_image)";
//open connection to db
cn.Open();
using (SqlCommand cmd = new SqlCommand(sqlText, cn))
{
//add parameters
cmd.Parameters.Add("@employee_id", System.Data.SqlDbType.NVarChar).Value = employee_id;
//for varbinary(max) specify size = -1, otherwise there is an 8000 byte limit
//see https://learn.microsoft.com/en-us/dotnet/api/system.data.sqldbtype?view=netframework-4.8
cmd.Parameters.Add("@user_image", System.Data.SqlDbType.VarBinary, -1).Value = user_image;
//execute
int numRowsAffected = cmd.ExecuteNonQuery();
status = "Data inserted into table 'Employee_Image'";
Debug.WriteLine("numRowsAffected: " + numRowsAffected);
}
}
return status;
}
Upload image to database
using (OpenFileDialog ofd = new OpenFileDialog())
{
ofd.Filter = "Image Files (*.bmp;*.gif;*.jpg;*.jpeg;*.png)|*.bmp;*.gif;*.jpg;*.jpeg;*.png|All Files (*.*)|*.*";
if (ofd.ShowDialog() == DialogResult.OK)
{
SaveImageToTblEmployeeImage("12345", ofd.FileName);
}
}
To display image in PictureBox (ex: pictureBox1)
Bitmap image = GetImageFromTblEmployeeImageBitmap("12345");
if (image != null)
{
pictureBox1.Image = image;
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; //fit to size
pictureBox1.Refresh();
}
Resources:
Upvotes: 0
Reputation: 640
Try using the MemoryStream.Write method.
Change this:
//This is in my ImageConverter class:
public static Image ConvertByteArrayToImage(byte[] buffer) //Get image from database
{
using (MemoryStream ms = new MemoryStream(buffer))
{
return Image.FromStream(ms);
}
}
to this:
//This is in my ImageConverter class:
public static Image ConvertByteArrayToImage(byte[] buffer) //Get image from database
{
using (MemoryStream ms = new MemoryStream)
{
ms.Write(buffer.ToArray(), 0, buffer.Length);
return Image.FromStream(ms);
}
}
Upvotes: 0