求思路,数据库中保存的图片,读取后以缩略图显示出来

时间:2021-05-25 11:16:25
图标以二进制方式保存在数据库中

在读取所有数据时,以缩略图显示,{效果想模仿ACDSEE中的缩略图}

求个思路,用那种来做速度和效率较快呢?

11 个解决方案

#1


不好意思,是图片以二进制方式保存在数据库中

#2


使用流对象保存和显示图片 
打开vb6,新建工程。

添加两个按钮,一个image控件
注意:Access中的photo字段类型为OLE对象.
SqlServer中的photo字段类型为Image

'** 引用 Microsoft ActiveX Data Objects 2.5 Library 及以上版本
‘2.5版本以下不支持Stream对象
Dim iConcstr As String
Dim iConc As ADODB.Connection
 

'保存文件到数据库中
Sub s_SaveFile()
    Dim iStm As ADODB.Stream
    Dim iRe As ADODB.Recordset
    Dim iConcstr As String

    '读取文件到内容
    Set iStm = New ADODB.Stream
    With iStm
        .Type = adTypeBinary   '二进制模式
        .Open
        .LoadFromFile App.Path + "\test.jpg"
    End With
   

    '打开保存文件的表
    Set iRe = New ADODB.Recordset
    With iRe
        .Open "select * from img", iConc, 1, 3
        .AddNew         '新增一条记录
        .Fields("photo") = iStm.Read
        .Update
    End With
   

   '完成后关闭对象
    iRe.Close
    iStm.Close
End Sub


Sub s_ReadFile()
    Dim iStm As ADODB.Stream
    Dim iRe As ADODB.Recordset
    '打开表
Set iRe = New ADODB.Recordset
‘得到最新添加的纪录
    iRe.Open "select top 1 * from img order by id desc", iConc, adOpenKeyset, adLockReadOnly
    '保存到文件
    Set iStm = New ADODB.Stream
    With iStm
        .Mode = adModeReadWrite
        .Type = adTypeBinary
        .Open
        .Write iRe("photo")
‘这里注意了,如果当前目录下存在test1.jpg,会报一个文件写入失败的错误.
        .SaveToFile App.Path & "\test1.jpg"
    End With
   

    Image1.Picture = LoadPicture(App.Path & "\test1.jpg")
   '关闭对象
    iRe.Close
    iStm.Close
End Sub
 

Private Sub Command1_Click()
Call s_ReadFile
End Sub


Private Sub Command2_Click()
Call s_SaveFile
End Sub


Private Sub Form_Load()
    '数据库连接字符串
    iConcstr = "Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False" & _
        ";Data Source=F:\csdn_vb\database\保存图片\access图片\img.mdb"

‘下面的语句是连接sqlserver数据库的.
    ‘iConcstr = "Provider=SQLOLEDB.1;Persist Security Info=True;" & _
‘ "User ID=sa;Password=;Initial Catalog=test;Data Source=yang"
 

   Set iConc = New ADODB.Connection
   iConc.Open iConcstr
End Sub
 

Private Sub Form_Unload(Cancel As Integer)
iConc.Close
Set iConc = Nothing
End Sub

#3


学习下
没做多相关的

#4


结合2楼的方法,然后PaintPicture做缩略图。

#5


2楼的代码有一点不尽如意,即需要临时文件做交换,在速度上受影响,为此,俺写了一段代码,直接保存和读取内存中的图像数据到ACCESS数据库,代码如下:
[code=VB]
Option Explicit

Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, _
    ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, _
    ByVal hObject As Long) As Long
Private Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, _
    ByVal dwCount As Long, lpBits As Any) As Long
Private Declare Function SetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, _
    ByVal dwCount As Long, lpBits As Any) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, _
    ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, _
        ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, _
    ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, _
    ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, _
    ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long

Dim m_Pic As New StdPicture
Dim WithEvents btnSave As CommandButton '图片保存按钮
Attribute btnSave.VB_VarHelpID = -1
Dim WithEvents btnShow As CommandButton '图片显示按钮
Attribute btnShow.VB_VarHelpID = -1

