关于VC++的图像数据访问的研究
在许多项目开发中,由于存在着大量的数据需要存储,通常采用数据库来存储这些数据,使得数据库技术被越来越广泛地应用。在这些数据中有简单的文本文件,只需通过api的简单编程即可实现,但也存在许多大对象数据,比如图像、音频和视频等,其存储形式有所不同。作为大对象数据的图像数据,一般以blob(二进制大对象,binary large object)形式存储,例如access数据库中ole对象数据类型、sql server数据库中的image数据类型等。在vc++ 7.0的环境下,为了高效快捷的访问图像数据,需要采用合适的数据库访问技术。
在vc++中标准的访问数据库技术有很多种,根据开发的项目,笔者采用了数据库技术中最常见有效的两种技术ado技术和mfc odbc在access数据库中访问图像数据。
2 图像数据访问原理
虽然图像数据的格式有多种,例如bmp、jpg和gif等格式,但都可以看成是二进制流,即blob类型。blob类型数据需要占用较大的硬盘空间和内存,对存储效率和查询速度都有很大的影响。
图像数据的访问分存储和读取两个过程。在存储过程中,由于存放图像数据的字段是可变长度(长度一般为0~2g)的blob类型,无法直接存储,必须首先将存储在文件中的图像数据以二进制流的形式读到缓冲区中,然后再将缓冲区中的图像数据添加到access数据库中的ole对象中。在读取过程中,将存放在access数据库中的图像数据读到缓冲区中,然后在显示在用户界面上。图像数据的访问原理如图1所示。
图1 图像数据访问原理图
3 应用ado访问图像数据3.1 ado的介绍
ado(activex data objects)是microsoft数据库应用程序开发的接口,是建立在ole db技术之上的高层数据库访技术,简化了编程,且有利于程序的可移植性及可扩充性。
ado包括connection对象、command对象、parameter对象、recordset对象、field对象、error对象、property对象以及相应的集合对象,这些对象被封装在_connection -ptr接口、_commndptr接口和_recordsetptr接口这三个基本接口中。
3.2 ado连接数据库
(1) 导入ado库
使用ado前需要在stdafx.h头文件中导入该库,只需利用import指令将此动态链接库导入,具体代码如下[1]:
#import“c:program filescommon files
systemadomsado15.dll”o_namespaceename(“eof”,
“adoeof”)
(2) 初始化com库
ado本身是一个com组件,在使用时需要初始化com库,需要调用coinitialize函数来实现。
:: coinitialize(null);
(3) 创建connection对象并连接数据库
创建connection对象:
_connectionptr m_pconnection;
m_pconnection.createinstanc -e(“adodb.connection”);
连接数据库:
_pconnection-》open(“provide -r=microsoft.jet.oledb.4.0;data
source = picture.mdb”, “”,“”, admodeunknown);
(4) 执行操作
m_precordset.createinstance(“adodb.recordset”);
m_precordset-》open
((_variant_t)strsql,_variant_t((idispatch*)
theapp.m_pconnection,true),adopendynamic,adlockoptimistic,adcmdtext);
3.3 图像数据的存储
对于一般数据,可以通过recordset对象的getcollect()和putcollect()函数来对数据进行存储和读取,而对于图像数据,就需要使用field对象中的appendchunk函数来进行存储和getchunk函数来进行读取。图像数据的存储过程可以分为以下三步:
(1) 打开图像数据,获得数据长度;申请缓冲区,把文件读入此缓冲区。
(2) 构造一个一维数组,把缓冲区中的数据拷贝到数组中,然后构造一个变体对象,用数组来对此对象赋值。
(3) 调用appendchunk函数,把数据存入recordset对象的本地缓冲区。
具体实现代码如下:
if(m_pic.m_ipicture != null) m_pic.freepicturedata();
if(f.open(m_strphotopath, cfile::moderead |
cfile::typebinary, &e)) //打开了一个图像文件
{nsize = f.getlength();//先得到图像数据长度
byte * pbuffer = new byte [nsize];
//根据数据的长度申请缓冲区
if (f.read(pbuffer, nsize) 》 0 )
//把图像数据读到缓冲区
{byte *pbuf = pbuffer;
//把pbuffer里的jpg数据放到库中
variant varblob;
safearray *psa;
safearraybound rgsabound[1];
//创建safearray对象
if(pbuf)
{rgsabound[0].llbound = 0;
rgsabound[0].celements = nsize;
psa = safearraycreate(vt_ui1, 1, rgsabound);
for (long i = 0; i 《 (long)nsize; i++)
safearrayputelement (psa, &i, pbuf++);
varblob.vt = vt_array | vt_ui1;
varblob.parray = psa;
m_precordset-》getfields()-》getitem(“picture”)-》appendchunk(varblob);
m_precordset-》update();//更新数据库
}
delete [] pbuffer; //释放缓冲区
pbuf=0;
}
f.close();
}
评论