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()

Answers


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

Need Your Help

Need help on excel autocomplete function for drop-down list

excel vba excel-vba excel-formula formulas

I'm trying to add an auto-complete function to some of the boxes on the first sheet that I have for entering data on an excel worksheet, but I can't figure out how so. Here's the link for the excel

Is it OK to pass a generic Dictionary as a param to a method expecting IDictionary

c# generics collections

AssemblyInstaller.Install expects a System.Collections.IDictionary.