cannot retrive image from sql server to vb .net form - vb.net

I am trying to display user with image using id; it throws an exception
Conversion from type 'Byte()' to type 'Byte' is not valid.
When I remove image code; its working fine displaying other data.
If rdbtninvestigator.Checked = True Then
Dim mycmd1 As New SqlCommand("Select * From investigator where id=#id ", connection)
mycmd1.Parameters.Add("#id", SqlDbType.VarChar).Value = txtid1.Text
Dim table As New DataTable
Dim adapter As New SqlDataAdapter(mycmd1)
adapter.Fill(table)
If table.Rows.Count > 0 Then
lblid.Text = table.Rows(0)(0).ToString()
lblname.Text = table.Rows(0)(1).ToString()
lblusername.Text = table.Rows(0)(2).ToString()
txtpassword.Text = table.Rows(0)(3).ToString()
Dim img As Byte
img = table.Rows(0)(4)
Dim ms As New MemoryStream(img)
picuser.Image = Image.FromStream(ms)
btnupdate.Enabled = True
btndelete.Enabled = True
Else
MsgBox("Account does not exist")
btnupdate.Enabled = False
btndelete.Enabled = False
End If

Images stored in databases are stored as a byte array. The error message you're getting say you are attempting to store the image in a byte variable, not a byte array.
The line of code you need to add/correct is:
Dim image As Byte()
That line creates a variable of type Byte(), a byte array.

Related

VB.NET I generated pictureboxes and LOOP it to my rows.Count, the problem is how can i call the PHOTOS?

So basically i generated picture boxes through codes to increment it whenever i ADD data in my database.. my problem is how can i get the PHOTOS from my database to be in my picture boxes.
Here is my code:
connection.Open()
cmd.Connection = connection
cmd.CommandType = CommandType.Text
cmd.CommandText = "SELECT ID, Candidate_Name, Candidate_Fname,c_Photo from softeng.candidates"
da.SelectCommand = cmd
da.Fill(pdt)
For j As Integer = 0 To pdt.Rows.Count - 1
Dim a As String = pdt.Rows(j).Item(0)
Dim b As String = pdt.Rows(j).Item(1)
Dim c As String = pdt.Rows(j).Item(2)
Dim pb As New PictureBox
Dim lb As New Label
lb.Name = "lbid" & j
lb.Text = "Candidate ID:" & a & vbCrLf & b + c & vbCrLf
lb.AutoSize = True
lb.Size = New Point(100, 100)
pb.Name = "pb" & j
pb.Text = a
pb.AutoSize = True
pb.Size = New Point(100, 100)
pb.BorderStyle = BorderStyle.Fixed3D
FlowLayoutPanel1.Controls.Add(pb)
FlowLayoutPanel1.Controls.Add(lb)
Next
connection.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
My codes for retrieving Pictures from my Database
Dim data As Byte() = DirectCast(dr("Photo"), Byte())
Dim ms As New MemoryStream(data)
PictureBox1.Image = Image.FromStream(ms)
How can i put it to my code so i can retrieve photos when im looping my picture boxes?
Basically, you must make sure you are saving the images as binaries in database, then basically you read the binary information and convert it to an image object, showing in your control.
I'm pretty sure the link below has everything you need:
https://www.aspsnippets.com/Articles/Display-Binary-Image-from-Database-in-PictureBox-control-in-Windows-Application-using-C-and-VBNet.aspx

datagridview Image Display vb.net MS Access

