Menu

using FreeImage_OpenMemory to access BLOB

Developers
2012-04-01
2013-06-24
  • Steve Murphy

    Steve Murphy - 2012-04-01

    Some time ago I wanted to find out how to read image data stored in a database
    BLOB column into Freeimage without having to save the BLOB as a temporary file
    on disk first. It seemed pretty obvious that using FreeImage_OpenMemory was
    the way to go but nobody else had been able to get any help with it here so I
    gave up as I was short of time. I've now had time to revisit the issue and
    thought it would be a good idea to to post some simple sample code to
    demonstrate the process.

        Dim rsWork As New cRecordset
        Dim byBlobData() As Byte
        Dim lngMem As Long
        Dim fifMem As FREE_IMAGE_FORMAT
        Dim fibImage As Long
    
        cnnDB.OpenDB mstrDBFile
    
        Set rsWork = cnnDB.OpenRecordset("SELECT Image_Len, ImageData FROM Medications")
    
        byBlobData = rsWork.Fields("ImageData").value
    
        ' Note that we just pass in the the first item of the array as VB handles
        ' turning it into an appropriate pointer
        lngMem = FreeImage_OpenMemory(byBlobData(0), rsWork!Image_Len)
    
        fifMem = FreeImage_GetFileTypeFromMemory(lngMem)
    
        fibImage = FreeImage_LoadFromMemory(fifMem, lngMem, 0)
    
        FreeImage_PaintDC Me.hdc, fibImage
        FreeImage_Unload fibImage
        FreeImage_CloseMemory lngMem
    
        Set rsWork = Nothing
    End Sub
    
     
  • Carsten Klein

    Carsten Klein - 2012-04-02

    Hi Crunchy Frog,

    you could do this even more easily by using wrapper method
    FreeImage_LoadFromMemoryEx, which takes a VB-style Byte array as its first
    parameter. Have a look at this modified version of your code.

    Dim rsWork As New cRecordset
    Dim byBlobData() As Byte
    Dim fifMem As FREE_IMAGE_FORMAT
    Dim fibImage As Long
    
       cnnDB.OpenDB mstrDBFile
       Set rsWork = cnnDB.OpenRecordset("SELECT Image_Len, ImageData FROM Medications")
       byBlobData = rsWork.Fields("ImageData").Value
    
       ' If you need the image type, add fifMem as the last ByRef parameter, which will contain the image's type
       ' after the function returns.
       fibImage = FreeImage_LoadFromMemoryEx(byBlobData, , , fifMem)
       ' Use this line instead, if you do not need the image type.
       'fibImage = FreeImage_LoadFromMemoryEx(byBlobData)
    
       ' Now, paint the image.
       FreeImage_PaintDC Me.hDC, fibImage
    
       ' Unload the FreeImage bitmap from memory.
       FreeImage_Unload fibImage
    
       Set rsWork = Nothing
    

    However, FreeImage_LoadFromMemoryEx only works with explicitly declared VB-
    style arrays so, you always need to assign your recordset field's value to a
    (Byte in this case) array. Although it seems obvious, doing this even shorter
    like

       fibImage = FreeImage_LoadFromMemoryEx(rsWork.Fields("ImageData").Value)
    

    does not work.

    Carsten

     
  • Steve Murphy

    Steve Murphy - 2012-04-03

    Thanks for the follow-up Carsten. I'll revisit my working code as you
    recommend.

    Regards

    Steve Murphy

     
  • Wolfgang Fürtbauer

    Carsten,
    I tried your code, but FreeImage_LoadFromMemoryEx returns 0
    Running step by step through the code, I found out that FreeImage_GetFileTypeFromMemory(hStream) returns -1 (unknown) ?

    Could you please help?

    Here's what i did:

    public function test()

    dim rs as recordset
    dim data() as byte
    dim dib as long

    ' "bild" is the memo/blob field containing the binary data

    set rs = currentdb().openrecordset("select * from tabelle1")
    rs.edit
    rs!bild = readbitmap("C:\temp\test.bmp")
    rs.update
    rs.Requery
    ' now we have the binaray data in the memo field
    data = rs!bild

    dib = FreeImage_LoadFromMemoryEx(data, , , FIF_BMP)
    ' dib is 0 ???

    end function

    Public Function readbmp(pfad As String) As String
    Dim content As String
    Open pfad For Binary Access Read As #1
    content = Space(LOF(1))
    Get #1, , content
    readbmp = content
    Close #1
    End Function

     
  • Carsten Klein

    Carsten Klein - 2013-06-24

    Hi,

    have you had a look at the data array after that line? Does is contain the same bytes that you see when you view the file C:\temp\test.bmp with a HEX editor?

    Currently I'm on vacation (St. Peter Ording) and only have a Linux box with me, so I'm not really able to figure out things about VBA and Access. But I guess that something with loading /storing / requerying of the image file's
    bytes goes wrong.

    Maybe you should not load the image file into a String variable in function readbmp. Try it with a byte array. Make the function return Byte() and turn variable content into a byte array. Then use

    ReDim content(LOF(1) - 1)

    instead of the Space() function.

    Carsten

     

Log in to post a comment.