I have a program to select an image and to set that selected image in a picture box then convert the image in the image box to byte array and save sql server data base in a image type column.
In browse button click event I'm selecting the image file like this.
OpenFileDialog fop = new OpenFileDialog();
fop.InitialDirectory = #"Desktop";
fop.Filter = "image files|*.jpg;*.png;*.gif";
if (fop.ShowDialog() == DialogResult.OK)
{
FileStream FS = new FileStream(#fop.FileName, FileMode.Open, FileAccess.Read);
pbPartySymbol.Image = new Bitmap(fop.FileName);
MessageBox.Show("Image Imported Successfully!!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
After selecting the image and setting it the picture box image I'm converting the picture box image to byte array in the save button click event and saving the byte array to database.
public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
I'm calling the method like this.
byte[] myArr1 = imageToByteArray(pbPartySymbol.Image);
and I'm passing this byte array to the data base. and it saves too. But ALL the added images are saved as like this.* 0x53797374656D2E427974655B5D* Saved images cannot be get back to the picture box in the reading operation. What am I doing wrong in the SAVING?
Here's what I do in saving operation in the form.
Party ptObj = new Party(myArr1);
if (new PartyOP().saveParty(ptObj))
{
MessageBox.Show("NEW data added");
}
In my business operation layer this is my code.
public Boolean saveParty(Party ptObj)
{
string query1 = "EXEC insertToParty'" + ptObj.PTSymARR + "'";
return (new DataAccessLayer().executeNonQueries(query1));
}
Here's how I have set the property in the Party class.
class Party
{
public Party() { }
public Party(byte[] ptSym)
{
this._PTSymARR = ptSym;
}
public byte[] PTSymARR
{
get { return _PTSymARR; }
set { _PTSymARR = value; }
}
}
here's my stored procedure.
CREATE PROCEDURE insertToParty
(
#ptSymbol image
)
AS
BEGIN
BEGIN TRANSACTION
SET NOCOUNT ON;
--Query
INSERT INTO Party(PTSYM)
VALUES (#ptSymbol);
Data type of PTSYM is image data type.
That Hex string tranlates to System.Byte[].
You add the Byte-Array to the string starting with EXEC insertToParty so .Net assumes you want a string representation of that variable. Unless specified it calls .ToString wich gives you .... "System.Byte[]".
Edit: Your stored procedure does not use hex encoding on insert. image data shows in hex when viewed in SQL Studio etc.
If you would encode your byte array to a string using base64 or hex when inserting and decode that when you read the data you only had to worry about the increased storage, but I recommend that you change your db acces from a dynamic SELECT to a prepared statement with parameters:
SqlCommand command = new SqlCommand("Exec InsertToParty(#blob)");
command.Parameters.AddWithValue("#blob", ptObj.PTSymARR);
command.ExecuteNonQuery();
Related
I want to compare an uploaded pic with all images in database , if it is matching then should display data with image , the compare is simple by converting each image to binary see this
I am using this code but its not working:
protected void CompareImages(object sender, EventArgs e)
{
if (this.FileUpload1.HasFile)
{
Stream fs = FileUpload1.PostedFile.InputStream;
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
string constr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
using (SqlConnection conn = new SqlConnection(constr))
{
string sqlQuery = "SELECT * from [MostWanted] WHERE Photo = #FileName";
using (SqlCommand cmd = new SqlCommand(sqlQuery, conn))
{
cmd.Parameters.AddWithValue("#FileName", Path.GetFileName(this.FileUpload1.PostedFile.FileName));
conn.Open();
Byte[] bytes2 = (Byte[])cmd.ExecuteScalar();
conn.Close();
if (bytes2 != null)
{
if (bytes.Length == bytes2.Length)
{
ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('Equal Images')", true);
}
else
{
ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('Images are not equal')", true);
}
}
else
{
ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('File Not found in the table')", true);
}
}
}
}
}
Unless those images are literally copies of the same file, a simple binary comparision will not work. Even one bit difference or a different file format will utterly break it. And that that point recognising them as the same goes into Artificial Intelligence Research.
If those files are the same down to the last byte, you could relevantly speed up the check by storing a hashvalue for every image. Compare the hash of the image you try to add with all existing image hashes to pre-filter wich ones can not be the same. You still should do a binary comparision, as even with hash values you can have wrong positives/colissions (two different inputs having the same output) happen.
As you are also planning to store a lot of images, I think the filestream atribute might help: https://www.simple-talk.com/sql/learn-sql-server/an-introduction-to-sql-server-filestream/
Have column named data varbinary(max) to store the image file
Query statement need not have where condition
Remove the add parameter line. It works perfectly then, by comparing binary data alone
So I collect a varbinary(MAX) value from a database where an image is stored.
It gets converted to byte[], then the aim is to display this in an image control.
This is where I read from the database
public TemplateData(SqlDataReader dr)
{
initialiseData();
if (dr.HasRows)
{
Logo = (byte[])dr["Logo"];
//Logo = dr["Logo"].ToString();
TemplateId = dr["TemplateId"].ToString();
Comment = dr["Comment"].ToString();
SchemeCode = dr["SchemeCode"].ToString();
Version = dr["Version"].ToString();
}
}
This is where the values are displayed into the corresponding controls
protected void ddSchemeCode_SelectedIndexChanged(object sender, EventArgs e)
{
if (ddSchemeCode.SelectedIndex > 0)
{
// Existing Data to load from database
TemplateData temp = DataClass.ReturnData(ddSchemeCode.SelectedItem.Text);
if (temp != null)
{
txtVersion.Text = temp.Version;
txtComment.Text = temp.Comment;
txtSchemeCode.Text = temp.SchemeCode;
txtTemplateId.Text = temp.TemplateId;
img.Src = temp.Logo;
}
So at the moment I am passing a byte[] into the source of an image control, where it would instead like a string. I've tried converting it to a string with Convert.ToBase64String(Logo) and ToString(Logo) but these do not work.
Any help is greatly appreciated. Cheers guys and gals.
Try converting the byte array to image and assign it to picturebox as below,
try
{
using (MemoryStream mStream = new MemoryStream())
{
// where pData is your byte array
mStream.Write(pData, 0, Convert.ToInt32(pData.Length));
Image originalImage = Image.FromStream(mStream);
picBox.Image = originalImage;
}
}
catch (Exception ex)
{
}
Hope it helps.
As you may have noticed, you cannot "print" an image in a webpage. You need to get a little bit creative now.
What you want to look into is Response.BinaryWrite. More information about that, here: https://msdn.microsoft.com/en-us/library/system.web.httpresponse.binarywrite%28v=vs.110%29.aspx
You will probably also need a generic ashx handler. Here is an example of how to show a picture using a handler: http://www.dotnetperls.com/ashx
My suggestion would be to store the logo as a byte[] into the http session. Put the source of the image to theHttpHandlerYourGonnaCreate.ashx. You can then binary write the byte[] you've stored into the session there.
Hope this helps!
As Michael shows here, you can convert the byte array to a Bitmap object with something like this:
Bitmap bitmap = null;
using (MemoryStream imageStream = new MemoryStream(imageData))
{
bitmap = new Bitmap(imageStream);
}
It isn't entirely clear what you're using for a control to show the image, but any control that can display an image should be able to take a Bitmap or Image object.
I have a PictureBox with an image and a delete button. The image is stored in a varbinary(MAX) format in the database. How do I delete it when the delete button is pressed?
I'm using this code to save an image into the database:
byte[] data;
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
conn.Open();
Image img = pictureBox1.Image;
img.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
data = stream.ToArray();
cmd.CommandText = "insert into images values(#images)";
cmd.Parameters.AddWithValue("#images", data);
int res = cmd.ExecuteNonQuery();
MessageBox.Show("success");
}
I don't see why the following wouldn't work.
cmd.CommandText = "delete from images where ID = x";
Sending plain SQL like this is getting fairly outdated and can be down right dangerous when implemented with a UI improperly, you should strongly consider using LINQ
http://en.wikipedia.org/wiki/Language_Integrated_Query
I want if user do not set image for picturebox save empy image in table .
my code is :
byte[] arrImage;
if (picperson.Image != null)
{
//convert image to byte
MemoryStream ms = new MemoryStream();
picperson.Image.Save(ms, picperson.Image.RawFormat);
arrImage = ms.GetBuffer();
ms.Close();
}
else arrImage = null;
objcommand.Parameters.AddWithValue("#picture", arrImage);
when he adds null image, exception occurs on line picperson.Image.Save(ms, picperson.Image.RawFormat);
How to add empty imag to table ?
You can't pass a null value for your image parameter, so a work around would be to send in a zero byte array:
if (picperson.Image != null) {
//convert image to byte
} else {
arrImage = new byte[0];
}
Unfortunately, that will not set the field to null.
To set the field to null would probably be handled best with a separate query, for example:
using (SqlCommand q = new SqlCommand("INSERT INTO M (MyImage) VALUES (null)", cn)
...
which does not use parameters.
As far as reading some of the comments are concerned, it sounds like the image format needs to be specified. Try using the actual format that you want the image saved as:
picperson.Image.Save(ms, ImageFormat.Bmp);
// or
picperson.Image.Save(ms, ImageFormat.Jpeg); // or Png, etc.
this may be impossible, or rather, not very popular, but I was wondering how I'd go about creating a data file for images, that would actually compress them? Say I had 200MB total of image files, is there some system I can use to store them in a single file, that would compress them to a total size of like 150MB? (Just example numbers, ratios not important).
I know I can encode the images with Base64 and then store them in an SQLite database, but I read that storing images in their encoded forms actually resulted in a slightly larger size than the original image file itself.
I was also thinking of a ZIP file, but I wasn't sure if it could be used as a 'library' as such?
If something like this doesn't exist as a predefined class, could someone lead me on the right track?
This is a mock of what I'm sort of looking for:
class ImageLibrary {
//this is where the code would go for the library?
}
class MyProgram{
public MyProgram()
{
ImageLibrary library = new ImageLibrary();
library.Add(<Image object here, with an ID of sorts>);
library.Add(<Another image object here, also with an ID>);
Load += new FormLoadEventHandler(MyProgram_Load);
}
void MyProgram_Load(object sender, EventArgs e)
{
PictureBox.Image = library.Get(<image id here>);
}
}
I hope this is possible. Else, I'll just put up with a slightly larger file size and Base64 encode them. But, because I have, at the moment, almost 500 images I want to store, a kB saved is a kB earned. :) Also, please don't judge the quality of my code example, it's just a mock up and I wrote it off the cuff.
Cheers, and thankyou in advance.
If save your images as binary files will help this is a code I use to convert them to binary and then save into SQLite:
public byte[] ImageToByte(Image image, System.Drawing.Imaging.ImageFormat format){
using (MemoryStream ms = new MemoryStream())
{
// Convert Image to byte[]
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();
return imageBytes;
}
}
public Image ByteToImage(byte[] imageBytes)
{
// Convert byte[] to Image
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
ms.Write(imageBytes, 0, imageBytes.Length);
Image image = new Bitmap(ms);
return image;
}
And then to save the binary:
void SaveImage(byte[] image){
string conStringDatosUsuarios = #" Data Source = \Program Files\GPS___CAM\Data\DatosUsuarios.s3db ";
SQLiteConnection con = new SQLiteConnection(conStringDatosUsuarios);
SQLiteCommand cmd = con.CreateCommand();
cmd.CommandText = String.Format("INSERT INTO Users (Foto) VALUES (#0);");
SQLiteParameter p = new SQLiteParameter("#0", System.Data.DbType.Binary);
p.Value = image;
cmd.Parameters.Add(p);
con.Open();
try
{
cmd.ExecuteNonQuery();
}
catch (Exception exc1)
{
MessageBox.Show(exc1.Message);
}
con.Close();
}
Hope it helps
EDIT As you asked, I'm updating with the load image code:
(to convert the byte to image you must use the ByteToImage function)
void LoadImage(string tag){
string query = "SELECT Foto FROM Users;";
string conString = #" conection to your database ";
SQLiteConnection con = new SQLiteConnection(conString);
SQLiteCommand cmd = new SQLiteCommand(query, con);
con.Open();
try
{
SQLiteDataReader rdr = cmd.ExecuteReader();
try
{
while (rdr.Read())
{
pictureBox1.Image = ByteToImage((System.Byte[])rdr[0]);
}
}
catch (Exception exc) { MessageBox.Show(exc.Message); }
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
con.Close();
}
EDIT 2 Try this to see which type of data are you trying to load:
System.Type checkType = rdr[0].GetType();
pictureBox1.Image = ByteToImage((System.Byte[])rdr[0]);
add the first line in your code and put a breakpoint in that line. Check checkType's type. Probably it isn't binary. Let me know the result to help you.
Check out this article: http://msdn.microsoft.com/en-us/library/aa479502.aspx
I hope it helps. An idea for accessing files from a ZIP. It's not ready-to-use solution, but a nice concept explanation.