I am getting the byte in database but I cannot convert it to bitmap, I got an exception in Parameter. This is what I've done so far.
con.ConnectionString = MyConnectionString;
con.Open();
OdbcCommand cmds = new OdbcCommand("Select ID from try where kalabaw = 5", con);
OdbcDataAdapter da = new OdbcDataAdapter(cmds);
byte[] image = (byte[])cmds.ExecuteScalar();
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
Bitmap bitmap = (Bitmap)tc.ConvertFrom(image);
pictureBox2.Image = bitmap;
con.Close();
I totally stole this answer from convert array of bytes to bitmapimage
public BitmapImage ToImage(byte[] array)
{
using (var ms = new System.IO.MemoryStream(array))
{
var image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad; // here
image.StreamSource = ms;
image.EndInit();
return image;
}
}
try the below. I expect it should work.
byte[] bytes = GetBytesArrayFromDatabase();
using (MemoryStream ms = new MemoryStream(bytes))
{
ms.Position = 0;
Bitmap obj = new Bitmap(ms);
// use the Bitmap object `obj` here
}
Related
I have two functions: one to convert from image to byte and other to convert from byte to bitmapImage.
So, when I open the window with that images, I convert from byte to bitmapImage and it works great, but when I close and open it again it just keeps on memory and if I continue to do that time and time again it just throws an exception Out Of Memory exception
Image to byte->
private byte[] ConvertImageToBinary(Image img)
{
using (MemoryStream ss = new MemoryStream())
{
img.Save(ss, System.Drawing.Imaging.ImageFormat.Jpeg);
var s = ss.ToArray();
var jpegQuality = 50;
Image image;
using (var inputStream = new MemoryStream(s))
{
image = Image.FromStream(inputStream);
var jpegEncoder = System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders()
.First(c => c.FormatID == System.Drawing.Imaging.ImageFormat.Jpeg.Guid);
var encoderParameters = new System.Drawing.Imaging.EncoderParameters(1);
encoderParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, jpegQuality);
Byte[] outputBytes;
using (var outputStream = new MemoryStream())
{
image.Save(outputStream, jpegEncoder, encoderParameters);
return outputBytes = outputStream.ToArray();
}
}
}
}
Byte to bitmap ->
public BitmapImage ConvertBinaryToImage(byte[] array)
{
var image = new BitmapImage();
using (var ms = new MemoryStream(array))
{
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad; // here
image.StreamSource = ms;
image.EndInit();
image.Freeze();
}
return image;
}
When I open the WindowDragAndDrop it loads all the images
But when I close it it still uses the same amount of memory
Image is indeed disposable (https://learn.microsoft.com/en-us/dotnet/api/system.drawing.image?view=netframework-4.8), so you also need:
using (var image = Image.FromStream(inputStream)){
}
Around everywhere you use Image objects.
With this code i am able to get one image from Mysql database in C# in WPF. But i have a table in database that contaon all countries's names and their
flag etc. When i query to select many or all countries folling error occur
"Cannot set the initializing state more than once" at this line "bi.BeginInit()".
Thanks in advance.
string co = null;
string na = null;
string le = null;
string gn = null;
string A = "pak";
BitmapImage bi = new BitmapImage();
try
{
MySqlCommand cmd = new MySqlCommand("Select Code,Name,LifeExpectancy,GNP,flg from country where Name REGEXP '" + A + "'", connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
co = dataReader["Code"].ToString();
na = dataReader["Name"].ToString();
le = dataReader["LifeExpectancy"].ToString();
gn = dataReader["GNP"].ToString();
Byte[] bindata = (Byte[])dataReader["flg"];
MemoryStream strm = new MemoryStream();
strm.Write(bindata, 0, bindata.Length);
strm.Position = 0;
System.Drawing.Image img = System.Drawing.Image.FromStream(strm);
bi.BeginInit();
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ms.Seek(0, SeekOrigin.Begin);
bi.StreamSource = ms;
bi.EndInit();
dt.Rows.Add(co, na, le, gn, bi);
dataGridCustomers.ItemsSource = dt.DefaultView;
}
}
catch (MySqlException ex)
{
MessageBox.Show(ex.ToString());
}
The reason for this is because you are creating the BitmapImage outside of the loop. So Once you get in the loop it keeps trying to set the initializing state on the same image. As your error states you can't do this. What you need to do is create a new BitmapImage on each iteration. Which can be accomplished by moving the line
BitmapImage bi = new BitmapImage();
To the inside of the loop. Unless there is a specific reason you are initializing it where you are.
string co = null;
string na = null;
string le = null;
string gn = null;
string A = "pak";
try
{
MySqlCommand cmd = new MySqlCommand("Select Code,Name,LifeExpectancy,GNP,flg from country where Name REGEXP '" + A + "'", connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
BitmapImage bi = new BitmapImage();
co = dataReader["Code"].ToString();
na = dataReader["Name"].ToString();
le = dataReader["LifeExpectancy"].ToString();
gn = dataReader["GNP"].ToString();
Byte[] bindata = (Byte[])dataReader["flg"];
MemoryStream strm = new MemoryStream();
strm.Write(bindata, 0, bindata.Length);
strm.Position = 0;
System.Drawing.Image img = System.Drawing.Image.FromStream(strm);
bi.BeginInit();
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ms.Seek(0, SeekOrigin.Begin);
bi.StreamSource = ms;
bi.EndInit();
dt.Rows.Add(co, na, le, gn, bi);
dataGridCustomers.ItemsSource = dt.DefaultView;
}
}
catch (MySqlException ex)
{
MessageBox.Show(ex.ToString());
}
EDIT: In the code above, the System.Drawing.Image is entirely redundant. You should directly create the BitmapImage from the byte array like this:
var bindata = (byte[])dataReader["flg"];
var bi = new BitmapImage();
using (var stream = new MemoryStream(bindata))
{
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.StreamSource = stream;
bi.EndInit();
}
I have an application that creates WPF Image controls on-the-fly to display images from a SQL Server database table. The panels that display the controls get replaced frequently. I use MemoryStreams to allow the controls to access the byte arrays loaded from the database. I cannot close these streams as long as the Image controls are displayed and still have the images displayed. My concern is that these streams will be left open until the Garbage Collector gets around to disposing of the Image controls and hopefully closing the streams too. I will probably end up just making sure that I close the streams or dispose of the Image controls before the panels are replaced but would like to know if there is an issue with leaving these streams open and if there is a way around this.
Here's the code that I am using.
public class ImageToSql
{
private static OpenFileDialog _openFileDialog = new OpenFileDialog();
static ImageToSql()
{
_openFileDialog = new OpenFileDialog();
_openFileDialog.AddExtension = true;
_openFileDialog.CheckFileExists = true;
_openFileDialog.DefaultExt = ".jpg";
_openFileDialog.Filter = "JPEG files (*.jpg)|*.jpg|All files (*.*)|*.*";
_openFileDialog.FilterIndex = 1;
_openFileDialog.Multiselect = false;
}
public static BitmapImage LoadImageFromFile(string caption)
{
BitmapImage bi = new BitmapImage();
_openFileDialog.Title = caption;
if (_openFileDialog.ShowDialog() == true)
{
bi.BeginInit();
bi.StreamSource = File.OpenRead(_openFileDialog.FileName);
bi.EndInit();
}
return bi;
}
public static int StoreImage(string connectionString, string sql, string imageParameterName, BitmapImage bitmapImage)
{
SqlConnection conn = new SqlConnection(connectionString);
try
{
conn.Open();
sql += ";SELECT ##IDENTITY";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
byte[] data = new byte[bitmapImage.StreamSource.Length];
bitmapImage.StreamSource.Seek(0, SeekOrigin.Begin);
bitmapImage.StreamSource.Read(data, 0, data.Length);
cmd.Parameters.Add(imageParameterName, System.Data.SqlDbType.VarBinary, -1).Value = data;
object obj = cmd.ExecuteScalar();
return Int32.Parse(obj.ToString());
}
}
finally
{
conn.Close();
}
}
public static BitmapImage RetrieveImage(string connectionString, string sql, string imageIDParameterName, int imageID)
{
BitmapImage bi = new BitmapImage();
SqlConnection conn = new SqlConnection(connectionString);
try
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add(imageIDParameterName, System.Data.SqlDbType.Int).Value = imageID;
byte[] data = (byte[])cmd.ExecuteScalar();
MemoryStream ms = new MemoryStream(data);
ms.Seek(0, SeekOrigin.Begin);
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
}
}
finally
{
conn.Close();
}
return bi;
}
}
Below is how this code is called. "_fileImage" and "_sqlImage" are Image controls on my test Window. At one point, I was using a stream to read the file from disk in "LoadImageFromFile" and think I was able to close that stream while still displaying the image in the Image control. So, MemoryStream seems to be special somehow.
BitmapImage bi = ImageToSql.LoadImageFromFile("Select Image to Save");
_fileImage.Source = bi;
int imageID = ImageToSql.StoreImage(connString,
"INSERT INTO PV_Image (Description, Image) VALUES ('Some Image', #pImage)",
"#pImage", bi);
_sqlImage.Source = ImageToSql.RetrieveImage(connString,
"SELECT Image FROM PV_Image WHERE ImageID = #pImageID",
"#pImageID", imageID);
You can dispose the memory stream once it is used using the using pattern:
using (Stream stream = new MemoryStream(data))
{
BitmapImage image = new BitmapImage():
stream.Position = 0;
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = stream;
image.EndInit();
image.Freeze();
return image;
}
OleDbCommand and = new OleDbCommand();
c.Open();
and.Connection = c;
and.CommandText = "SELECT * FROM MaleShoes WHERE IDhere=ID ";
OleDbDataReader read = and.ExecuteReader();
while (read.Read())
{
label6.Text = (read[1].ToString());
textBox1.Text = (read[2].ToString());
pictureBox1.Image = (read[3].ToString());
}
c.Close();
I got this error:
Error 1 Cannot implicitly convert type 'string' to 'System.Drawing.Image'
How should I fix it?
My pictures are in my database on the third column.
If you your database column contains the path to the image file, you should write:
pictureBox1.Image = Image.FromFile((string)read[3]);
If it is the image data (binary), you should write:
var bytes = (byte[])read[3];
using(MemoryStream ms = new MemoryStream(bytes))
{
pictureBox1.Image = Image.FromStream(ms);
}
Hope this help (in case you are storing a binary):
pictureBox1.Image = byteArrayToImage((byte[])read[3]);
And your method
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
you can also use this
byte[] imagebyte = (byte[])read[3].ToString();
MemoryStream ms = new MemoryStream();
ms.Write(imagebyte, 0, imagebyte.Length);
Bitmap bmp = new Bitmap(ms);
pictureBox1.Image = bmp;
You can try this:
MemoryStream ms = new MemoryStream((byte[])read[1]);
pictureBox1.Image = Image.FromStream(ms);
How do I assign an in-memory Bitmap object to an Image control in WPF ?
According to http://khason.net/blog/how-to-use-systemdrawingbitmap-hbitmap-in-wpf/
[DllImport("gdi32")]
static extern int DeleteObject(IntPtr o);
public static BitmapSource loadBitmap(System.Drawing.Bitmap source)
{
IntPtr ip = source.GetHbitmap();
BitmapSource bs = null;
try
{
bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip,
IntPtr.Zero, Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
}
finally
{
DeleteObject(ip);
}
return bs;
}
It gets System.Drawing.Bitmap (from WindowsBased) and converts it into BitmapSource, which can be actually used as image source for your Image control in WPF.
image1.Source = YourUtilClass.loadBitmap(SomeBitmap);
You can use the Source property of the image. Try this code...
ImageSource imageSource = new BitmapImage(new Uri("C:\\FileName.gif"));
image1.Source = imageSource;
It's easy for disk file, but harder for Bitmap in memory.
System.Drawing.Bitmap bmp;
Image image;
...
MemoryStream ms = new MemoryStream();
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
ms.Position = 0;
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
image.Source = bi;
Stealed here
I wrote a program with wpf and used Database for showing images and this is my code:
SqlConnection con = new SqlConnection(#"Data Source=HITMAN-PC\MYSQL;
Initial Catalog=Payam;
Integrated Security=True");
SqlDataAdapter da = new SqlDataAdapter("select * from news", con);
DataTable dt = new DataTable();
da.Fill(dt);
string adress = dt.Rows[i]["ImgLink"].ToString();
ImageSource imgsr = new BitmapImage(new Uri(adress));
PnlImg.Source = imgsr;