Sky Scraper
Sky Scraper

Reputation: 185

How to save a PictureBox Image in DB

when i try to capture an image to my webcam in VB.NET using Emgu and copy it into another PictureBox in another Form with this code Form23.PictureBox1.Image = New Bitmap(captureImageBox.Image) and try to save it in my database, it doesn't save and an error appears like this Empty path name is not legal but the picture is there and copied from the webcam PictureBox.

this is my code in saving the image in database:

Dim a As OpenFileDialog = New OpenFileDialog

SQL = "UPDATE candidate SET photo='" photo=@photo WHERE idn='" & cd & "'"
        Dim sqlCommand As New MySqlCommand
        sqlCommand.Parameters.Add("@photo", MySqlDbType.LongBlob)
        sqlCommand.Parameters("@photo").Value = IO.File.ReadAllBytes(a.FileName)

       With sqlCommand
            .CommandText = SQL
            .Connection = sConnection
            .ExecuteNonQuery()

but if i save an image from OpenFileDialog it saves. why can't it be?hmm is there a problem in my code in copying the Image from PictureBox to another?

UPDATE

tried this but it doesn't work either:

Replaced this:

sqlCommand.Parameters.Add("@photo", MySqlDbType.LongBlob)
        sqlCommand.Parameters("@photo").Value = IO.File.ReadAllBytes(a.FileName)

       With sqlCommand
            .CommandText = SQL
            .Connection = sConnection
            .ExecuteNonQuery()

with this one:

Dim ms As New IO.MemoryStream()
PictureBox1.Image.Save(ms, PictureBox1.Image.RawFormat)
Dim data As Byte() = MS.GetBuffer()
Dim p As New MySqlParameter("@photo", MySqlDbType.LongBlob)
p.Value = data
cmd.Parameters.Add(p)
sqlCommand.Parameters.Add("@cd", MySqlDbType.Int32).Value = cd
cmd.ExecuteNonQuery()

Upvotes: 1

Views: 17759

Answers (3)

Caveat: I have no idea what role the FileDialog plays in all this. Saving an image from a PictureBox to a database does not involve a File or a FileDialog. This address the Title question, not the updates where files and dialogs creep in.

First, consider not storing an image, but the name of an archived copy of the filename. You can mangle these as in <id>_<orgfilename>.<ext> if you want to embed the ID to the disk file.

To save a picturebox image, it needs to be converted to as byte array. Net includes a type converter for that:

Dim imgData As Byte()         ' storage for the img bytes

Dim cvt As New ImageConverter
imgData = CType(cvt.ConvertTo(myImage, GetType(Byte())), Byte())

It works (usually), but it also does boxing back and forth from Object (the CType) and issues with the ImageFormat it selects bug me. Doing it yourself is very simple:

' this is easily used from a class or converted to an extension
Public Shared Function ImgToByteArray(img As Image, imgFormat As ImageFormat) As Byte()
    Dim tmpData As Byte()
    Using ms As New MemoryStream()
        img.Save(ms, imgFormat)

        tmpData = ms.ToArray
    End Using              ' dispose of memstream
    Return tmpData
End Function

This is pretty much what the TypeConverter does without the boxing, but the code controls the format. Then save the byte array to the db:

Dim imgData As Byte()         ' storage for the img bytes
imgData = ImgToByteArray(PictureBox1.Image, ImageFormat.Jpeg)

...
sqlCommand.Parameters("@photo").Value = imgData 

If you want a more generic procedure to save from file or picturebox, create a procedure which accepts a byte array as a param. The button click for Save PictureBoxImage can convert the image to byte array and pass it, as can the other button working from a file:

Function SaveRecord(ingData As Byte(),...other params...) As Boolean

Note: Do not use GetBuffer. See MSDN MemoryStream.GetBuffer:

Note that the buffer contains allocated bytes which might be unused. For example, if the string "test" is written into the MemoryStream object, the length of the buffer returned from GetBuffer is 256, not 4, with 252 bytes unused. ...

On a 968,012 byte file, .ToArray returns the proper size, GetBuffer returns 1,719,296 with all elements after 968012 being Null.


With just a little work you can create a class of image helpers:

Public Class myImaging

    ' image to byte array from file name
    Public Shared Function ImgToByteArray(imgFile As String, 
                imgFormat As ImageFormat) As Byte()
       ...

    ' the one above
    Public Shared Function ImgToByteArray(img As Image, 
           imgFormat As ImageFormat) As Byte()
       ...

    ' going the other way Bytes() --> Image
    Public Shared Function ImgFromByteArray(b As Byte()) As Image
       ...

    ' shrink img and scale it
    Public Shared Function ImgToThumb(img As Image, maxSize As Size) As Image

End Class

Then it is just: imgData = myImaging.ImgToByteArray(picturebox84.Image)

Upvotes: 3

Sky Scraper
Sky Scraper

Reputation: 185

got the answer!

Dim cn As New MySqlConnection("server = localhost; user id = root; database = db; password = root")
        Dim sqlQuery As String = "UPDATE candidate SET cpos=@cpos, cparty=@cparty, candidacy='Filed', photo=@photo WHERE idn=@cd"
        Dim sqlcom As New MySqlCommand(sqlQuery, cn)
        Dim ms As New IO.MemoryStream()
        PictureBox1.Image.Save(ms, Imaging.ImageFormat.Jpeg)
        Dim data As Byte() = ms.GetBuffer()
        Dim p As New MySqlParameter("@photo", MySqlDbType.LongBlob)
        p.Value = data
        sqlcom.Parameters.Add(p)
        sqlcom.Parameters.AddWithValue("@cpos", ComboBox1.Text)
        sqlcom.Parameters.AddWithValue("@cparty", TextBox1.Text)
        sqlcom.Parameters.Add("@cd", MySqlDbType.Int32).Value = cd
        cn.Open()
        sqlcom.ExecuteNonQuery()

Upvotes: 0

Joel Coehoorn
Joel Coehoorn

Reputation: 416131

Dim a As OpenFileDialog = New OpenFileDialog
'...

SQL = "UPDATE candidate SET photo= @photo WHERE idn= @cd"
Dim sqlCommand As New MySqlCommand(SQL, sConnection)
sqlCommand.Parameters.Add("@photo", MySqlDbType.LongBlob).Value = IO.File.ReadAllBytes(a.FileName)
sqlCommand.Parameters.Add("@cd", MySqlDbtype.Int32).Value = cd

sConnection.Open()
sqlCommand.ExecuteNonQuery()

Upvotes: 0

Related Questions