'窗口启动时加载C盘下名为pic1.jpg的图片文件
Private Sub Form_Load()
    If Len(Dir("c:\pic1.jpg")) = 0 Then Exit Sub
    Set m_Pic = LoadPicture("c:\pic1.jpg")
    
    Set btnSave = Me.Controls.Add("VB.CommandButton", "btnSave")
    btnSave.Caption = "保存"
    btnSave.Visible = True
    Set btnShow = Me.Controls.Add("VB.CommandButton", "btnShow")
    btnShow.Caption = "显示"
    btnShow.Left = btnSave.Left + btnSave.Width + 10
    btnShow.Visible = True
End Sub

'保存图片到ACCESS数据库中
Private Sub btnSave_Click()
    Dim Bits() As Byte, BitsLen As Long
    Dim PicWidth As Long, PicHeight As Long
    Dim hMemDC As Long, hMemBmp As Long, hOldBmp As Long
    Dim adoxCat As Object, adoDB As Object, adoRS As Object
    Dim strDatabaseName As String

    If m_Pic.Handle = 0 Then Exit Sub
    PicWidth = Me.ScaleX(m_Pic.Width, vbHimetric, vbPixels)
    PicHeight = Me.ScaleY(m_Pic.Height, vbHimetric, vbPixels)
    hMemDC = CreateCompatibleDC(Me.hdc)
    hMemBmp = CreateCompatibleBitmap(Me.hdc, PicWidth, PicHeight)
    hOldBmp = SelectObject(hMemDC, hMemBmp)
    m_Pic.Render CLng(hMemDC), 0, 0, CLng(PicWidth), CLng(PicHeight), 0, m_Pic.Height, _
        m_Pic.Width, -m_Pic.Height, 0
    BitsLen = GetBitmapBits(hMemBmp, 0, ByVal 0&)
    ReDim Bits(BitsLen - 1)
    GetBitmapBits hMemBmp, BitsLen, Bits(0)
    
    strDatabaseName = "C:\TEMP.MDB"
    If Len(Dir(strDatabaseName)) > 0 Then Kill strDatabaseName
    Set adoxCat = CreateObject("ADOX.Catalog")
    adoxCat.Create "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strDatabaseName
    Set adoDB = CreateObject("ADODB.Connection")
    adoDB.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strDatabaseName
    adoDB.Execute "CREATE TABLE 图像表(图像宽度 LONG,图像高度 LONG,图像字段 IMAGE)"
    Set adoRS = CreateObject("ADODB.Recordset")
    adoRS.Open "图像表", adoDB, 1, 3
    adoRS.AddNew
    adoRS.Fields("图像宽度").Value = PicWidth
    adoRS.Fields("图像高度").Value = PicHeight
    adoRS.Fields("图像字段").AppendChunk Bits
    adoRS.Update
    adoRS.Close
    adoDB.Close
    Set adoRS = Nothing
    Set adoDB = Nothing
    DeleteObject SelectObject(hMemDC, hOldBmp)
    DeleteDC hMemDC
    Erase Bits
End Sub

'从ACCESS数据库中读取并显示图片
Private Sub btnShow_Click()
    Dim Bits() As Byte, BitsLen As Long
    Dim PicWidth As Long, PicHeight As Long
    Dim hMemDC As Long, hMemBmp As Long, hOldBmp As Long
    Dim adoDB As Object, adoRS As Object
    
    If Len(Dir("c:\temp.mdb")) = 0 Then Exit Sub
    Set adoDB = CreateObject("ADODB.Connection")
    adoDB.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\temp.mdb"
    Set adoRS = adoDB.Execute("SELECT * FROM 图像表")
    If Not adoRS.EOF Then
        PicWidth = adoRS.Fields("图像宽度").Value
        PicHeight = adoRS.Fields("图像高度").Value
        BitsLen = LenB(adoRS.Fields("图像字段").Value)
        Bits = adoRS.Fields("图像字段").GetChunk(BitsLen)
        hMemDC = CreateCompatibleDC(Me.hdc)
        hMemBmp = CreateCompatibleBitmap(Me.hdc, PicWidth, PicHeight)
        hOldBmp = SelectObject(hMemDC, hMemBmp)
        SetBitmapBits hMemBmp, BitsLen, Bits(0)
        '显示图片
        BitBlt Me.hdc, 0, 0, PicWidth, PicHeight, hMemDC, 0, 0, vbSrcCopy
        '显示缩略图
        'StretchBlt Me.hdc, 0, 0, PicWidth \ 4, PicHeight \ 4, hMemDC, 0, 0, PicWidth, PicHeight, vbSrcCopy
        DeleteObject SelectObject(hMemDC, hOldBmp)
        DeleteDC hMemDC
    End If
    adoRS.Close
    adoDB.Close
    Set adoRS = Nothing
    Set adoDB = Nothing
    Erase Bits
