關于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();
}
評論