VC++读取数据库中的位图文件

o0o0123123 2014-12-19 08:10:34
小弟在编一个数据库的客户端,需要进行数据库的位图存取,之前试过把位图存进数据库但是在将位图取出的时候在中间的判断是否是位图的地方总是判断不是位图然后就返回了,程序都是在网上淘的,找不到问题,纠结好几天了,求帮忙。。。
char *pBuff = NULL;//用于存放位图的内存空间
try
{
long DataSize;//在数据库中读取出来的位图的大小
DataSize = rec->Fields->GetItem("肖像")->ActualSize;//得到位图字段的大小

if (DataSize>0)//判断那个位图字段是否为空
{
_variant_t TheValue;//存储读出来的数据
TheValue = rec->GetFields()->GetItem(_variant_t("肖像"))->GetChunk(DataSize);//读取字段一
if (TheValue.vt == (VT_ARRAY | VT_UI1))
{
pBuff = new char[DataSize + 1];
if (pBuff)
{
char *buff = NULL;
/***********************主要也就下面这几句画,其它的和显示位图相似**************************/

SafeArrayAccessData(TheValue.parray, (void**)&buff);//把位图数据放到buff中去
memcpy(pBuff, buff, DataSize);//把位图数据放到pBuff中

SafeArrayUnaccessData(TheValue.parray);//释放
char * m_pBMPBuffer = new char[DataSize + 1];//开辟符数组
memset(m_pBMPBuffer, '\0', DataSize + 1);
memcpy(m_pBMPBuffer, pBuff, DataSize);

//将位图内存数据PBuff转为HBITMAP
HBITMAP hBitmap = NULL;//定义一个HBITMAP对象,用于显示位图用
LPSTR hDIB, lpBuffer = m_pBMPBuffer;
LPVOID lpDIBBits;
BITMAPFILEHEADER bmfHeader;
DWORD bmfHeaderLen;
//获得位图的头信息
bmfHeaderLen = sizeof(bmfHeader);
//strncpy_s((LPSTR)&bmfHeader, bmfHeaderLen,(LPSTR)lpBuffer, _TRUNCATE);
memcpy(&bmfHeader, lpBuffer, bmfHeaderLen);

//根据获得的信息头判断是否是位图
if (bmfHeader.bfType != (*(WORD*)"BM"))
{
AfxMessageBox("this is not bitmap!");
return true;
}

//获取位图数据
hDIB = lpBuffer + bmfHeaderLen;//将指针移动到文件头的后面
BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB;
BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB;
lpDIBBits = (lpBuffer)+((BITMAPFILEHEADER *)lpBuffer)->bfOffBits; //偏移字节数
//创建位图
CClientDC dc(this);
hBitmap = CreateDIBitmap(dc.m_hDC, &bmiHeader,
CBM_INIT, lpDIBBits, &bmInfo, DIB_RGB_COLORS);
//显示位图
CBitmap bmp; //定义位图变量
bmp.Attach(hBitmap);
BITMAP bm; //定义一个位图结构
bmp.GetBitmap(&bm);
CDC dcMem;
dcMem.CreateCompatibleDC(GetDC()); //创建一个兼容的DC
CBitmap *poldBitmap = (CBitmap*)dcMem.SelectObject(bmp); //将位图选入设备环境类
CRect lRect; //定义一个区域
CStatic *pstatic = (CStatic*)GetDlgItem(IDC_STATIC);
pstatic->GetClientRect(&lRect); //获取控件的客户区域
lRect.NormalizeRect();

pstatic->GetDC()->StretchBlt(lRect.left, lRect.top, lRect.Width(), lRect.Height(),
&dcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); //显示位图
dcMem.SelectObject(&poldBitmap); //将原有的句柄选入设备环境
bmp.DeleteObject();
}
}
}
}
catch (_com_error e)
{
MessageBox("打开数据表失败!");
return true;
}

在中间的判断是否是位图的地方总是判断不是位图然后就返回了,求大神救命..纠结好几天了。
...全文
188 点赞 收藏 6
写回复
6 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
jacksonfan 2014-12-22
/////////////////////读取记录集当前记录中数据,包括图像数据//////////////
void CADOBlobDlg::ReadData()
{
	DestroyPhoto();						///清除原图像
	if(m_pRecordset->adoEOF||m_pRecordset->BOF) 
	{
		m_UserName.Empty();
		m_Old.Empty();
		UpdateData(FALSE);
		return;
	}
	long lDataSize = m_pRecordset->GetFields()->GetItem("photo")->ActualSize;
	if(lDataSize > 0)
	{
		_variant_t			varBLOB;
		varBLOB = m_pRecordset->GetFields()->GetItem("photo")->GetChunk(lDataSize);
		if(varBLOB.vt == (VT_ARRAY | VT_UI1))
		{
			if(m_pBMPBuffer = new char[lDataSize+1])				///重新分配必要的存储空间
			{	
				char *pBuf = NULL;
				SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
				memcpy(m_pBMPBuffer,pBuf,lDataSize);				///复制数据到缓冲区m_pBMPBuffer
				SafeArrayUnaccessData (varBLOB.parray);
				m_nFileLen = lDataSize;
				m_hPhotoBitmap = BufferToHBITMAP();					///生成BITMAP对象
			}
		}
	}
	m_UserName = m_pRecordset->GetCollect("username").bstrVal;
	m_Old.Format("%d",m_pRecordset->GetCollect("old").lVal);
	m_editUserName.EnableWindow();
	m_editOld.EnableWindow();
	m_buttonSelectPhoto.EnableWindow();
	m_buttonDeleteUser.EnableWindow();
	UpdateData(FALSE);
}