End Sub

#6


不懂,up

#7


不懂,up

#8


如果一个图片非常大,比如100M以上,那么全读出来再显示缩略图,应该就会非常慢.

我不懂数据库,不知道是否有类似读文件方式的偏移量+长度模式来读二进制数据.....假设没有,那就试下这个思路:

另建一个专用的缩略图字段,内容也是二进制格式;

在加入图片时(图片肯定也是你程序加入的对吧),把图片的缩略图先保存在这个字段里,大小固定为1024x768,这样再大的原图,在这个字段里的大小也是有限的.

只需要显示缩略图时,用上面朋友的招读这个缩略图字段里的内容,肯定会比读原始数据快多了.

一个1024x768的24位BMP,也就两兆多点;按ATA33硬盘每秒33M的速度来算,也至少可以一秒读十张缩略图出来了....而且台式机硬盘速度一般还不止这个数.

当然,如果数据库可以根据偏移量+长度来读二进制字段的内容,那就又有另一个思路:

先得到字段里面存储图片的格式,比如BMP;

假设它的分辨率是大幅广告那种变态的大小,100M以上的,那么就根据你的缩略图分辨率(还是以1024x768为例),计算出缩略图所需要显示的象素点在原图中的位置,直接从二进制数据中取出这1024x768个象素点,再显示出来即可.....

这种思路在大量超大图片缩略图显示的场合应该非常有用......但是比较麻烦的问题是需要非常清楚目标文件的格式,因此要是遇到识别不了的图片格式,那就OVER了.....

不过我在想,N大图片的场合,那格式应该也非常有限吧......

以上纯粹个人瞎想,代码嘛,按我水平来说应该是很难实现的.....

匿- -!

#9


ding

#10


ding

#11


是的,应该将缩略图作为单独的数据进行存取。
而且从缩略图的用途来说,不排除需要反复显示,将每个缩略图在本地保留文件的做法效率反而更高。

#1


不好意思,是图片以二进制方式保存在数据库中

#2


使用流对象保存和显示图片 
打开vb6,新建工程。

添加两个按钮,一个image控件
注意:Access中的photo字段类型为OLE对象.
SqlServer中的photo字段类型为Image

'** 引用 Microsoft ActiveX Data Objects 2.5 Library 及以上版本
‘2.5版本以下不支持Stream对象
Dim iConcstr As String
Dim iConc As ADODB.Connection
 

'保存文件到数据库中
Sub s_SaveFile()
    Dim iStm As ADODB.Stream
    Dim iRe As ADODB.Recordset
    Dim iConcstr As String

    '读取文件到内容
    Set iStm = New ADODB.Stream
    With iStm
        .Type = adTypeBinary   '二进制模式
        .Open
        .LoadFromFile App.Path + "\test.jpg"
    End With
   

    '打开保存文件的表
    Set iRe = New ADODB.Recordset
    With iRe
        .Open "select * from img", iConc, 1, 3
        .AddNew         '新增一条记录
        .Fields("photo") = iStm.Read
        .Update
    End With
   

   '完成后关闭对象
    iRe.Close
    iStm.Close
End Sub


Sub s_ReadFile()
    Dim iStm As ADODB.Stream
    Dim iRe As ADODB.Recordset
    '打开表
Set iRe = New ADODB.Recordset
‘得到最新添加的纪录
    iRe.Open "select top 1 * from img order by id desc", iConc, adOpenKeyset, adLockReadOnly
    '保存到文件
    Set iStm = New ADODB.Stream
    With iStm
        .Mode = adModeReadWrite
        .Type = adTypeBinary
        .Open
        .Write iRe("photo")
‘这里注意了,如果当前目录下存在test1.jpg,会报一个文件写入失败的错误.
        .SaveToFile App.Path & "\test1.jpg"
    End With
   

    Image1.Picture = LoadPicture(App.Path & "\test1.jpg")
   '关闭对象
    iRe.Close
    iStm.Close
