时间:2022-09-19 05:32:31
摘要:本文通过具体实例量化比较研究,得出在Visual Basic环境下快速数据库图像存取的方法,对于其他多媒体信息存取与编程环境也有一定的借鉴作用。
关键词:图像存取;ICB方法;CKA方法
中图分类号:TP311文献标识码:A文章编号:1009-3044(2007)06-11719-02
1 引言
图形图像、音频视频等多媒体信息在数据库中存储不同于传统的文本、数字等有着非常规范的结构化形式,程序设计中采用不同的存取方法,对数据库访问速度以及文件容量有非常大的影响,程序的运行效率当然也是相差甚远。
SQL Server用Image字段(Access用OLE对象字段)来存储图形图像甚至音视频等多媒体信息,在库中以“长二进制数据”的形式存放。对于图形图像来说,Visual Basic传统的作法是将ADO控件RecordSet对象存放图像的字段与图像(Image或Picture)控件进行绑定,用LoadPicture函数加载图像并刷新图像控件,再调用RecordSet对象的Update方法即可完成图像的存储,这里称为图像控件绑定(Image Control Binding,ICB)方法。这种方法的优势是代码简单、容易理解和实现,特别是对于库中所存图像的浏览(读取)尤为方便。但由于其不管源图像格式,对加载的图像统一按24位位图进行处理,故只适用于小型图像的存取,如人事档案中的相片,而对于较大的尤其是经过压缩的图像,ICB方法的存取速度就会慢得让人无法忍受,数据库的膨胀幅度则会大得惊人。
2 图像的存储优化
为提高图像的存储速度,最大限度地限制数据库大小增幅,对普通图像(如BMP)文件,需要先将其转化成压缩格式文件(如Jpeg格式)。VB存储图像时,先把图像文件按二进制文件打并开读入到相应的Byte型数组,再用ADO控件RecordSet对象的追加大块数据方法[1](AppendChunk方法)将其写入数据库,这里称之为大块数据存取(Chunk Access,CKA)方法。实际上,利用CKA方法可以将任何类型的计算机文件存入数据库。
CKA方法图像存入数据库代码:
Dim bytData() As Byte
'以二进制文件方式打开临时图像文件
Open App.Path & "\temp1.jpg" For Binary As #1
ReDim bytData(FileLen(App.Path & "\temp1.jpg"))
Get #1, , bytData()'读入图像二进制数组
Close #1
'用AppendChunk方法将二进制数组入库
Me.Adodc2.Recordset("Pic").AppendChunk bytData()
Me.Adodc2.Recordset.Update
表1所示是ICB方法和CKA方法存储JPEG图像速度与存储图像后数据库文件大小的测试数据对照表[2]。
表1 图像存储对照表
为突出效果,选用9张2048×1536像素的JPEG数码相片进行测试,图片大小介于1.3MB到2MB之间。分析测试结果得出,ICB方法存储JPEG相片的平均速度为120 B/ms,CKA方法则为2848 B/ms。存储时间与图像大小的关系如图1所示,CKA方法的存储时间与图像大小成比例,ICB方法的存储时间波动范围较大,这是由于存储时间本身较长(12~15s),测试期间受其它进程影响较多造成的。
对于图像存储后库文件的大小,ICB方法对应的库文件呈线性膨胀(如图2所示),每次增量为9.2MB左右,即2048×1536像素的24位图文件的大小,也就是说,ICB方法存储图像是按24位像素处理的,并没有按源图像格式存储;CKA方法对应的库文件每次增量则与JPEG文件的大小相吻合,如果需要,可在图像格式转换时保证图像视学效果的前提下减小Quality取值以获得更大的压缩率,从而降低图像对数据库大小的影响。
3 图像的查询优化
图像查询时使用ICB方法基本不需要写任何代码就可完成查询,借助Adodc控件的导航按钮可以方便地实现对数据库中图片的浏览。但是如果图像记录较多或存在大图像,查询操作就会变得异常缓慢,出现类似“死机”的现象。
图片的查询优化包含两方面内容,其一为图片查询与普通数据查询分开进行,单独使用一个记录集对象,每次只检索一条记录对应的图片,避免一次检索过多图片造成查询延时过长;其二需要把存放在数据库图像字段中的长二进制数据信息用CKA方法(ADO控件的GetChunk方法)分段读出写到一个临时文件中,重新组装成原来的图像,再用LoadPicture函数加载到图像(Image或Picture)控件[3]。
CKA方法图像查询关键代码:
Dim bytData() As Byte
Dim lngOffset As Long
Dim varChunk() As Byte
Dim sFile As String
Dim lngLogoSize As Long
Const conChunkSize = 8192
Fn = Me.Adodc1.Recordset("Name")
'只检索一条记录对应的图片,尤其在网络环境下
Me.Adodc2.RecordSource = "select pic from picture where Name='" & Fn & "'"
图1 存储时间与图像大小关系图
Me.Adodc2.Refresh
If Not IsNull(Me.Adodc2.Recordset("pic")) Then
'用于组装图像的临时文件
sFile = App.Path & "\temp1.jpg"
Open sFile For Binary Access Write As #1
lngOffset = 0
varChunk() = Me.Adodc2.Recordset("pic"). GetChunk(conChunkSize)'从库中读出第一段数据
Put #1, , varChunk()'组装图像
lngOffset = lngOffset + conChunkSize
lngLogoSize = Me.Adodc2.Recordset("pic"). ActualSize'读出存放图像二进制数据字段总长
If lngOffset < lngLogoSize Then
Do While lngOffset < lngLogoSize
varChunk() = Me.Adodc2.Recordset("pic"). GetChunk(conChunkSize)'读出后续数据段
Put #1, , varChunk()'后继组装
lngOffset = lngOffset + conChunkSize
Loop
End If
Close #1
End If
'组装完毕, 用Image显示
Me.Image2.Picture = LoadPicture(sFile)
Me.Image2.Refresh
图2 两种方法存储图像后对库文件大小的影响
表2 图像查询时间对照表
ICB方法与CKA方法用于图像查询的对照测试工作在前面存入9张相片的Access数据库上进行,测试数据如表2所示。
计算得出,ICB方法图像查询的平均速度只有35 B/ms,CKA方法为2809 B/ms,与存储速度相当,就是算上图像合成(含加载)时间,CKA方法查询速度也能达到2597 B/ms,远远优于ICB方法。两种方法查询时间对照关系如图3所示。
图3 图像查询时间对照图
4 结束语
通过实例测试可以发现,在VB环境下,用ADO控件RecordSet对象的大块数据读写(GetChunk、AppendChunk方法)的CKA方法进行图像的存取,无论从速度还是对库文件大小的影响来说,性能都远远优于传统的ICB方法。实际上,运用CKA方法也可以实现音视频等多媒体信息甚至任何类型计算机文件的数据库存取,这里不再赘述。
参考文献:
[1] 李树海,陆体虎. 对数据库的操作――图像的存储与显示[J]. 计算机与信息技术,2004,(11).
[2] 马战宝. 基于Intranet的商品混凝土生产控制管理系统的研究与实现[D]. 西安:西安交通大学硕士论文,2006.
[3] 张毅,王晓强, 等. Visual Basic应用技巧与常见问题你问我答[M]. 北京:机械工业出版社,2003.222-226.
本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。