///////////将内存中的BMP文件内容转换到HBITMAP///////
HBITMAP CADOBlobDlg::BufferToHBITMAP()
{
	HBITMAP				hBmp;
	LPSTR				hDIB,lpBuffer = m_pBMPBuffer;
	LPVOID				lpDIBBits;
	BITMAPFILEHEADER	bmfHeader;
	DWORD				bmfHeaderLen;

	bmfHeaderLen = sizeof(bmfHeader);
	strncpy((LPSTR)&bmfHeader,(LPSTR)lpBuffer,bmfHeaderLen);
//	if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B')) return NULL;
	if (bmfHeader.bfType != (*(WORD*)"BM")) return NULL;//copy《Windows程序设计》上的做法。
	hDIB = lpBuffer + bmfHeaderLen;
	BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ;
	BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
	lpDIBBits=(lpBuffer)+((BITMAPFILEHEADER *)lpBuffer)->bfOffBits;
	CClientDC dc(this);
	hBmp = CreateDIBitmap(dc.m_hDC,&bmiHeader,CBM_INIT,lpDIBBits,&bmInfo,DIB_RGB_COLORS);
	return hBmp;
}
回复
hhhh63 2014-12-21
用二进制数据
回复
o0o0123123 2014-12-21
感觉还是之前找的往数据库里写入图片的程序有问题,把写入程序改成如下的,头文件就不会报错了,但是又会在检测24位图像哪里报错,估计还是写入程序有问题,而且直接用位图确实挺大的,每个照片都有1M左右呢。。 for (long index = 0; index <= size; index++) { SafeArrayPutElement(pArray, &index, pBuffer++); }
回复
JasomH 2014-12-19
学习学习....谢谢楼主分享。
回复
Sandrer 2014-12-19
试想一下当用户量激增的时候,你的数据库压力得多大啊 一般存储二进制内容的话,首先考虑一下这个字段的数据会有多少 如果超过某个长度的话(我自己预算是127个字节),那不如把文件分开存放,数据库中只保存数据的路径 因为如果是远程访问,你一次过得把位图的数据select出来,那程序中途会有一段时间的“当”机 上传用ftp,上传成功后把路径存到数据库中 下载用http,首先在数据库中获得远程路径,然后用http进行下载 还可以自己做个下载进度,当然数据库中也可以分段读取,不过比用http下载控制更麻烦(个人觉得) 更何况你用的还是位图,试想一下一幅位图得有多大啊 if (bmfHeader.bfType != (*(WORD*)"BM")) 改成 if (bmfHeader.bfType != MAKEWORD('B', 'M')) 试试
回复
o0o0123123 2014-12-19
char * m_pbufferBMP = new char[fileSize + 1]; memset(m_pbufferBMP, '\0', fileSize + 1); UINT size = file.Read(m_pbufferBMP, fileSize); char *pBuffer = m_pbufferBMP; //这段程序是将图片放置到VARIANT结构中。 VARIANT varPic; SAFEARRAY *pArray; SAFEARRAYBOUND rgsabound[1]; if (pBuffer) { rgsabound[0].lLbound = 0; rgsabound[0].cElements = size; pArray = SafeArrayCreate(VT_UI1, 1, rgsabound); char *byte; SafeArrayAccessData(pArray, (void**)&byte); for (long index = 0; index <= size; ++index) { byte = m_pbufferBMP; } SafeArrayUnaccessData(pArray); varPic.vt = VT_ARRAY | VT_UI1; varPic.parray = pArray; } try //将VARIANT结构中的图片放置入数据库中。 { rec->GetFields()->GetItem(_variant_t("肖像"))->AppendChunk(varPic); //MessageBox("add ok"); } catch (_com_error e) { MessageBox("Add picture to database is failed!"); } 这个是我将位图存入数据库的程序段
回复
相关推荐
发帖
数据库
创建于2007-09-28

3956

社区成员

VC/MFC 数据库
申请成为版主
帖子事件
创建了帖子
2014-12-19 08:10
社区公告
暂无公告