向数据库中存取图片(BITMAP)

BITMAP
测试环境:windows xp2 vc6.0 access2003/sql2000
当前时间所限就先把关于BMP文件的操作总结了一下,在接下来会再总结一下其它几种图片在数据库的操作的。
转入下文:
个人感觉向数据库中写入和读取位图,也没有什么难的,重点还是在于对位图文件的读取,如果这一关能把握好的话,那也就没有问题了。如果哪位看过我的一篇《VC下显示位图的几种方法》其中有一段是关于,直接读取位图文件的,如果看明白了它,也今天这几个问题就会很好明白了。
进入正题:既然是向数据库中添加位图信息,那么有必须明白我们的数据是以什么形式存放在数据库的,当然没有别的方法,只能是二进制了,所以在创建数据库的时候,一定要注意选择的字段的类型,不然是添加下进去的。(刚开始的时候,我就遇到了这个问题,费了好长时间才搞定的。Access中的字段定义为”  OLE 对象”,sql2000中字义为image就行了。)
1> 读取一个位图,
CFile FilePic;//用来读取位图文件
DWORD FileLen=0;//位图的长度
char* FileBuff;//用于存放位图信息

if(!FilePic.Open(FilePath,Cfile::modeRead))//打开位图文件 
 
{ 
 
  MessageBox("打开图片信息失败!"); 
 
  return false; 
 
} 
 
FileLen=FilePic.GetLength();//得到位图的长度 
 
FileBuff=new char[FileLen+1];//给位图文件申请内在空间 
 
memset(FileBuff,0,FileLen+1);//初始化位图文件的空间 
 
if(!FileBuff)//判断位图空间是否申请成功 
 
{ 
 
  MessageBox("给图片分配空间失败!"); 
 
  return false; 
 
} 
 
if(FilePic.Read(FileBuff,FileLen)!=FileLen)//读取位图信息,存入到FileBuff中去 
 
{ 
 
  MessageBox("读取图片信息失败!"); 
 
  return false; 
 
} 
 
2> 把位图信息存放到VARIANT对象中,存入数据库中 
 
char* pBuff= FileBuff; 
 
VARIANT varPic;//该对象用于存放位图信息 
 
SAFEARRAY *safeArray;//定义一个SAFEARRAY结构对象(对于这个东西,会有专门的文档大家可以看一下,网上很多,不过都差不多,最好去MSDN上找一下) 
 
SAFEARRAYBOUND rgsabound[1];//此结构体用来定义SAFEARRAY的边界,详情见MSDN 
 
if(pBuff)//判断位图文件是否为空 
 
{ 
 
  rgsabound[0].lLbound=0;//定义下界 
 
  rgsabound[0].cElements=DwPic;//定义上限 
 
  safeArray=SafeArrayCreate(VT_UI1,1,rgsabound);// 使用SafeArrayCreate在堆上创建一维数组 
 
  for(long i=0;i<(long)DwPic;i++) 
 
  { 
 
   SafeArrayPutElement(safeArray,&i,pBuff++);//传值 
 
  } 
 
  varPic.vt=VT_ARRAY|VT_UI1;//把值给VARIANT对象 
 
  varPic.parray=safeArray; //把值给VARIANT对象 
 
} 
 
3> 把数据写到数据库中 
 
ACCESS2003: 
 
pRecordset->AddNew(); 
 
try 
 
{ 
 
pRecordset->PutCollect("Name",_variant_t("zhang1")); 
 
pRecordset->GetFields()->GetItem("Picture")->AppendChunk(varPic); 
 
} 
 
catch(_com_error e) 
 
{ 
 
  MessageBox("Add pic to access is falied!"); 
 
} 
 
pRecordset->Update(); 
 
sql2000: 
 
pRecordsetSql->AddNew(); 
 

try 
 
{ 
 
  pRecordsetSql->PutCollect("Name",_variant_t("zhang1")); 
 
  pRecordsetSql->GetFields()->GetItem("Pic")->AppendChunk(SavePic(FileBuff,FileLen)); 
 
} 
 
catch(_com_error e) 
 
{ 
 
  MessageBox("Add picture to sqlserver2000 is failed!"); 
 
} 
 
pRecordsetSql->Update(); 
 
在数据库中读取位图信息并显示出来: 
 