End Sub
 

Private Sub Command1_Click()
Call s_ReadFile
End Sub


Private Sub Command2_Click()
Call s_SaveFile
End Sub


Private Sub Form_Load()
    '数据库连接字符串
    iConcstr = "Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False" & _
        ";Data Source=F:\csdn_vb\database\保存图片\access图片\img.mdb"

‘下面的语句是连接sqlserver数据库的.
    ‘iConcstr = "Provider=SQLOLEDB.1;Persist Security Info=True;" & _
‘ "User ID=sa;Password=;Initial Catalog=test;Data Source=yang"
 

   Set iConc = New ADODB.Connection
   iConc.Open iConcstr
End Sub
 

Private Sub Form_Unload(Cancel As Integer)
iConc.Close
Set iConc = Nothing
End Sub

#3


学习下
没做多相关的

#4


结合2楼的方法,然后PaintPicture做缩略图。

#5


2楼的代码有一点不尽如意,即需要临时文件做交换,在速度上受影响,为此,俺写了一段代码,直接保存和读取内存中的图像数据到ACCESS数据库,代码如下:
[code=VB]
Option Explicit

Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, _
    ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, _
    ByVal hObject As Long) As Long
Private Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, _
    ByVal dwCount As Long, lpBits As Any) As Long
Private Declare Function SetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, _
    ByVal dwCount As Long, lpBits As Any) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, _
    ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, _
        ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, _
    ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, _
    ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, _
    ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long

Dim m_Pic As New StdPicture
Dim WithEvents btnSave As CommandButton '图片保存按钮
Attribute btnSave.VB_VarHelpID = -1
Dim WithEvents btnShow As CommandButton '图片显示按钮
Attribute btnShow.VB_VarHelpID = -1

'窗口启动时加载C盘下名为pic1.jpg的图片文件
Private Sub Form_Load()
    If Len(Dir("c:\pic1.jpg")) = 0 Then Exit Sub
    Set m_Pic = LoadPicture("c:\pic1.jpg")
    
    Set btnSave = Me.Controls.Add("VB.CommandButton", "btnSave")
    btnSave.Caption = "保存"
    btnSave.Visible = True
    Set btnShow = Me.Controls.Add("VB.CommandButton", "btnShow")
    btnShow.Caption = "显示"
    btnShow.Left = btnSave.Left + btnSave.Width + 10
    btnShow.Visible = True
End Sub

'保存图片到ACCESS数据库中
Private Sub btnSave_Click()
    Dim Bits() As Byte, BitsLen As Long
    Dim PicWidth As Long, PicHeight As Long
    Dim hMemDC As Long, hMemBmp As Long, hOldBmp As Long
    Dim adoxCat As Object, adoDB As Object, adoRS As Object
    Dim strDatabaseName As String

    If m_Pic.Handle = 0 Then Exit Sub
    PicWidth = Me.ScaleX(m_Pic.Width, vbHimetric, vbPixels)
    PicHeight = Me.ScaleY(m_Pic.Height, vbHimetric, vbPixels)
    hMemDC = CreateCompatibleDC(Me.hdc)
    hMemBmp = CreateCompatibleBitmap(Me.hdc, PicWidth, PicHeight)
    hOldBmp = SelectObject(hMemDC, hMemBmp)
    m_Pic.Render CLng(hMemDC), 0, 0, CLng(PicWidth), CLng(PicHeight), 0, m_Pic.Height, _
        m_Pic.Width, -m_Pic.Height, 0
    BitsLen = GetBitmapBits(hMemBmp, 0, ByVal 0&)
    ReDim Bits(BitsLen - 1)
    GetBitmapBits hMemBmp, BitsLen, Bits(0)
    
    strDatabaseName = "C:\TEMP.MDB"
    If Len(Dir(strDatabaseName)) > 0 Then Kill strDatabaseName
    Set adoxCat = CreateObject("ADOX.Catalog")
    adoxCat.Create "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strDatabaseName
    Set adoDB = CreateObject("ADODB.Connection")
    adoDB.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strDatabaseName
    adoDB.Execute "CREATE TABLE 图像表(图像宽度 LONG,图像高度 LONG,图像字段 IMAGE)"
    Set adoRS = CreateObject("ADODB.Recordset")
    adoRS.Open "图像表", adoDB, 1, 3
    adoRS.AddNew
    adoRS.Fields("图像宽度").Value = PicWidth
    adoRS.Fields("图像高度").Value = PicHeight
    adoRS.Fields("图像字段").AppendChunk Bits
    adoRS.Update
    adoRS.Close
    adoDB.Close
    Set adoRS = Nothing
    Set adoDB = Nothing
    DeleteObject SelectObject(hMemDC, hOldBmp)
    DeleteDC hMemDC
    Erase Bits
