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

BITMAP
测试环境:windows xp2 vc6.0 access2003/sql2000
当前时间所限就先把关于BMP文件的操作总结了一下,在接下来会再总结一下其它几种图片在数据库的操作的。
既然是向数据库中添加位图信息,那么有必须明白我们的数据是以什么形式存放在数据库的,当然没有别的方法,只能是二进制了,所以在创建数据库的时候,一定要注意选择的字段的类型,不然是添加下进去的。(刚开始的时候,我就遇到了这个问题,费了好长时间才搞定的。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的文件的在数据库的读写方法总结出来,供大家交流之用。

 

 

 

 

 


VC下显示位图的几种方法
所属类别:VC++
文章作者:vbcs
推荐指数:★★★★
文档人气:1888
本周人气:23
发布日期:2007-5-14
/*************************************************************/
想来想去还是不能叫做原创,毕竟里面的大部分东西都是前辈们的劳动成功
我只是收集了一下,所以还是叫学习小结的好!
转载请说明出处
如有问题欢迎和本人联系讨论:baoliangster@gmail.com
由于每次上传只能100K所以就所文件给分开了,分为DemoBitmap1.rar,DemoBitmap.rar
下载先解压DemoBitmap.rar,然后把DemoBitmap1.ra解压的内容放到入前一个解压后的文件
中,对于里面的位图文件,只能大家自己准备了,为了节省空间,我就没上传.(上传的时候
出现了错误可能有两个相同的只要选择一个就可以了。)
/*************************************************************/
VC下显示位图的几种方法
总结一下关于位图的几种用法。
说到这还是开头给大家介绍一下,有关位图的知识吧,以及对于我们比较有用的几个关于位图的结构体。
一.位图结构如下:

---- 一、BMP文件结构
---- 1. BMP文件组成
---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。
---- 2. BMP文件头
---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。
---- 其结构定义如下:
typedef struct tagBITMAPFILEHEADER
{
WORDbfType;   // 位图文件的类型,必须为BM
DWORD   bfSize;   // 位图文件的大小,以字节为单位
WORDbfReserved1; // 位图文件保留字,必须为0
WORDbfReserved2; // 位图文件保留字,必须为0
DWORD   bfOffBits; // 位图数据的起始位置,以相对于位图
// 文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;
---- 3. 位图信息头
BMP位图信息头数据用于说明位图的尺寸等信息。
typedef struct tagBITMAPINFOHEADER{
   DWORD biSize;   // 本结构所占用字节数
   LONGbiWidth; // 位图的宽度,以像素为单位
   LONGbiHeight; // 位图的高度,以像素为单位
   WORD   biPlanes; // 目标设备的级别,必须为1
   WORD   biBitCount// 每个像素所需的位数,必须是1(双色),
// 4(16色),8(256色)或24(真彩色)之一
   DWORD biCompression;   // 位图压缩类型,必须是 0(不压缩),
// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
   DWORD biSizeImage; // 位图的大小,以字节为单位
   LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数
   LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数
   DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数
   DWORD biClrImportant;// 位图显示过程中重要的颜色数
} BITMAPINFOHEADER;
---- 4. 颜色表
    颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:
typedef struct tagRGBQUAD {

BYTErgbBlue;// 蓝色的亮度(值范围为0-255)
BYTErgbGreen;   // 绿色的亮度(值范围为0-255)
BYTErgbRed; // 红色的亮度(值范围为0-255)
BYTErgbReserved;// 保留,必须为0
} RGBQUAD;
颜色表中RGBQUAD结构数据的个数有biBitCount来确定:
当biBitCount=1,4,8时,分别有2,16,256个表项;
当biBitCount=24时,没有颜色表项。
   位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
typedef struct tagBITMAPINFO {
   BITMAPINFOHEADER bmiHeader;   // 位图信息头
   RGBQUAD bmiColors[1]; // 颜色表
} BITMAPINFO;
下面我们介绍第一种办法:
//第一种方法,使用WM__CTRLCOLOR来实现
/*******************OnCtlColor中添加的代码*****************/
HBRUSH CDemoBitmapDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

// TODO: Change any attributes of the DC here
//第一种实现方法
if(nCtlColor=CTLCOLOR_DLG)
{
return brush;
}
// TODO: Return a different brush if the default is not desired
return hbr;
}

BOOL CDemoBitmapDlg::OnInitDialog()
{
//第一种方法,使用wm_ctlcolor来实现
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
brush.CreatePatternBrush(&bitmap);//brush定义在头文件中CBrush burush
bitmap.DeleteObject();
}
第二种方法使用资源文件中导入的IDB_BITMAP来实现
第一步先在资源中导入一个位图:IDB_BITMAP1
void CDemoBitmapDlg::OnBtnBitmap()
{
// TODO: Add your control notification handler code here
/***************显示BITMAP的第二种方法**********************/
HBITMAP hBitmap;
CBitmap bitmap;
CClientDC *pDC;
pDC=new CClientDC(this);
hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
bitmap.Attach(hBitmap);
CDC CDCompatible;
CDCompatible.CreateCompatibleDC(pDC);//创建兼容DC
CDCompatible.SelectObject(&bitmap);
/*********其它几种显示方式********/
/* pDC->BitBlt(0,0,200,200,&CDCompatible,0,0,SRCCOPY);
CDCompatible.SetBkMode(TRANSPARENT);
pDC->StretchBlt(0,0,352,288,&CDCompatible,0,0,352,288,SRCCOPY);
    CDCompatible.CreateCompatibleDC(this->GetDC());
    CDCompatible.SelectObject(&bitmap); */ //选择绘图对象
BITMAP bmp;
bitmap.GetBitmap(&bmp);
    pDC->StretchBlt(0,0,bmp.bmWidth,bmp.bmHeight,&CDCompatible,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
    CDCompatible.DeleteDC();
    ::DeleteObject(&bitmap);
}
第三种方法是通过读取指定目录中的位图文件来显示(这里分别把它们显示在Picture控件和Static上面这也是大家通常要用到的):
void CDemoBitmapDlg::OnBtnPic()
{
// TODO: Add your control notification handler code here
/****************向PICTURE控件中动态添加位图****************************/
HBITMAP hBitmap;
CBitmap bitmap;
hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
bitmap.Attach(hBitmap);
m_Pic.SetBitmap(hBitmap);

}
/****************在STATIC中显示位图*********************/
void CDemoBitmapDlg::OnBtnStatic()
{
// TODO: Add your control notification handler code here
CBitmap hbmp;
HBITMAP hbitmap;
//将pStatic指向要显示的地方
CStatic *pStaic;
pStaic=(CStatic*)GetDlgItem(IDC_IMAGE);
// pStaic=(CStatic*)GetDlgItem(IDC_BUTTON1);
//装载资源 MM.bmp是我的一个文件名,用你的替换
hbitmap=(HBITMAP)::LoadImage (::AfxGetInstanceHandle(),"NetFriend.bmp",
IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);

hbmp.Attach(hbitmap);
//获取图片格式
BITMAP bm;
hbmp.GetBitmap(&bm);
CDC dcMem;
dcMem.CreateCompatibleDC(GetDC());
CBitmap *poldBitmap=(CBitmap*)dcMem.SelectObject(hbmp);
CRect lRect;
pStaic->GetClientRect(&lRect);
//显示位图
pStaic->GetDC()->StretchBlt(lRect.left ,lRect.top ,lRect.Width(),lRect.Height(), &dcMem,0 ,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
dcMem.SelectObject(&poldBitmap);
}
/*****************向BUTTON中添加ICON*****************************/
//方法和导入其它位图类似,在这里就只做一个说明一下就是了。
HICON hIco;
hIco=AfxGetApp()->LoadIcon(IDI_ICON1);
m_BtnBitmap.SetIcon(hIco);
第四种读取位图文件来显示位图:
void CDemoBitmapDlg::OnBtnBtmfile()
{
// TODO: Add your control notification handler code here
/*******************通过读取位图文件来显示位图**********************/
CString strFileName;
strFileName.Format("%s","NetFriend.bmp");
//成位图信息BITMAPINFO
BITMAPINFO *bitmapinfo=NULL;
BYTE *BmpData=NULL;
CFile file;//读取位图信息
//设置文件的打开方式
if(!file.Open(strFileName,Cfile::modeRead|Cfile::typeBinary))
{
return;
}
//BITMAP文件头结构体
BITMAPFILEHEADER BitmapHead;
//读取位图文件头
if(file.Read(&BitmapHead,sizeof(BITMAPFILEHEADER))!=sizeof(BITMAPFILEHEADER))
{
MessageBox("读取文件头失败!");
return;
}
if(BitmapHead.bfType!=0x4d42)
{
MessageBox("对不起,您读取的不是位图文件!");
return;
}
//位图信息
BITMAPINFOHEADER BitmapInfo;
if(file.Read(&BitmapInfo,sizeof(BITMAPINFOHEADER))!=sizeof(BITMAPINFOHEADER))
{
MessageBox("读取位图信息失败!");
return;
}
if(BitmapInfo.biBitCount!=24)
{
MessageBox("对不起,当前程序只支持24位位图信息!");
return;
}
bitmapinfo=(BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER)];
if(!bitmapinfo)
{
MessageBox("内存分配失败!");
return;
}
/*把BMP位图信息头中的数据读取到位图信息结构中去.*/
memcpy(bitmapinfo,&BitmapInfo,sizeof(BITMAPINFOHEADER));
/*用来得到位图文件的大小*/
DWORD dataByte=BitmapHead.bfSize-BitmapHead.bfOffBits;
BmpData=(BYTE*)new char[dataByte];
if(!BmpData)
{
MessageBox("内存分配失败!");
delete bitmapinfo;
delete BmpData;
return;
}
if(file.Read(BmpData,dataByte)!=dataByte)
{
MessageBox("读取位图数据失败!");
return;
}
file.Close();
CClientDC *pDC=new CClientDC(this);
pDC->SetStretchBltMode(COLORONCOLOR);
StretchDIBits(pDC->GetSafeHdc(),200,0,BitmapInfo.biWidth,BitmapInfo.biHeight, 0,0,BitmapInfo.biWidth,BitmapInfo.biHeight,BmpData,bitmapinfo,DIB_RGB_COLORS,SRCCOPY);
}
最后给大家介绍两个显示位图的特效的例子更多的特效显示(http://www.pconline.com.cn/pcedu/empolder/gj/vc/0504/608259.html):
1> 水平交错显示位图
void CListBmap::OnButton1()
{
// TODO: Add your control notification handler code here
HBITMAP hBitmap;
CBitmap cBitmap;
hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp", IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
cBitmap.Attach(hBitmap);
cBitmap.GetBitmap(&bitmap);
int i=0,j=0;
CClientDC *pDC=new CClientDC(this);
CDC memDC;
memDC.CreateCompatibleDC(GetDC());
memDC.SelectObject(&cBitmap);
for(i=0;i<bitmap.bmHeight;i+=2)
{
j=i;
while(j>0)
{
   pDC->StretchBlt(0,j-1,bitmap.bmWidth,1,&memDC,0,bitmap.bmHeight-(i-j+1),    bitmap.bmWidth,1,SRCCOPY);
   pDC->StretchBlt(0,bitmap.bmHeight-j,bitmap.bmWidth,1,&memDC,0,i-j,    bitmap.bmWidth,1,SRCCOPY);
   j-=2;
}
Sleep(50);
}

}

2>雨点显示:
void CListBmap::OnButton2()
{
// TODO: Add your control notification handler code here

HBITMAP hBitmap;
CBitmap cBitmap;
hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp", IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
cBitmap.Attach(hBitmap);
cBitmap.GetBitmap(&bitmap);
int i=0,j=0;
CClientDC *pDC=new CClientDC(this);
CDC memDC;
memDC.CreateCompatibleDC(GetDC());
memDC.SelectObject(&cBitmap);
for ( i=0; i<=bitmap.bmHeight; i++ )  
{
for ( j=0; j<=bitmap.bmHeight-i; j++ )
   pDC->StretchBlt(
   0,j,
   //目标设备逻辑横、纵坐标
   bitmap.bmWidth,1,
   //显示位图的像素宽、高度
   &memDC,
   //源位图设备情境对象
   0,bitmap.bmHeight-i,
   //源位图的起始横、纵坐标
   bitmap.bmWidth,1,
   //源位图的像素宽、高度
   SRCCOPY);
Sleep(20);
}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值