my code is to read the image file path in every row and display it in the datagridview "Image" Column.
.....
what's the problem with my code? please help me fix this.
UPDATE
this is the updated code but it displays nothing.
Dim dbdataset As New DataTable
Try
con.Open()
query = "Select * FROM [svfmemberlist]"
cmd = New OleDbCommand(query, con)
da.SelectCommand = cmd
da.Fill(dbdataset)
dgvSearch.RowTemplate.Height = 150
source.DataSource = dbdataset
dgvSearch.DataSource = source
Dim img As New DataGridViewImageColumn()
dgvSearch.Columns.Add(img)
img.HeaderText = "Image"
img.Name = "img"
img.ImageLayout = DataGridViewImageCellLayout.Zoom
dgvSearch.Columns("img").DataGridView.AutoGenerateColumns = False
dgvSearch.Columns("Name").AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
dgvSearch.Columns("img").Width = 150
For Each row As DataGridViewRow In dgvSearch.Rows
If Not row.Cells("imgPath").FormattedValue.ToString = Nothing Then
Dim str As String = row.Cells("imgPath").FormattedValue.ToString
Dim inImg As Image = Image.FromFile(str)
row.Cells("img").Value = inImg
Else
img.Image = Nothing
End If
Next
con.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
The following example does not match how you are loading data and images but with a little effort will work within your current code.
I created two columns in the DataGridView via the IDE, one Text and one Image DataGridViewColumn.
The first line in form load sets ImageLayout, second line of code sets alignment to top-left for appearances. Next I set auto-size mode for all columns followed by setting the row height for each row.
Next (these lines are to load images from a folder one level below the app folder).
Setup the path to the images.
Add images using FileImageBytes function (which I would place into a separate class or code module but works just fine in your form).
Yes everything is hard-wired so it's easy to see how everything works.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CType(DataGridView1.Columns("PictureColumn"), DataGridViewImageColumn).ImageLayout = DataGridViewImageCellLayout.Normal
DataGridView1.Columns.Cast(Of DataGridViewColumn).Select(Function(col) col).ToList _
.ForEach(Sub(col) col.CellTemplate.Style.Alignment = DataGridViewContentAlignment.TopLeft)
DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
DataGridView1.RowTemplate.Height = 222
Dim imagePath As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images")
DataGridView1.Rows.Add(New Object() {"Car1", FileImageBytes(IO.Path.Combine(imagePath, "Car1.bmp"))})
DataGridView1.Rows.Add(New Object() {"Car2", FileImageBytes(IO.Path.Combine(imagePath, "Car2.jpg"))})
End Sub
Public Function FileImageBytes(ByVal FileName As String) As Byte()
Dim fileStream As IO.FileStream = New IO.FileStream(FileName, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
Dim byteArray(CInt(fileStream.Length - 1)) As Byte
fileStream.Read(byteArray, 0, CInt(fileStream.Length))
Return byteArray
End Function
End Class

Image.FromStream is not a member of System.Windows.Forms.DataGridViewImageColumn

So I use this code to display my data in a DataGridView:
Sub display_Infodata()
DGUSERS.Rows.Clear()
Dim sql As New MySqlDataAdapter("select * from tbl_info", con)
Dim ds As New DataSet
DGUSERS.AllowUserToAddRows = False
DGUSERS.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
DGUSERS.RowTemplate.Height = 40
sql.Fill(ds, 0)
For i As Integer = 0 To ds.Tables(0).Rows.Count - 1
Dim xx As Integer = DGUSERS.Rows.Add
Dim uid As String = ds.Tables(0).Rows(i).Item(0).ToString
Dim sqls As New MySqlDataAdapter("select * from tbl_other where userid='" & uid & "'", con)
Dim dss As New DataSet
sqls.Fill(dss, 0)
With DGUSERS.Rows(xx)
If dss.Tables(0).Rows.Count > 0 Then
.Cells(0).Value = uid
.Cells(1).Value = ds.Tables(0).Rows(i).Item(2).ToString
.Cells(2).Value = ds.Tables(0).Rows(i).Item(3).ToString
.Cells(3).Value = ds.Tables(0).Rows(i).Item(4).ToString
.Cells(4).Value = ds.Tables(0).Rows(i).Item(5).ToString
.Cells(5).Value = ds.Tables(0).Rows(i).Item(6).ToString
.Cells(6).Value = dss.Tables(0).Rows(0).Item(1).ToString
.Cells(7).Value = ds.Tables(0).Rows(0).Item(2).ToString
.Cells(8).Value = ds.Tables(0).Rows(0).Item(8).ToString
.Cells(9).Value = ds.Tables(0).Rows(0).Item("Image")
.Cells(10).Value = dss.Tables(0).Rows(0).Item(2).ToString
.Cells(11).Value = dss.Tables(0).Rows(0).Item(3).ToString
Else
End If
End With
Next
End Sub
It displays and works, but my problem is that when I try to display the data in the DataGridView of another form it shows the following error:
This is what I use:
Try
With View_Info
Dim index As Integer
Dim selectedRow As DataGridViewRow
selectedRow = DGUSERS.Rows(index)
.UserID.Text = DGUSERS.SelectedRows(0).Cells("UserID").Value
.UserType.Text = DGUSERS.SelectedRows(0).Cells("UserType").Value
.Fname.Text = DGUSERS.SelectedRows(0).Cells("Firstname").Value
.Mname.Text = DGUSERS.SelectedRows(0).Cells("Middlename").Value
.Lname.Text = DGUSERS.SelectedRows(0).Cells("Lastname").Value
.Contact.Text = DGUSERS.SelectedRows(0).Cells("Contact").Value
.Standing.Text = DGUSERS.SelectedRows(0).Cells("Standing").Value
.Guardian.Text = DGUSERS.SelectedRows(0).Cells("Guardian").Value
.ContactG.Text = DGUSERS.SelectedRows(0).Cells("GuardianContact").Value
.DPCreated.Text = DGUSERS.SelectedRows(0).Cells("DateCreated").Value
.DPValidity.Text = DGUSERS.SelectedRows(0).Cells("Validity").Value
Dim img As Byte()
img = DGUSERS.SelectedRows(0).Cells("Image").Value
Dim ms As New MemoryStream(img)
.UploadImage.Image = Image.FromStream(ms)
.Show()
.Focus()
End With
Catch ex As Exception
MsgBox(ex.Message & " Please select a corresponding records.", MsgBoxStyle.Exclamation)
End Try
Any help please?
It's hard to see the full picture, but the problem is most likely that you have created a DataGridViewImageColumn which you've chosen to call Image.
The compiler will always choose local variables, properties or classes over library/pre-imported namespace objects with the same name. Thus, your column by the name Image will be used rather than System.Drawing.Image because the former is "more local".
Try specifying the namespace as well and it should work:
.UploadImage.Image = System.Drawing.Image.FromStream(ms)
So what I did to solve this is by:
Dim pCell As New DataGridViewImageCell
pCell = Me.DGUSERS.Item("Picture", e.RowIndex)
.UploadImage.Image = byteArrayToImage(pCell.Value)
and using this function:
Private Function byteArrayToImage(ByVal byt As Byte()) As Image
Dim ms As New System.IO.MemoryStream()
Dim drwimg As Image = Nothing
Try
ms.Write(byt, 0, byt.Length)
drwimg = New Bitmap(ms)
Finally
ms.Close()
End Try
Return drwimg
End Function

Crop image and save it in database using vb.net

I'm following a tutorial on Image Cropping with resizing using vb.net . Everything works well, But instead of saving it
on the hard disk. I want to save it on my database(SQLServer).
This is the code of saving on a disk
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cropSaveBtn.Click
Dim tempFileName As String
Dim svdlg As New SaveFileDialog()
svdlg.Filter = "JPEG files (*.jpg)|*.jpg|All files (*.*)|*.*"
svdlg.FilterIndex = 1
svdlg.RestoreDirectory = True
If svdlg.ShowDialog() = Windows.Forms.DialogResult.OK Then
tempFileName = svdlg.FileName 'check the file exist else save the cropped image
Try
Dim img As Image = PreviewPictureBox.Image
SavePhoto(img, tempFileName, 225)
Catch exc As Exception
MsgBox("Error on Saving: " & exc.Message)
End Try
End If
End Sub
Public Function SavePhoto(ByVal src As Image, ByVal dest As String, ByVal w As Integer) As Boolean
Try
Dim imgTmp As System.Drawing.Image
Dim imgFoto As System.Drawing.Bitmap
imgTmp = src
imgFoto = New System.Drawing.Bitmap(w, 225)
Dim recDest As New Rectangle(0, 0, w, imgFoto.Height)
Dim gphCrop As Graphics = Graphics.FromImage(imgFoto)
gphCrop.SmoothingMode = SmoothingMode.HighQuality
gphCrop.CompositingQuality = CompositingQuality.HighQuality
gphCrop.InterpolationMode = InterpolationMode.High
gphCrop.DrawImage(imgTmp, recDest, 0, 0, imgTmp.Width, imgTmp.Height, GraphicsUnit.Pixel)
Dim myEncoder As System.Drawing.Imaging.Encoder
Dim myEncoderParameter As System.Drawing.Imaging.EncoderParameter
Dim myEncoderParameters As System.Drawing.Imaging.EncoderParameters
Dim arrayICI() As System.Drawing.Imaging.ImageCodecInfo = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()
Dim jpegICI As System.Drawing.Imaging.ImageCodecInfo = Nothing
Dim x As Integer = 0
For x = 0 To arrayICI.Length - 1
If (arrayICI(x).FormatDescription.Equals("JPEG")) Then
jpegICI = arrayICI(x)
Exit For
End If
Next
myEncoder = System.Drawing.Imaging.Encoder.Quality
myEncoderParameters = New System.Drawing.Imaging.EncoderParameters(1)
myEncoderParameter = New System.Drawing.Imaging.EncoderParameter(myEncoder, 60L)
myEncoderParameters.Param(0) = myEncoderParameter
imgFoto.Save(dest, jpegICI, myEncoderParameters)
imgFoto.Dispose()
imgTmp.Dispose()
Catch ex As Exception
End Try
End Function
I want it to save the picture to SQL Server 2008 (Image data type) together with my two data just like this
Using cmd As New SqlClient.SqlCommand("dbo.uspAdd", cn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#firstname", SqlDbType.VarChar, 100).Value = txtName.Text
cmd.Parameters.Add("#lastName", SqlDbType.VarChar, 100).Value = txtSurname.Text
'add insert picture code here
cmd.ExecuteNonQuery()
MsgBox("Save Record New record Successfully")
End Using
And now i'm stuck for almost 8 hours finding ways on how to fix this.Can anyone help me to solve this. Any help would be very much appreciated.
I would suggest converting the image to Base64 and then storing it as a string.
Then when you want to get the image back you need to convert it back from Base64 to an image.
You can convert an image to Base64 using this code:
Public Function ConvertImageToBase64(ByRef img As Image, ByVal format As System.Drawing.Imaging.ImageFormat) As String
Dim ImgStream As MemoryStream = New MemoryStream()
img.Save(ImgStream, format)
ImgStream.Close()
Dim ByteArray() As Byte = ImgStream.ToArray()
ImgStream.Dispose()
Return Convert.ToBase64String(ByteArray)
End Function
(http://www.dailycoding.com/posts/convert_image_to_base64_string_and_base64_string_to_image.aspx)
And to convert it back to an image you can use this code:
Public Function ConvertBase64ToImage(ByVal base64 As String) As Image
Dim img As System.Drawing.Image
Dim MS As System.IO.MemoryStream = New System.IO.MemoryStream
Dim b64 As String = base64.Replace(" ", "+")
Dim b() As Byte
b = Convert.FromBase64String(b64)
MS = New System.IO.MemoryStream(b)
img = System.Drawing.Image.FromStream(MS)
Return img
End Function
(http://snipplr.com/view/27514/vbnet-base64-to-image/)
Now you can basically add the image as a string, like this:
Dim Base64Bitmap As String = ConvertImageToBase64(img, System.Drawing.Imaging.ImageFormat.Png)
cmd.Parameters.Add("#Image", SqlDbType.VarChar, Base64Bitmap.Length).Value = Base64Bitmap

SQL Download Image into Picture Box 'Out of Memory' Error

*strong text*Okay, I've got a test application which is just to test the Uploading and Downloading of images to/from an SQL Server. The upload code works, but when I try to retrieve the image from the SQL Server I receive an 'Out of Memory' error. However, when I change the picturebox from .BackGroundImage to just .Image the code works flawlessly.
I require the image to be in the format of a BackGoundImage so that I can easily change the size of the image (center, stretch ect).
The error:
An unhandled exception of type 'System.OutOfMemoryException' occurred
in System.Drawing.dll
Additional information: Out of memory.
The code for retrieving the image from the SQL Server is:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
'Retrieve Image
GroupBox2.BringToFront()
GroupBox2.Visible = True
Label1.Visible = False
TextBox1.Visible = False
con.Open()
Dim cmd As New SqlCommand("SELECT DP FROM PersonsA WHERE Members_ID = 1", con)
cmd.CommandType = CommandType.Text
Dim ImgStream As New IO.MemoryStream(CType(cmd.ExecuteScalar, Byte()))
PictureBox2.BackgroundImage = Image.FromStream(ImgStream, False, True)
ImgStream.Dispose()
con.Close()
End Sub
The error highlights the PictureBox2.BackgroundImage = Image.FromStream(ImgStream, False, True) line.
Additional information:
Only 1 row is expected as Members_ID is Primary Key.
SQL Server is MS SQL Server + Management Studio.
The DP Column is formatted as 'Image' and stores the picture like this:
0xFFD8FFE000104A46494600010201000000000000FF....
Here's the upload image code (WORKING)
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'Upload Image
con.Open()
Dim cmd As New SqlCommand("UPDATE PersonsA SET DP=#DP WHERE Members_ID = 1", con)
Dim ms As New MemoryStream()
PictureBox1.BackgroundImage.Save(ms, PictureBox1.BackgroundImage.RawFormat)
Dim data As Byte() = ms.GetBuffer()
Dim p As New SqlParameter("#DP", SqlDbType.Image)
p.Value = data
cmd.Parameters.Add(p)
cmd.ExecuteNonQuery()
MessageBox.Show("Image has been saved", "Save", MessageBoxButtons.OK)
Label1.Visible = False
TextBox1.Visible = False
con.Close()
Imports and Dims
Imports System.Data.SqlClient
Imports System.IO
Public Class Form1
'path variable use for Get application running path
Dim path As String = (Microsoft.VisualBasic.Left(Application.StartupPath, Len(Application.StartupPath) - 9))
Dim con As New SqlConnection("CONNECTION_STRING;")
Dim cn As New SqlConnection("CONNECTION_STRING;")
Dim cmd As SqlCommand
Any ideas on why I'm receiving the 'Out of Memory Error'? The program is tiny and doesn't seam to be using excessive amounts of RAM so it has to be with my code...
[EDIT 1]
Following Jaques very helpful advice I've changed my code to the following - note there's two errors as read is not declared - what should that be declared as?
Dim cmd As New SqlCommand("SELECT DP FROM PersonsA WHERE Members_ID = 1", con)
cmd.CommandType = CommandType.Text
Dim Buffersize As Integer = 4096
Dim retval As Long = 0
Dim TempLen1 As Long = 0
Dim startindex As Long = 0
Dim reference_temp As [Byte]() = New [Byte](4095) {}
Dim RefTemp As New List(Of Byte)()
Dim Read As
retval = read.GetBytes(0, startindex, reference_temp, 0, buffersize)
'0 is the first Column
TempLen1 += retval
While retval = buffersize
RefTemp.AddRange(reference_temp)
startindex += buffersize
retval = read.GetBytes(0, startindex, reference_temp, 0, buffersize)
TempLen1 += retval
End While
RefTemp.AddRange(reference_temp)
Dim Reference_temp1 As Byte() = RefTemp.GetRange(0, CInt(TempLen1)).ToArray()
End Sub
[EDIT 2]
I'm now receiving an error on the retval - read.GetBytes(16, startindex.... line.
An unhandled exception of type 'System.InvalidOperationException'
occurred in Microsoft.VisualBasic.dll
Additional information: Invalid attempt to read when no data is
present.
My code so far:
'Retrieve Image
GroupBox2.BringToFront()
GroupBox2.Visible = True
Label1.Visible = False
TextBox1.Visible = False
con.Open()
Dim cmd As New SqlCommand("SELECT DP FROM PersonsA WHERE Members_ID = 1", con)
cmd.CommandType = CommandType.Text
Dim read = cmd.ExecuteReader
Dim Buffersize As Integer = 4096
Dim retval As Long = 0
Dim TempLen1 As Long = 0
Dim startindex As Long = 0
Dim reference_temp As [Byte]() = New [Byte](4095) {}
Dim RefTemp As New List(Of Byte)()
retval = read.GetBytes(16, startindex, reference_temp, 16, Buffersize)
'0 is the first Column
TempLen1 += retval
While retval = buffersize
RefTemp.AddRange(reference_temp)
startindex += buffersize
retval = read.GetBytes(16, startindex, reference_temp, 16, Buffersize)
TempLen1 += retval
End While
RefTemp.AddRange(reference_temp)
Dim Reference_temp1 As Byte() = RefTemp.GetRange(16, CInt(TempLen1)).ToArray()
Dim ImgStream As New IO.MemoryStream(Reference_temp1)
PictureBox2.BackgroundImage = Image.FromStream(ImgStream, False, True)
ImgStream.Dispose()
Why don't you use the GetBytes from a DataReader like (Its C#, but I'm sure you can convert it :))
'Retrieve Image
GroupBox2.BringToFront()
GroupBox2.Visible = True
Label1.Visible = False
TextBox1.Visible = False
con.Open()
Dim cmd As New SqlCommand("SELECT DP FROM PersonsA WHERE Members_ID = 1", con)
cmd.CommandType = CommandType.Text
Dim read = cmd.ExecuteReader();
if(read.HadRows) then
read.Read() 'Reads the first record from the DataReader
Convert this to VB:
int buffersize = 4096;
long retval = 0;
long TempLen1 = 0;
long startindex = 0;
Byte[] reference_temp = new Byte[4096];
List<byte> RefTemp = new List<byte>();
retval = read.GetBytes(0, startindex, reference_temp, 0, buffersize); //0 is the first Column
TempLen1 += retval;
while (retval == buffersize)
{
RefTemp.AddRange(reference_temp);
startindex += buffersize;
retval = read.GetBytes(0, startindex, reference_temp, 0, buffersize);
TempLen1 += retval;
}
RefTemp.AddRange(reference_temp);
byte[] Reference_temp1 = RefTemp.GetRange(0, (int)TempLen1).ToArray();
Then add your code
Dim ImgStream As New IO.MemoryStream(Reference_temp1)
PictureBox2.BackgroundImage = Image.FromStream(ImgStream, False, True)
ImgStream.Dispose()
EndIf
I'd like to thank Jaques for his/her efforts in helping me. The solution was a little simpler than that answer - which still resulted in a 'Out of Memory' Error. But the efforts made are extremely appreciated. In the end this code worked without any errors.
'Retrieve Image
GroupBox2.BringToFront()
GroupBox2.Visible = True
Label1.Visible = False
TextBox1.Visible = False
Dim stream As New MemoryStream()
con.Open()
Dim cmd As New SqlCommand("SELECT DP FROM PersonsA WHERE Members_ID = 1", con)
cmd.CommandType = CommandType.Text
Dim image As Byte() = DirectCast(cmd.ExecuteScalar(), Byte())
Stream.Write(image, 0, image.Length)
con.Close()
Dim bitmap As New Bitmap(stream)
PictureBox2.BackgroundImage = bitmap
PictureBox2.BackgroundImageLayout = ImageLayout.Stretch