i tried to add pictures using openfiledialog into an image list then save it in my Ms Access data base and call it in another form to show them in picture box by slide through them using a timer control but when i try to add picture's using open file dialog i get this error An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll Additional information: Out of memory.
here is my code
private void btnPicAdd_Click(object sender, EventArgs e)
{
ofdTargetPic.Filter = "Image File (*.Gif;*.jpg)|*.Gif;*.jpg";
ofdTargetPic.Title = "Add target picture";
ofdTargetPic.Multiselect = true;
ofdTargetPic.FileName = string.Empty;
DialogResult result = ofdTargetPic.ShowDialog();
if (result == DialogResult.OK)
{
picTargetchoose.SizeMode = PictureBoxSizeMode.StretchImage;
foreach (var picture in ofdTargetPic.FileNames)
{
imgltargetpic.Images.Add(Image.FromFile(picture));//error is here
}
}
}
also if it's possible tell me with what format i can save the imagelist data in my data base i know the codes i just want to know what space should i open in my data base to save the data ( the format of imagelist output data)
here is the code for those who need to learn how to add the data into data base
OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Target.accdb");//this addres here is based on where you save your data base
OleDbCommand cmd = new OleDbCommand();
cmd.CommandText = "insert into tablename(tablefieldname,tablefieldname,...)values('" textboxName.Text "','" textboxfamily.Text "')";
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
Update's : first of all the error ;; An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll Additional information: Out of memory. in my problem was because the image i was choosing was corrupted !! for clarity i want to show the saved image data from data base in my c# windows form application in a picture box and the reason I'm choosing an image list is because i want to choose multiple image's and then slide show them using timer in a picture box for that i have already wrote the code to show it to the user before saving it in the data base here is the code :
int selectedpic = 0;
private void timerpicslide_Tick(object sender, EventArgs e)
{
picTargetchoose.Image = imgltargetpic.Images[selectedpic];
if (selectedpic == imgltargetpic.Images.Count -1)
{
selectedpic = 0;
}
else
{
selectedpic ;
}
}
i used the timer to select the picture's in the image list one by one every time the timer ticks (remember to start the timer when you add the picture's) now the problem is i cant call the saved data into my image list from data base and show it to the user using picture box here is the code I'm using :
private void cmbTarget_SelectedIndexChanged(object sender, EventArgs e)
{
con.Open();
OleDbDataAdapter da = new OleDbDataAdapter("select * from targetInfo where targetName like '" cmbTarget.SelectedItem.ToString() "%'", con);
DataTable dt = new DataTable();
da.Fill(dt);
dgvtargetview.DataSource = dt;
imglpicshow.Images.Add(Image.FromFile(dgvtargetview.CurrentRow.Cells[3].Value.ToString())); // where the problem lies
}
image list takes binary data i have saved the data in OLE Object format in my data base the way our friend @Albert D. Kallal suggested in the answer but now i cant take out of data base and put it in the image list to do the process .
thanks for your time!
CodePudding user response:
Well, one would assume if you going to save the raw binary file in Access? Then the image control probably can figure out the format, but this suggests that you should ALSO at least have another column that saves the file name with extension.
And I would at least spend a cup of coffee time being REALLY sure you want to store the file in the database as opposed to in a folder, and then ONLY save the path name to the folder in the database table.
The reason for above are many, but this means:
If you ever want to adopt say sql server, then the data migration becomes very easy.
For any web based software - again having a path to a folder with images is VERY much less hassle and work.
Users can with great easy "copy files out" of that folder, search for file names in that folder, and use launch their favorite picture editor and viewing software. If you tuck away that file inside of the database, then you quite much lose use of any and all picture editors, and even picture organization and picture slide show software etc. And it makes it difficult for any other software to use such pictures.
Also, it is not clear if you are wishing to display the pictures in c# applcation, or that you want the pictures to display say in a access form? So this issue should be made clear here.
As noted, you want to save the filename with extension, since if you ever need to pull pictures out of the db, then you need the file extension (unless say you only ever allow one picture type to be saved).
You CAN use the oleDB type column in the Access db, or use memo. (but, if you save as binary into memo type column, then you need a do a string covert into byte[] BEFORE you shove into the image control.
So, I used oleDB type, and my database is this:
DO KEEP in mind, we are not at all using the oleDB format that Access uses. This choice is really simple a binary data blob.
The images without wee bit of code in VBA/MS-Access can be displayed, but I'm assume we display and using in c# a winform.
Ok, so say a form like this - real simple:
So, at top, we browse to a file - select it
This code:
private void cmdBrowseFile_Click(object sender, EventArgs e)
{
OpenFileDialog MyFile = new OpenFileDialog();
MyFile.ShowDialog();
if (MyFile.FileNames.Length > 0)
{
txtFile.Text = MyFile.FileName;
txtFileName.Text = Path.GetFileName(txtFile.Text);
ShowPicFile(MyFile.FileName);
}
}
void ShowPicFile(string sFile)
{
pictureBox1.Image = ByteToImage(File.ReadAllBytes(sFile));
}
public static Bitmap ByteToImage(byte[] blob)
{
Bitmap image;
using (MemoryStream stream = new MemoryStream(blob))
image = new Bitmap(stream);
return image;
}
So, if we browse to file - we display (not saved to db).
Say like this:
So, I take JUST the file name, shove into lower right box and then hit save to db
And it will add/save to db. That code is this:
private void cmdSave_Click(object sender, EventArgs e)
{
// save picture as bytes to DB
byte[] fData = File.ReadAllBytes(txtFile.Text);
string strSQL =
@"INSERT INTO MyPictures (FileName, PictureData)
VALUES(@File, @Data)";
OleDbCommand cmdSQL = new OleDbCommand(strSQL);
cmdSQL.Parameters.Add("@File", OleDbType.VarWChar).Value = txtFileName.Text;
cmdSQL.Parameters.Add("@Data", OleDbType.Binary).Value = fData;
MyRstP(cmdSQL, false);
// display in grid
cmdSQL.CommandText = "SELECT ID, FileName FROM MyPIctures";
cmdSQL.Parameters.Clear();
dataGridView1.DataSource = MyRstP(cmdSQL);
MessageBox.Show("saved");
}
And now the new row appears in our grid. I can click on any row, then click show from DB. that code is this:
private void cmdShow_Click(object sender, EventArgs e)
{
int pk = (int)dataGridView1.CurrentRow.Cells[0].Value;
OleDbCommand cmdSQL =
new OleDbCommand("SELECT ID, PictureData FROM MyPictures WHERE ID = @ID");
cmdSQL.Parameters.Add("@ID", OleDbType.Integer).Value = pk;
DataRow OneRow = MyRstP(cmdSQL).Rows[0];
pictureBox1.Image = ByteToImage((byte[])OneRow["PictureData"]);
}
And my helper routines
DataTable MyRstP(OleDbCommand cmdSQL, bool ReturnsData = true)
{
DataTable rstData = new DataTable();
using (OleDbConnection conn = new OleDbConnection(Properties.Settings.Default.AccessDB))
{
using (cmdSQL)
{
cmdSQL.Connection = conn;
conn.Open();
if (ReturnsData)
rstData.Load(cmdSQL.ExecuteReader());
else
cmdSQL.ExecuteNonQuery();
}
}
return rstData;
}
and
public static Bitmap ByteToImage(byte[] blob)
{
Bitmap image;
using (MemoryStream stream = new MemoryStream(blob))
image = new Bitmap(stream);
return image;
}