none
afficher une image a partir d'une base de donnée access RRS feed

  • Question

  •  

    Bonjour,

     

    Sous Visual Basic Express 2008:

    Je cherche comment affiicher, dans un pîcturebox, une image (format bmp) située dans une base de donnée access.

     

    Les images on été insérés dans la BDD par glissé / deposé, donc sont en fait encapsulées dans un objet OLE.

     

    D'apres ce que j'ai lu a droite et a gauche, le principe est simple:

    - convertir les donnée lues dans la base en tableau d'octet

    - Ecrire le tableau d'octet dans un flux (stream)

    - utiliser la methode Image.fromStream().

     

    Après avoir ecrit un code de test, j'obtiens une erreur:

     "L'exception ArgumentException n'a pas été gérée"

     "Le paramètre n'est pas valide"

     

    Voici mon code:

    - Mon formulaire s'apelle frm_mob

    - J'ai un picturebox nommé pic_mob

    - La base de donnée (que je n'ai pas crée ni ne peut modifier) s'appelle Fiesta Drop Info.mdb et est située dans le dossier courrant de l'application

    - J'interroge la table "MOB" qui contient entre autre une colonne "PICTURE" ou se trouve les données des images.

     

    Code Snippet

    Option Explicit On

    Imports System.Data.OleDb

     

    Public Class frm_mob

    Dim cn As OleDbConnection

    Dim cmd As OleDbCommand

    Dim dr As OleDbDataReader

    Dim strConnectionString As String

    Dim strSQL As String

    Dim b As Byte()

    Dim stream As IO.MemoryStream

     

    Private Sub frm_mob_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _

      "Data Source=" & Application.StartupPath & "\Fiesta Drop Info.mdb;" & _

      "User Id=admin;" & _

      "Password=;"

    strSQL = "SELECT * " & _

        "FROM MOB"

    cn = New OleDbConnection(strConnectionString)

    cmd = New OleDbCommand(strSQL, cn)

    cn.Open()

    dr = cmd.ExecuteReader

    dr.Read()

    b = CType(dr.Item("PICTURE"), Byte())

    If (b.Length > 0) Then

    stream = New IO.MemoryStream(b)

    pic_mob.Image = System.Drawing.Image.FromStream(stream)  'Ca coince ici

    stream.Close()

    stream = Nothing

    End If

    dr.Close()

    dr = Nothing

    cmd = Nothing

    cn.Close()

    cn = Nothing

    End Sub

    End Class

     

    - Est-ce que l'erreur est due au fait que le type accepté par la methode Image.FromStream (System.IO.Stream) et la variable stream (System.IO.MemoryStream) sont different ?

    - Ou est-ce les entetes OLE qui viennent semer la zizanie ?

     

    Dans les 2 cas, quelle(s) solution(s) me suggerez vous ?

     

    - Deedolith

    mardi 16 septembre 2008 23:40

Réponses

  • Comme je le présumais, les entêtes OLE viennent semer la pagaille, il faut donc les retirer du taleau d'octet avant de copier les données dans un flux.

    D'apres les specification du format BMP, une image commence par les deux lettre: "BM", il suffit donc de rechercher la premiere occurence de ces lettres (converties en tableau d'octet), et copier tous ce qui suit dans un autre tableau d'octet.

     

    Voici mon nouveau code: (changements surligné en jaune)

     

    Code Snippet

    Option Explicit On

    Imports System.Data.OleDb

     

    Public Class frm_mob

    Dim cn As OleDbConnection

    Dim cmd As OleDbCommand

    Dim dr As OleDbDataReader

    Dim strConnectionString As String

    Dim strSQL As String

    Dim b As Byte()

    Dim a As Byte()

    Dim stream As IO.MemoryStream

     

    Private Sub frm_mob_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    Dim index As Integer

     

    strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _

      "Data Source=" & Application.StartupPath & "\Fiesta Drop Info.mdb;" & _

      "User Id=admin;" & _

      "Password=;"

    strSQL = "SELECT * " & _

        "FROM MOB"

    cn = New OleDbConnection(strConnectionString)

    cmd = New OleDbCommand(strSQL, cn)

    cn.Open()

    dr = cmd.ExecuteReader

    dr.Read()

    a = CType(dr.Item("PICTURE"), Byte())

    index = findBM(a)

    If (index <> -1) Then

    ReDim b(0 To a.Length - index)

    System.Array.Copy(a, index, b, 0, a.Length - index)

    If (b.Length > 0) Then

    stream = New IO.MemoryStream(b)

    pic_mob.Image = System.Drawing.Image.FromStream(stream)

    stream.Close()

    stream = Nothing

    End If

    End If

    dr.Close()

    dr = Nothing

    cmd = Nothing

    cn.Close()

    cn = Nothing

    End Sub

     

    'Recherche de le 1er occurence de "BM"

    Private Function findBM(ByVal b As Byte()) As Integer

    Dim index As Integer

    Dim search() As Byte = {CType(Asc("B"), Byte), CType(Asc("M"), Byte)}

     

    index = 0

    While (Not (b(index) = search(0) And b(index + 1) = search(1))) And index < (UBound(b) - 1)

    index = index + 1

    End While

    If ((index >= 0) And (index <= (UBound(b) - 1))) Then

    findBM = index

    Else

    findBM = -1

    End If

    End Function

    End Class

     

     

    c'est un peu barbare comme solution (faute de mieux), on peut egalement stocker les entêtes OLE dans un tableau d'octet pour utilisation ultérieur (ecrire une image BMP dans la base par example).
    mercredi 17 septembre 2008 12:13