none
OLE Object Problem with VB.Net RRS feed

  • Question

  •  

    Hi!

     

    I have a list of jpeg pictures that i will be loading from an Access DB into a VB.Net imagelist but unfortunately I can't even load a single image into a picturebox. I get an invalid parameter error in

     

    PictureBox1.Image = Image.FromStream(stmBLOBData)

     

    I tried searching the net and found out that you need to strip the OLE first. But all th samples that was listed was for BMP files (i.e. OLE Header = 78 bits), what I have are JPEG files. So it's either, I need to know what is the  OLE Header length to be stripped for JPEG files or I need to know another way around loading JPEG from Access to VB.Net. Can anybody help?

     

    btw, this is my sample code:

     

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Me.DataSet111.Clear()

    Me.OleDbDataAdapter1.SelectCommand.CommandText = "select picture from members"

    Me.OleDbDataAdapter1.Fill(Me.DataSet111)

    Dim cs As DataTable = Me.DataSet111.Tables(0)

    Dim test2 As MemoryStream

    Dim test() As Byte = Me.DataSet111.Tables("members").Rows(0)("Picture")

    Dim stmBLOBData As New MemoryStream(test, 78, test.Length - 78)

    Try

    PictureBox1.Image = Image.FromStream(stmBLOBData)

    Catch ex As Exception

    MsgBox(ex.Message)

    End Try

    End Sub

    Wednesday, September 19, 2007 3:37 AM

All replies

  • One easy way to do this (guessing here) is just search for the jpeg header in the binary stream and start from there.

     

    FF D8 FF E1?  This is what I see with jpegs from my Canon 30D.

     

    Not sure, maybe there is a jpeg spec somewhere.

     

    There once was a sample app to do this in C++ about 10 years ago called OLEFLD, perhaps google this.

     

     

     

     

    Wednesday, September 19, 2007 5:55 AM
  • Thanks,

     

    I tried google and got an email address, i'll try checking that out.

     

    Is there a way to change OLE Objects into Binary inside Access?

    Wednesday, September 19, 2007 10:52 AM
  • When you embed a object into an Ole Object field in Access, Access is using OLE serialization to store the value.  This allows you to save just about anything that supports OLE serialization into the field, which is a cool feature.  Like you can stick an Excel spreadsheet or Word doc or picture.

     

    The "correct" way to suck this data out is to do the same in reverse, use the OLE APIs to deserialize.  Unfortunately Access does not expose a nice wrapper for this, you have to figure out how to do this yourself.  This is where the OLEFLD sample was useful, it shows how to do it in C++. 

     

    Note I found this article that explains the header format, this might be useful to you:

     

    http://support.microsoft.com/kb/175261

     

    This details the header format, I think you can use this interchangibly with jpeg files.

    Wednesday, September 19, 2007 4:51 PM
  • Someone recently post a solution to this in the forum. See if the following helps:

     

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2156764&SiteID=1

     

     

    Thursday, September 20, 2007 12:41 PM
  • Hence the idea of just blindly scanning for jpeg header works.  Simple enough.

    Thursday, September 20, 2007 5:03 PM
  •  

    Thanks, Nice one!

     

    When I followed the procedure using C#.Net it worked like a charm but unfortunately when I converted it to VB.Net I cannot load the image.

     

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

    aConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\\Images.mdb")

    aConnection.Open()

    If aConnection.State = ConnectionState.Open Then

    Label1.BackColor = System.Drawing.Color.WhiteSmoke

    End If

    End Sub

     

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim BITMAP_ID_BLOCK As String = "Bitmap"

    Dim JPG_ID_BLOCK As String = "\u00FF\u00D8\u00FF"

    'create the command object and store the sql query

    aCommand = New OleDbCommand(("select Image from Images where KeyID = " + TextBox1.Text), aConnection)

    Dim ms As MemoryStream = New MemoryStream

    Dim img() As Byte = CType(aCommand.ExecuteScalar, Byte())

    Dim u8 As Encoding = Encoding.UTF7

    Dim strTemp As String = u8.GetString(img)

    Dim strVTemp As String = strTemp.Substring(0, 300)

    Dim iPos As Integer = -1

    Dim test As Integer = strVTemp.IndexOf(JPG_ID_BLOCK)

    If (strVTemp.IndexOf(BITMAP_ID_BLOCK) = -1) Then

    ' Find the starting block of the image

    iPos = strVTemp.IndexOf(JPG_ID_BLOCK)

    Else

    iPos = 78

    End If

    ' From the position above get the new image

    If (iPos <> -1) Then

    ms.Write(img, iPos, (img.Length - iPos))

    Me.PictureBox1.Image = Image.FromStream(ms)

    End If

    ms.Close()

    End Sub

     

     

    I made a sample Access DB named images.mdb with 2 images (1 .jpg and 1 .bmp), when I try to load the bmp file it works ok but when I use the jpg file, it doesn't load. The C# strTemp value is somehow different from the VB strTemp value.

     Also the VB iPos = -1 at the last IF statement. It works with C#, I really don't understand why it wouldn't using VB.

     

    I tried using http://www.carlosag.net/Tools/CodeTranslator/Default.aspx and http://www.kamalpatel.net/ConvertCSharp2VB.aspx for the conversion.

     

    Thanks for the link, it really was a very big help.

    Friday, September 21, 2007 8:30 AM
  • Keep in mind that the length of the OLE header will be different depending upon the document or file type. If you have different types of objects stored then it will be somewhat tricky to identify the document or file type before stripping the header.

    Friday, September 21, 2007 8:24 PM
  •  

    Yes, that's why the link was a big help. It gave me a procedure to identify and strip the header but my problem now is that using the same DB, I can load the JPEG successfully in C# but not in VB.Net. strTemp returns different values for C# and VB.Net with technically the same code, just converted for VB.  I might try stripping the header with C# then save it back to Access in another format, but I'd try other things out first.

     

    Seems that VB.Net strTemp can only read the first character of the object while C# gets 13008.

    Saturday, September 22, 2007 2:27 AM
  • I recall from past forays into VB that it has peculiar behavior when dealing with byte arrays and strings converted to byte arrays.  So don't give up so easy, instead step back and take a look at what the code is doing one piece at a time.

     

    For example, write some code to dump out the byte array and string from C# and VB and see if you see any differences.   Also, instead of searching for the binary value in the string version of the byte array, just scan the byte array looking for the correct bytes.  Most likely VB is converting byte array to string differently OR string search behaves differently. 

     

    To be honest, converting a byte array of random data to a string (which is UNICODE) is going to have problems.  Likewise, searching inside this string will have problems, it is probably not a valid UNICODE string.  So be smart and search the byte array as bytes and don't convert it to a string is my best advice.

     

    Saturday, September 22, 2007 6:46 PM