其实读取并且显示过程的过程也非常的简单,主要是把它们在数据库中读取出来,放到一个内存空间中,然后把这此些读取出来的信息再转换成一个BITMAP就可以显示了,(如果不明白怎么转换的话,可以看一下关于位图的文件格式,我关于它的一些信息,也可以参与一下本人的《VC下显示位图的几种方法》里面有详细的解释) 
 
进入正题: 
 
_variant_t TheValue;//存储读出来的数据 
 
DWORD DataSize;//在数据库中读取出来的位图的大小 
 

char *pBuff;//用于存放位图的内存空间 
 
CString str="select * from Picture";//SQL语句^_^ 
 
BSTR bstrRecordset=str.AllocSysString();//这句也不用解释了吧 
 
HBITMAP hBitmap;//定义一个HBITMAP对象,用于显示位图用 
 
try 
 
{ 
 
  pRecordset->Open(bstrRecordset,pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText); 
 
  pRecordset->MoveLast(); 
 
  TheValue=pRecordset->GetCollect("Picture");//读取字段一 
 
DataSize=pRecordset->GetFields()->GetItem("Picture")->ActualSize;//得到位图字段的大小 
 
  if(DataSize>0)//判断那个位图字段是否为空 
 
  { 
 
   if(TheValue.vt==(VT_ARRAY|VT_UI1)) 
 
   { 
 
    if(pBuff=new char[DataSize+1]) 
 
    { 
 
     char *buff; 
 
/***********************主要也就下面这几句画,其它的和显示位图相似**************************/ 
 
     SafeArrayAccessData(TheValue.parray,(void**)&buff);//把位图数据放到buff中去 
 
     memcpy(pBuff,buff,DataSize);//把位图数据放到pBuff中 
 
     SafeArrayUnaccessData(TheValue.parray);//释放 
 
     hBitmap=MemTOPic(pBuff);//这是一个自字义 
 
    } 
 
   } 
 
  } 
 
} 
 
catch(_com_error e) 
 
{ 
 
  MessageBox("打开数据表失败!"); 
 
  return ; 
 
} 
 
/******************根据HBITMAP把位图显示出来************************/ 
 
CBitmap cBitmap; 
 
CClientDC *pDC=new CClientDC(this); 
 
BITMAP bitmap; 
 
CDC MemDC; 
 
cBitmap.Attach(hBitmap); 
 
MemDC.CreateCompatibleDC(pDC); 
 
MemDC.SelectObject(&cBitmap); 
 
cBitmap.GetBitmap(&bitmap); 
 
pDC->StretchBlt(0,0,bitmap.bmWidth,bitmap.bmHeight,&MemDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); 
 
MemDC.DeleteDC(); 
 
::DeleteObject(&bitmap); 
 
/*************自定义函数************把内存数据转为HBITMAP***************************/ 
 
HBITMAP CDBPicDllDlg::MemTOPic(char *buff) 
 
{ 
 

HBITMAP hBitmap=NULL; 
 
LPSTR hDib=NULL; 
 
LPSTR PicBuff=NULL; 
 
PicBuff=buff; 
 
LPVOID pDibBit=NULL; 
 
BITMAPFILEHEADER bmpHead;//位图头结构 
 
DWORD LenBmpHead; 
 
LenBmpHead=sizeof(BITMAPFILEHEADER); 
 
strncpy((LPSTR)&bmpHead,PicBuff,LenBmpHead); 
 
// memcpy((LPSTR)&bmpHead,PicBuff,LenBmpHead); 
 
if(bmpHead.bfType!=(*(WORD*)"BM"))//(*(WORD*)"BM") 
 
{ 
 
  MessageBox("您选择的图片不是bmp图片!"); 
 
  return NULL; 
 
} 
 
hDib=PicBuff+LenBmpHead;//hDib=PicBuff 
 
BITMAPINFOHEADER  &BitmapInfoHead=*(LPBITMAPINFOHEADER)hDib; 
 
BITMAPINFO &BitmapInfo=*(LPBITMAPINFO)hDib; 
 
pDibBit=PicBuff+((BITMAPFILEHEADER*)PicBuff)->bfOffBits; 
 
CClientDC dc(this); 
 
hBitmap=CreateDIBitmap(dc.m_hDC,&BitmapInfoHead,CBM_INIT,pDibBit,&BitmapInfo,DIB_RGB_COLORS); 
 
return hBitmap; 
 
}


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
在SQL2000下方法也是相同的,这里就不重复了。由于时间原因今天这里只是和大家讨论了BMP文件,接下来我会把一些关于JPG的文件的在数据库的读写方法总结出来,供大家交流之用。