为什么我提取出来的位图为有偏移的现象.看了全部程序也没找出原因!! 为什么我提取出来的位图为有偏移的现象.看了全部程序也没找出原因!!就是横向有偏移!!象素的点应该是从下自上,从左至右的吧.我现在就是从中间靠左一点开始描一样的!!描到最后再把前面的描上.发生错位了.现象就是这样!!不知道大家有没有出现这种问题啊??需要帮忙解决!谢谢了!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 BMP有个填充象素你有没有考虑到?就是BMP文件规定行的象素数是4的倍数,不足的要填充,你没有考虑这个的话描绘出来的图像就有可能是倾斜的.我给你代码,里面的skip就是计算填充的.//------------读灰度BMP文件,返回data 为正向存储的矩阵.bool ReadBMP(char *file,BITMAPFILEHEADER_ *bmph,BITMAPINFO_ *bmpi,unsigned char **data){ int i,pos; FILE *f=fopen(file,"rb"); if(f==NULL) //判断文件是否打开成功 { return false; } fseek(f,0,0);//移动到开头 //----------读BMP文件头 if(fread((char*)bmph,sizeof(BITMAPFILEHEADER_),1,f)==NULL) { return false; } //-----------读BMP信息头 if(fread((char*)bmpi,sizeof(BITMAPINFO_),1,f)==NULL) { return false; } fseek(f,bmph->Offbits,0); //定位位图矩阵 int skip=0; //填充象素数 if(bmpi->width%4==0) skip=0; else skip=4-bmpi->width%4; long N=(bmpi->width)*(bmpi->height);//有效象素总数 *data=(unsigned char*)malloc(N); for(i=0;i<(bmpi->width)*(bmpi->height);i++) //清空,变白色. { (*data)[i]=0xff; } unsigned char waste[8]; pos=N-bmpi->width; for(i=0;i<bmpi->height;i++) //读入位图矩阵 { fread(&(*data)[pos],bmpi->width,1,f); fread(waste,skip,1,f); pos=pos-bmpi->width; } fclose(f); return true;} 想来是字节对齐的原因。每一行的像素数据宽度并非简单的是点数*色深/8;还需要对DWORD对齐。 我的代码如下.是画出位图的函数!void CBaseGdi::DrawBmp(CDC* pDC,int x,int y,int wide,int high,CString fName){ LPVOID hBmpData; HPALETTE hpal; HBITMAP bhm_ddb; int NumbColors; BITMAPFILEHEADER bFileH; BITMAPINFOHEADER bFileInfoH; LPBITMAPINFOHEADER lpFileInfoH; CFile FileBmp; CBitmap* pOldMap; CDC pDC1; int wide1,high1; long bytes_per_line; long BmpSize; long ImageSize; BOOL YN=FileBmp.Open(fName,CFile::typeBinary|CFile::modeRead); if(YN==0) { AfxMessageBox("Not Open File!"); return; } FileBmp.Read((unsigned char*)&bFileH,sizeof(BITMAPFILEHEADER)); if(bFileH.bfType!=19778) { FileBmp.Close(); AfxMessageBox("Not A Bitmap File!"); return; } FileBmp.Read((unsigned char*)&bFileInfoH,sizeof(BITMAPINFOHEADER));// BmpSize=bFileH.bfSize-sizeof(BITMAPFILEHEADER); bytes_per_line=(long)((bFileInfoH.biWidth*bFileInfoH.biBitCount+31)/32*4); ImageSize=(long)(bytes_per_line*bFileInfoH.biHeight); if(bFileInfoH.biClrUsed!=0) NumbColors=bFileInfoH.biClrUsed; else { switch(bFileInfoH.biBitCount) { case 1: NumbColors=2; break; case 4: NumbColors=16; break; case 8: NumbColors=256; break; case 24: { // NumbColors=0; FileBmp.Close(); AfxMessageBox("本系统最多支持256色位图!"); return; // break; } default: NumbColors=2; break; } }if(bFileH.bfOffBits!=(DWORD)(NumbColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER))) { AfxMessageBox("The NumbColors is Wrong!"); FileBmp.Close(); return; } bFileH.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+ NumbColors*sizeof(RGBQUAD)+ImageSize; BmpSize=bFileH.bfSize-sizeof(BITMAPFILEHEADER); if((hBmpData=GlobalAlloc(GHND,BmpSize))==0) { AfxMessageBox("The Memory is Wrong!"); FileBmp.Close(); return; } lpFileInfoH=(LPBITMAPINFOHEADER)GlobalLock(hBmpData); FileBmp.Seek(sizeof(BITMAPFILEHEADER),CFile::begin); FileBmp.Read((unsigned char*)lpFileInfoH,BmpSize); if(NumbColors>0)//NumColors不为零,说明用到了调色板 { //为逻辑调色板分配局部内存,大小为逻辑调色板结构长度加NumColors个PALETTENTRYLPLOGPALETTE cp=(LPLOGPALETTE)LocalAlloc(LHND,sizeof(LPLOGPALETTE)+NumbColors*sizeof(PALETTEENTRY)); if(cp!=NULL) { cp->palVersion=0x0300; cp->palNumEntries=NumbColors; //p_bi指向的是调色板开始的位置LPRGBQUAD p_bi= (LPRGBQUAD)((LPSTR)lpFileInfoH +(DWORD)sizeof(BITMAPINFOHEADER)); for(int k=0;k<NumbColors;k++) { cp->palPalEntry[k].peRed=p_bi->rgbRed; cp->palPalEntry[k].peGreen=p_bi->rgbGreen; cp->palPalEntry[k].peBlue=p_bi->rgbBlue; p_bi++; } //产生逻辑调色板 hpal=CreatePalette(cp); LocalFree(cp); } } HPALETTE pOldHpal=NULL; if(hpal)//如果刚才产生了逻辑调色板 { //将新的逻辑调色板选入DC,将旧的逻辑调色板句柄保存在//pOldHpal pOldHpal=SelectPalette(pDC->GetSafeHdc(),hpal,FALSE); RealizePalette(pDC->GetSafeHdc()); } LPSTR p_image=(LPSTR)lpFileInfoH+sizeof(LPBITMAPINFOHEADER)+NumbColors*sizeof(RGBQUAD); //产生位图句柄 bhm_ddb=CreateDIBitmap(pDC->GetSafeHdc(),lpFileInfoH,CBM_INIT,p_image,(LPBITMAPINFO)lpFileInfoH,DIB_RGB_COLORS); //将原来的调色板(如果有的话)选入设备上下文句柄 if(pOldHpal) { SelectPalette(pDC->GetSafeHdc(),pOldHpal,FALSE); hpal=0; } wide1=wide; high1=high; if(bhm_ddb!=0) { pDC1.CreateCompatibleDC(pDC); pOldMap=pDC1.SelectObject(CBitmap::FromHandle(bhm_ddb)); pDC->StretchBlt(x,y,wide1,high1,&pDC1,0,0,lpFileInfoH->biWidth,lpFileInfoH->biHeight,SRCCOPY); pDC1.SelectObject(pOldMap); } GlobalUnlock(hBmpData); GlobalFree(hBmpData); FileBmp.Close(); return;} 还有个问题,我经常会在LocalFree(cp);后出现错误,请高手门看看这段代码是否有错误?还有字节对齐问题!,请教一下该怎么对齐呢??不太懂!!望告知! 请问上面的大姐或兄弟,fread(waste,skip,1,f);这句是干什么用的啊?? 就是读填充的字节啊,BMP文件如果行象素数不是4的倍数就会在文件里填入不足的字节,这句就是读这个填充字节,读到waste里扔掉的啊,不要填充字节嘛,相信你就是要了这个填充字节才出现倾斜得.伤心得说不出话了........... void CBitmapButtons::GetBitMapData(){ if(m_PreFilePathName == m_FilePathName[m_ButtonState]) return; LPVOID hBmpData; BITMAPFILEHEADER bFileH; BITMAPINFOHEADER bFileInfoH; DWORD bytes_per_line; CFile BitMapFile; BOOL YN=BitMapFile.Open(m_FilePathName[m_ButtonState],CFile::modeRead | CFile::typeBinary); if(YN==0) { AfxMessageBox("该文件不存在,请检查!"); m_FilePathName[m_ButtonState] = m_PreFilePathName; return; } m_PreFilePathName = m_FilePathName[m_ButtonState]; BitMapFile.Read((unsigned char*)&bFileH,sizeof(BITMAPFILEHEADER)); if(bFileH.bfType!=19778) { BitMapFile.Close(); AfxMessageBox("Not A Bitmap File!"); return; } BitMapFile.Read((unsigned char*)&bFileInfoH,sizeof(BITMAPINFOHEADER)); m_BMPWidth[m_ButtonState] = bFileInfoH.biWidth; m_BMPHeight[m_ButtonState] = bFileInfoH.biHeight; switch(bFileInfoH.biBitCount) { case 1: m_BMPType[m_ButtonState] = 0; break; case 4: m_BMPType[m_ButtonState] = 1; break; case 8: m_BMPType[m_ButtonState] = 2; break; case 24: {// m_BMPType = 3; BitMapFile.Close(); AfxMessageBox("本系统最多支持256色位图!"); return; } } m_BMPSize[m_ButtonState]=bFileH.bfSize-sizeof(BITMAPFILEHEADER); bytes_per_line=(DWORD)((bFileInfoH.biWidth*bFileInfoH.biBitCount+31)/32*4); //有效象素总数 m_BMPImageSize[m_ButtonState]=(DWORD)(bytes_per_line*bFileInfoH.biHeight);// m_BMPImageSize = bFileInfoH.biSizeImage; if(bFileInfoH.biClrUsed!=0) m_NumbColors[m_ButtonState]=bFileInfoH.biClrUsed; else { switch(bFileInfoH.biBitCount) { case 1: m_NumbColors[m_ButtonState]=2; break; case 4: m_NumbColors[m_ButtonState]=16; break; case 8: m_NumbColors[m_ButtonState]=256; break; case 24: m_NumbColors[m_ButtonState]=0; break; default: m_NumbColors[m_ButtonState]=2; break; } } if(bFileH.bfOffBits!=(DWORD)(m_NumbColors[m_ButtonState]*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER))) { AfxMessageBox("The NumbColors is Wrong!"); BitMapFile.Close(); return; } bFileH.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+ m_NumbColors[m_ButtonState]*sizeof(RGBQUAD)+m_BMPImageSize[m_ButtonState]; m_BMPSize[m_ButtonState]=bFileH.bfSize-sizeof(BITMAPFILEHEADER); if((hBmpData=GlobalAlloc(GHND,m_BMPSize[m_ButtonState]))==0) { AfxMessageBox("The Memory is Wrong!"); BitMapFile.Close(); return; } lpFileInfoH[m_ButtonState]=(LPBITMAPINFOHEADER)GlobalLock(hBmpData); BitMapFile.Seek(sizeof(BITMAPFILEHEADER),CFile::begin); BitMapFile.Read((unsigned char*)lpFileInfoH[m_ButtonState],m_BMPSize[m_ButtonState]);///*// LPSTR STR = ((LPSTR)lpFileInfoH)+8;//*/ BitMapFile.Close();} 上面的这段是我的读取位图的函数!!我是已经算好了.行象素已经是4的整数倍了!!!但我没有进行清空变白!!是不是这个问题??我现在是整块而且很整齐的移位了.而不是杂乱的.上面的兄弟姐妹们,能不能解释以下啊??sboom(+-LingCh-+)(怪你过分美丽) 能否留个联系方法!!我可以多向你请教!!谢谢 >>我经常会在LocalFree(cp);后出现错误cp 使用 LHND 分配的,LHNM = LMEM_MOVEABLE | LMEM_ZEROINIT.由于是Moveable, 所以需要先Lock再使用。像素错位:LPSTR p_image=(LPSTR)lpFileInfoH+sizeof(LPBITMAPINFOHEADER)+NumbColors*sizeof(RGBQUAD);就是这儿啦,结构错写成了指针。结果 sizeof(LPBITMAPINFOHEADER) = 4。眼睛都看花了...... 太感谢whoo(谁) 了.象素错位就是你说的那个地方!!改了就可以了.谢谢大家了!! 继承自CListCtrl的自定义类中的DrawItem成员函数为什么不被调用? 如何让爷爷窗口来响应本窗口的消息 在activex中如何关闭主对话框 急急 枚举系统安装程序的一点疑问 有dll,h和map文件。。请问我该怎么引用这个动态链接库? 关于DrawText的小问题 关于消息的几个问题,谢谢 急啊,CFile写数据文件!!!在线等待了…… 想要一个类似FPE的功能,最好有源代码 文件拖拽功能的疑问 求 CDHtmlDialog中如何设置某种颜色透明?(比如用来设置边角透明)
//------------读灰度BMP文件,返回data 为正向存储的矩阵.
bool ReadBMP(char *file,BITMAPFILEHEADER_ *bmph,BITMAPINFO_ *bmpi,unsigned char **data)
{
int i,pos; FILE *f=fopen(file,"rb"); if(f==NULL) //判断文件是否打开成功
{
return false;
} fseek(f,0,0);//移动到开头 //----------读BMP文件头
if(fread((char*)bmph,sizeof(BITMAPFILEHEADER_),1,f)==NULL)
{
return false;
} //-----------读BMP信息头
if(fread((char*)bmpi,sizeof(BITMAPINFO_),1,f)==NULL)
{
return false;
} fseek(f,bmph->Offbits,0); //定位位图矩阵 int skip=0; //填充象素数
if(bmpi->width%4==0)
skip=0;
else
skip=4-bmpi->width%4; long N=(bmpi->width)*(bmpi->height);//有效象素总数
*data=(unsigned char*)malloc(N);
for(i=0;i<(bmpi->width)*(bmpi->height);i++) //清空,变白色.
{
(*data)[i]=0xff;
} unsigned char waste[8];
pos=N-bmpi->width;
for(i=0;i<bmpi->height;i++) //读入位图矩阵
{
fread(&(*data)[pos],bmpi->width,1,f);
fread(waste,skip,1,f);
pos=pos-bmpi->width;
}
fclose(f); return true;
}
每一行的像素数据宽度并非简单的是点数*色深/8;还需要对DWORD对齐。
void CBaseGdi::DrawBmp(CDC* pDC,int x,int y,int wide,int high,CString fName)
{
LPVOID hBmpData;
HPALETTE hpal;
HBITMAP bhm_ddb;
int NumbColors; BITMAPFILEHEADER bFileH;
BITMAPINFOHEADER bFileInfoH;
LPBITMAPINFOHEADER lpFileInfoH;
CFile FileBmp;
CBitmap* pOldMap;
CDC pDC1;
int wide1,high1;
long bytes_per_line;
long BmpSize;
long ImageSize; BOOL YN=FileBmp.Open(fName,CFile::typeBinary|CFile::modeRead);
if(YN==0)
{
AfxMessageBox("Not Open File!");
return;
} FileBmp.Read((unsigned char*)&bFileH,sizeof(BITMAPFILEHEADER));
if(bFileH.bfType!=19778)
{
FileBmp.Close();
AfxMessageBox("Not A Bitmap File!");
return;
}
FileBmp.Read((unsigned char*)&bFileInfoH,sizeof(BITMAPINFOHEADER));
// BmpSize=bFileH.bfSize-sizeof(BITMAPFILEHEADER);
bytes_per_line=(long)((bFileInfoH.biWidth*bFileInfoH.biBitCount+31)/32*4);
ImageSize=(long)(bytes_per_line*bFileInfoH.biHeight);
if(bFileInfoH.biClrUsed!=0)
NumbColors=bFileInfoH.biClrUsed;
else
{
switch(bFileInfoH.biBitCount)
{
case 1: NumbColors=2; break;
case 4: NumbColors=16; break;
case 8: NumbColors=256; break;
case 24:
{
// NumbColors=0;
FileBmp.Close();
AfxMessageBox("本系统最多支持256色位图!");
return;
// break;
}
default: NumbColors=2; break;
}
}
if(bFileH.bfOffBits!=(DWORD)(NumbColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)))
{
AfxMessageBox("The NumbColors is Wrong!");
FileBmp.Close();
return;
}
bFileH.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
NumbColors*sizeof(RGBQUAD)+ImageSize;
BmpSize=bFileH.bfSize-sizeof(BITMAPFILEHEADER); if((hBmpData=GlobalAlloc(GHND,BmpSize))==0)
{
AfxMessageBox("The Memory is Wrong!");
FileBmp.Close();
return;
}
lpFileInfoH=(LPBITMAPINFOHEADER)GlobalLock(hBmpData);
FileBmp.Seek(sizeof(BITMAPFILEHEADER),CFile::begin);
FileBmp.Read((unsigned char*)lpFileInfoH,BmpSize); if(NumbColors>0)//NumColors不为零,说明用到了调色板
{
//为逻辑调色板分配局部内存,大小为逻辑调色板结构长度加NumColors个PALETTENTRYLPLOGPALETTE cp=(LPLOGPALETTE)LocalAlloc(LHND,sizeof(LPLOGPALETTE)+NumbColors*sizeof(PALETTEENTRY)); if(cp!=NULL)
{
cp->palVersion=0x0300;
cp->palNumEntries=NumbColors;
//p_bi指向的是调色板开始的位置
LPRGBQUAD p_bi= (LPRGBQUAD)((LPSTR)lpFileInfoH +(DWORD)sizeof(BITMAPINFOHEADER));
for(int k=0;k<NumbColors;k++)
{
cp->palPalEntry[k].peRed=p_bi->rgbRed;
cp->palPalEntry[k].peGreen=p_bi->rgbGreen;
cp->palPalEntry[k].peBlue=p_bi->rgbBlue;
p_bi++;
}
//产生逻辑调色板 hpal=CreatePalette(cp);
LocalFree(cp);
}
}
HPALETTE pOldHpal=NULL;
if(hpal)//如果刚才产生了逻辑调色板
{
//将新的逻辑调色板选入DC,将旧的逻辑调色板句柄保存在//pOldHpal pOldHpal=SelectPalette(pDC->GetSafeHdc(),hpal,FALSE);
RealizePalette(pDC->GetSafeHdc());
}
LPSTR p_image=(LPSTR)lpFileInfoH+sizeof(LPBITMAPINFOHEADER)+NumbColors*sizeof(RGBQUAD);
//产生位图句柄
bhm_ddb=CreateDIBitmap(pDC->GetSafeHdc(),lpFileInfoH,CBM_INIT,p_image,(LPBITMAPINFO)lpFileInfoH,DIB_RGB_COLORS);
//将原来的调色板(如果有的话)选入设备上下文句柄 if(pOldHpal)
{
SelectPalette(pDC->GetSafeHdc(),pOldHpal,FALSE);
hpal=0;
} wide1=wide;
high1=high;
if(bhm_ddb!=0)
{
pDC1.CreateCompatibleDC(pDC);
pOldMap=pDC1.SelectObject(CBitmap::FromHandle(bhm_ddb));
pDC->StretchBlt(x,y,wide1,high1,&pDC1,0,0,lpFileInfoH->biWidth,lpFileInfoH->biHeight,SRCCOPY);
pDC1.SelectObject(pOldMap);
} GlobalUnlock(hBmpData);
GlobalFree(hBmpData);
FileBmp.Close();
return;}
还有字节对齐问题!,请教一下该怎么对齐呢??不太懂!!望告知!
伤心得说不出话了...........
{
if(m_PreFilePathName == m_FilePathName[m_ButtonState])
return; LPVOID hBmpData; BITMAPFILEHEADER bFileH;
BITMAPINFOHEADER bFileInfoH; DWORD bytes_per_line; CFile BitMapFile;
BOOL YN=BitMapFile.Open(m_FilePathName[m_ButtonState],CFile::modeRead | CFile::typeBinary);
if(YN==0)
{
AfxMessageBox("该文件不存在,请检查!");
m_FilePathName[m_ButtonState] = m_PreFilePathName;
return;
} m_PreFilePathName = m_FilePathName[m_ButtonState]; BitMapFile.Read((unsigned char*)&bFileH,sizeof(BITMAPFILEHEADER));
if(bFileH.bfType!=19778)
{
BitMapFile.Close();
AfxMessageBox("Not A Bitmap File!");
return;
} BitMapFile.Read((unsigned char*)&bFileInfoH,sizeof(BITMAPINFOHEADER)); m_BMPWidth[m_ButtonState] = bFileInfoH.biWidth;
m_BMPHeight[m_ButtonState] = bFileInfoH.biHeight; switch(bFileInfoH.biBitCount)
{
case 1: m_BMPType[m_ButtonState] = 0; break;
case 4: m_BMPType[m_ButtonState] = 1; break;
case 8: m_BMPType[m_ButtonState] = 2; break;
case 24:
{
// m_BMPType = 3; BitMapFile.Close();
AfxMessageBox("本系统最多支持256色位图!");
return;
}
} m_BMPSize[m_ButtonState]=bFileH.bfSize-sizeof(BITMAPFILEHEADER);
bytes_per_line=(DWORD)((bFileInfoH.biWidth*bFileInfoH.biBitCount+31)/32*4);
//有效象素总数
m_BMPImageSize[m_ButtonState]=(DWORD)(bytes_per_line*bFileInfoH.biHeight);
// m_BMPImageSize = bFileInfoH.biSizeImage;
if(bFileInfoH.biClrUsed!=0)
m_NumbColors[m_ButtonState]=bFileInfoH.biClrUsed;
else
{
switch(bFileInfoH.biBitCount)
{
case 1: m_NumbColors[m_ButtonState]=2; break;
case 4: m_NumbColors[m_ButtonState]=16; break;
case 8: m_NumbColors[m_ButtonState]=256; break;
case 24: m_NumbColors[m_ButtonState]=0; break;
default: m_NumbColors[m_ButtonState]=2; break;
}
}
if(bFileH.bfOffBits!=(DWORD)(m_NumbColors[m_ButtonState]*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)))
{
AfxMessageBox("The NumbColors is Wrong!");
BitMapFile.Close();
return;
}
bFileH.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
m_NumbColors[m_ButtonState]*sizeof(RGBQUAD)+m_BMPImageSize[m_ButtonState];
m_BMPSize[m_ButtonState]=bFileH.bfSize-sizeof(BITMAPFILEHEADER); if((hBmpData=GlobalAlloc(GHND,m_BMPSize[m_ButtonState]))==0)
{
AfxMessageBox("The Memory is Wrong!");
BitMapFile.Close();
return;
}
lpFileInfoH[m_ButtonState]=(LPBITMAPINFOHEADER)GlobalLock(hBmpData); BitMapFile.Seek(sizeof(BITMAPFILEHEADER),CFile::begin);
BitMapFile.Read((unsigned char*)lpFileInfoH[m_ButtonState],m_BMPSize[m_ButtonState]);
///*
// LPSTR STR = ((LPSTR)lpFileInfoH)+8;
//*/
BitMapFile.Close();}
sboom(+-LingCh-+)(怪你过分美丽) 能否留个联系方法!!我可以多向你请教!!谢谢
>>我经常会在LocalFree(cp);后出现错误
cp 使用 LHND 分配的,LHNM = LMEM_MOVEABLE | LMEM_ZEROINIT.
由于是Moveable, 所以需要先Lock再使用。像素错位:
LPSTR p_image=(LPSTR)lpFileInfoH+sizeof(LPBITMAPINFOHEADER)+NumbColors*sizeof(RGBQUAD);就是这儿啦,结构错写成了指针。
结果 sizeof(LPBITMAPINFOHEADER) = 4。眼睛都看花了......