End Sub

'从ACCESS数据库中读取并显示图片
Private Sub btnShow_Click()
    Dim Bits() As Byte, BitsLen As Long
    Dim PicWidth As Long, PicHeight As Long
    Dim hMemDC As Long, hMemBmp As Long, hOldBmp As Long
    Dim adoDB As Object, adoRS As Object
    
    If Len(Dir("c:\temp.mdb")) = 0 Then Exit Sub
    Set adoDB = CreateObject("ADODB.Connection")
    adoDB.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\temp.mdb"
    Set adoRS = adoDB.Execute("SELECT * FROM 图像表")
    If Not adoRS.EOF Then
        PicWidth = adoRS.Fields("图像宽度").Value
        PicHeight = adoRS.Fields("图像高度").Value
        BitsLen = LenB(adoRS.Fields("图像字段").Value)
        Bits = adoRS.Fields("图像字段").GetChunk(BitsLen)
        hMemDC = CreateCompatibleDC(Me.hdc)
        hMemBmp = CreateCompatibleBitmap(Me.hdc, PicWidth, PicHeight)
        hOldBmp = SelectObject(hMemDC, hMemBmp)
        SetBitmapBits hMemBmp, BitsLen, Bits(0)
        '显示图片
        BitBlt Me.hdc, 0, 0, PicWidth, PicHeight, hMemDC, 0, 0, vbSrcCopy
        '显示缩略图
        'StretchBlt Me.hdc, 0, 0, PicWidth \ 4, PicHeight \ 4, hMemDC, 0, 0, PicWidth, PicHeight, vbSrcCopy
        DeleteObject SelectObject(hMemDC, hOldBmp)
        DeleteDC hMemDC
    End If
    adoRS.Close
    adoDB.Close
    Set adoRS = Nothing
    Set adoDB = Nothing
    Erase Bits
End Sub

#6


不懂,up

#7


不懂,up

#8


如果一个图片非常大,比如100M以上,那么全读出来再显示缩略图,应该就会非常慢.

我不懂数据库,不知道是否有类似读文件方式的偏移量+长度模式来读二进制数据.....假设没有,那就试下这个思路:

另建一个专用的缩略图字段,内容也是二进制格式;

在加入图片时(图片肯定也是你程序加入的对吧),把图片的缩略图先保存在这个字段里,大小固定为1024x768,这样再大的原图,在这个字段里的大小也是有限的.

只需要显示缩略图时,用上面朋友的招读这个缩略图字段里的内容,肯定会比读原始数据快多了.

一个1024x768的24位BMP,也就两兆多点;按ATA33硬盘每秒33M的速度来算,也至少可以一秒读十张缩略图出来了....而且台式机硬盘速度一般还不止这个数.

当然,如果数据库可以根据偏移量+长度来读二进制字段的内容,那就又有另一个思路:

先得到字段里面存储图片的格式,比如BMP;

假设它的分辨率是大幅广告那种变态的大小,100M以上的,那么就根据你的缩略图分辨率(还是以1024x768为例),计算出缩略图所需要显示的象素点在原图中的位置,直接从二进制数据中取出这1024x768个象素点,再显示出来即可.....

这种思路在大量超大图片缩略图显示的场合应该非常有用......但是比较麻烦的问题是需要非常清楚目标文件的格式,因此要是遇到识别不了的图片格式,那就OVER了.....

不过我在想,N大图片的场合,那格式应该也非常有限吧......

以上纯粹个人瞎想,代码嘛,按我水平来说应该是很难实现的.....

匿- -!

#9


ding

#10


ding

#11


是的,应该将缩略图作为单独的数据进行存取。
而且从缩略图的用途来说,不排除需要反复显示,将每个缩略图在本地保留文件的做法效率反而更高。