如何分块导入大位图,图像大小为1.2G左右,有什么类可以用吗?还是用API函数?该怎么做呢?对其进行处理还得新建一个位图以存放处理完后的数据吧?谁有现成的代码吗?谢谢
解决方案 »
- 垂直滚动条的问题
- 不透明的图案填充算法,大家帮忙看看
- C++通过InternetReadFile函数取得url地址的内容后出现错误
- 用VC2005制作DLL,并使用Microsoft Web浏览器控件
- 如何在对话框里嵌一个FrameWnd?
- 关于一个GetTickCount()的问题
- 高手指教!!
- 渴求仪表数据采集的程序
- 在listctrl控件的header上放置图片无法显示
- 我是一个VC++的初学者,在帮助文件的制作中遇到了困难,万望各位大侠能帮我一把,也望能和大家多多交友,给我一些好的学习建议。因初次到访,仅有20分,望见谅!
- VC调用java的web服务,url里汉字问题
- VS2010 MFC使用Excel出错
//获取像素数据的大小(文件总长度-位图文件头的长度-位图信息的长度)
DWORD dwSize=dwFileLength-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFO); //Read the image by stocks
lWidth=bitmapinfo.bmiHeader.biWidth;
nBitCount=bitmapinfo.bmiHeader.biBitCount;
LONG lLineByte=WIDTHBYTE(lWidth*nBitCount);
DWORD dwSize1=lLineByte*10000;
m_hDIB1=(HGLOBAL)::GlobalAlloc(GMEM_MOVEABLE,dwSize1);
BYTE* m_pdib1=(BYTE*)::GlobalLock((HGLOBAL)m_hDIB1);
DWORD dwReadSize1=dibFile.Read((void*)m_pdib1,dwSize1); DWORD dwSize2=lLineByte*10000;
m_hDIB2=(HGLOBAL)::GlobalAlloc(GMEM_MOVEABLE,dwSize2);
BYTE* m_pdib2=(BYTE*)::GlobalLock((HGLOBAL)m_hDIB2);
DWORD dwReadSize2=dibFile.Read((void*)m_pdib2,dwSize2); DWORD dwSize3=lLineByte*10000;
m_hDIB3=(HGLOBAL)::GlobalAlloc(GMEM_MOVEABLE,dwSize3);
BYTE* m_pdib3=(BYTE*)::GlobalLock((HGLOBAL)m_hDIB3);
DWORD dwReadSize3=dibFile.Read((void*)m_pdib3,dwSize3); DWORD dwSize4=dwSize-lLineByte*30000;
m_hDIB4=(HGLOBAL)::GlobalAlloc(GMEM_MOVEABLE,dwSize4);
BYTE* m_pdib4=(BYTE*)::GlobalLock((HGLOBAL)m_hDIB4);
DWORD dwReadSize4=dibFile.Read((void*)m_pdib4,dwSize4);
首先,我需要知道你用什么方法实现图像在DC上的显示,反正不管什么方法,最后肯定用到windows API位图显示函数,以及位图句柄CBitmap m_hDIB1 ,以及位图指针CBitmap *m_pdib1,按照你的理解,把位图分块就是把文件按照大小分割,才得到m_pdib1,m_pdib2,m_pdib3,m_pdib4。但其实呢?除了第一个m_pdib1,其他的你得到的仅仅是一堆像素数据,并没有包含bitmapinfo信息,windows API位图显示函数不可能识别出来的。
因此,图像分割不是说像你想象的那样把图像数据分成几份就可以的,还需要分别给他们加上bitmapinfo,使他们分别成为一个独立的完整位图。另外单单把原有的bitmapinfo头拿来直接用,也是不行的,一看你就没好好看我的回答。我再次强调下
这里的DIB头信息中的图像宽度、高度需要根据你所分的块进行修改,
再次强调:黑白位图(就是单色图)和灰度图(大部分教材提到的都是指256色,8位图)是两回事,存储方式都不一样,别搞混了。
要是想把黑白图像转成8位图,那么DIB头信息还需要更改biBitCount、biClrUsed、biSizeImage的信息,调色板不能用原来的,需要自己加,就是从0,0,0,0 1,1,1,0 一直添加到255,255,255,0,最后像素数据也要从1位表示,改成8位表示
CreateFileMapping
MapViewOfFile
// 创建文件内核对象,其句柄保存于hFile
HANDLE hFile = CreateFile(
lpszPathName,
GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING, //注意这里是打开现有的CREATE_ALWAYS新建
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
DWORD dwFileSize;
// 得到文件的大小
dwFileSize = GetFileSize(hFile,NULL);
// 创建文件映射内核对象,句柄保存于hFileMapping
HANDLE hFileMapping = CreateFileMapping(hFile,
NULL,
PAGE_READWRITE,
0,//(DWORD)(dwBitsSize >> 32), //因为我的文件不可能超过4G,所以我就没有采用__int64类型,
//而是DWORD类,如果超过4G,请把dwBitsSize定义为__int64,然后采用注释掉的语句就可以了
dwFileSize,//(DWORD)(dwBitsSize & 0xFFFFFFFF),
NULL);
// 释放文件内核对象
CloseHandle(hFile);
// 设定大小、偏移量等参数 __int64是long long类型64位整数
__int64 qwFileOffset = 0;
// 将文件数据映射到进程的地址空间
PBYTE pbFile = (PBYTE)MapViewOfFile(
hFileMapping,FILE_MAP_ALL_ACCESS,
(DWORD)(qwFileOffset>>32),
(DWORD)(qwFileOffset&0xFFFFFFFF),
dwFileSize);
BITMAPFILEHEADER bmfHeader; //bmp文件头结构
BITMAPINFO lpDIBHdr; //DIB头结构
PBYTE lpDIBBits; //DIB像素数据首地址
//获取bmp文件头数据
memcpy(&bmfHeader,pbFile,sizeof(bmfHeader));
//获取DIB头信息
memcpy(&lpDIBHdr,pbFile+sizeof(bmfHeader), *(pbFile+sizeof(bmfHeader)));
//获得DIB像素首地址
lpDIBBits = pbFile + sizeof(bmfHeader) + *(pbFile+sizeof(bmfHeader));
// 从进程的地址空间撤消文件数据映像
UnmapViewOfFile(pbFile);
// 关闭文件映射对象
CloseHandle(hFileMapping);
经过验证完全没有问题,你要知道,大部分高手都比较懒,因为他们已经回答过好多遍了,所以都懒得回答太详细的内容,许多时候往往只是提点一句两句,给你提供一个方向,然后就需要你自己去研究,只有这样得来的东西才是自己的,否则拿来就用,往往学的似是而非,学习程序一定要有研究精神,我喜欢回答详细一点是因为我也是初学者,我学C++还不到3个月,学习图像处理也才2个月,只有在回答问题的过程中,才能发现自己没有理解到的地方。
createdibsection()函数
HBITMAP CreateDIBSection(HDC hdc,CONST BITMAPINFO *pbmi,UINT iUsage,VOID** ppvBits,HANDLE hSection,DWORD dwOffset);
如果函数执行成功,那么返回值是一个指向刚刚创建的与设备无关位图的句柄,并且*ppvBits指向该位图的位数据值;如果函数执行失败,那么返回值为NULL,并且*ppvBit也为NULL
memcpy(&bmfHeader,pbFile,sizeof(bmfHeader));
提示读取位置时发生访问冲突。这是为什么?
你不贴怎么知道哪里错了,再说根据我的用法的话
//获取bmp文件头数据
memcpy(&bmfHeader,pbFile,sizeof(bmfHeader));
//获取DIB头信息
memcpy(&lpDIBHdr,pbFile+sizeof(bmfHeader), *(pbFile+sizeof(bmfHeader)));
//获得DIB像素首地址
lpDIBBits = pbFile + sizeof(bmfHeader) + *(pbFile+sizeof(bmfHeader));
sizeof(bmfHeader)和*(pbFile+sizeof(bmfHeader))应该都不大,也就几十字节
lpDIBBits只是一个地址,不涉及大小问题。
要出错也可能是*(pbFile+sizeof(bmfHeader))这个地址的值有问题。
有问题自己追踪把,很可能机器运行的过程和你想象的不一样,调试程序也是非常重要的一步。
memcpy(&bmfHeader,pbFile,sizeof(bmfHeader));
追踪到memcpy.asm中,调试指针指向:UnwindUp3:
mov eax,[esi+ecx*4-12] ;U(entry)/V(not) - get dword from source
;V(entry) - spare
mov [edi+ecx*4-12],eax ;U - put dword into destination
我在导入560MB图像都没问题,但到了1G就出错了,我真的搞不懂呢。
你追踪这个毫无意义,你只需要查看出错时,sizeof(bmfHeader),pbFile,&bmfHeader这些数据的值就好了
你可以依次察看*(pbFile),*(pbFile+1),*(pbFile+2),。,*(pbFile+sizeof(bmfHeader)-1)的值啊
看看是不是符合你预期的数值,sizeof(bmfHeader)不大,而且是个固定植。
memcpy抱错只可能是你的pbfile当前指针指向有问题,另外如果pbFile是空也会出问题的,加条语句判断一下吧