怎么把bmp图像二值化,变成黑白两色

arabicsara 2011-08-30 09:17:10
bmp可以是256色,24位位图,16位位图或单色位图,我要把它转成只有黑白两色的图像
我试了n种方法都不行,一种是GetDIBits或GetBitmapBits得到bmp的数据;
	CBitmap   m_Bitmap; 
//m_Bitmap.LoadBitmap()

m_Bitmap.m_hObject = LoadImage(NULL,strFilePath,IMAGE_BITMAP,0, 0,LR_LOADFROMFILE);
BITMAP btm;
m_Bitmap.GetBitmap(&btm);
if (btm.bmWidth!=104&&btm.bmHeight!=80)
{
AfxMessageBox(L"logo像素需符合:104*80!");
return 0;
}


#if 1
CDC dc;
dc.CreateDC(L"DISPLAY",NULL,NULL,NULL);

// BITMAP btm;
//bm.GetBitmap(&btm);
DWORD size=btm.bmWidthBytes*btm.bmHeight;
LPSTR lpData=(LPSTR)GlobalAllocPtr(GPTR,size);
//BYTE *pBmpBuffer = new BYTE[size];
//memset(pBmpBuffer,0,size);
/////////////////////////////////////////////
BITMAPINFOHEADER bih;
bih.biBitCount=btm.bmBitsPixel;
bih.biClrImportant=0;
bih.biClrUsed=0;
bih.biCompression=0;
bih.biHeight=btm.bmHeight;
bih.biPlanes=1;
bih.biSize=sizeof(BITMAPINFOHEADER);
bih.biSizeImage=size;
bih.biWidth=btm.bmWidth;
bih.biXPelsPerMeter=0;
bih.biYPelsPerMeter=0;
///////////////////////////////////
GetDIBits(dc,m_Bitmap,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);

//TraceShow(L"logo:",pBmpBuffer,size,0);
// TRACE(lpData);

bih.biBitCount=1;//btm.bmBitsPixel;
BITMAPFILEHEADER bfh;
bfh.bfReserved1=bfh.bfReserved2=0;
bfh.bfType=((WORD)('M'<< 8)|'B');
bfh.bfSize=54+size;
bfh.bfOffBits=54;

CFile bf;
if(bf.Open(strFilePath+L".bmp",CFile::modeCreate|CFile::modeWrite)){
bf.Write(&bfh,sizeof(BITMAPFILEHEADER));
bf.Write(&bih,sizeof(BITMAPINFOHEADER));
bf.Write(lpData,size);
bf.Close();
// nCount++;
}
GlobalFreePtr(lpData);

//IFDELS(pBmpBuffer)

m_Bitmap.Detach();
#endif

另一种方法用了GDI+,保存的时候,不知道怎么保存成biBitCount=1的单色的图片,图片还不全是黑和白
	Color color,colorTemp;

Bitmap Bimage(L"C:\\24.bmp");
int bWidth=Bimage.GetWidth();
int bHeight=Bimage.GetHeight();
//graphics.DrawImage(&Bimage,20,bHeight-10,bWidth,bHeight);
Bitmap* Bimage2=Bimage.Clone(0,0,bWidth,bHeight,PixelFormatDontCare);
int i,j,middle;
for(i=bWidth;i>0;i--)
{
for(j=bHeight;j>0;j--)
{
Bimage.GetPixel(i,j,&color);
middle=(color.GetRed()+color.GetGreen()+color.GetBlue())/3;
if(middle<128)
middle=0;
else
middle=255;
Bimage2->SetPixel(i,j,middle);
}
}
CLSID pngClsid;
GetEncoderClsid(L"image/bmp", &pngClsid);

又试了CDib类的一种方法,好像只能处理24色的,处理结果图像变成乱码:

BOOL CDib::Load( const TCHAR *pszFilename )
{

CFile cf;

// Attempt to open the Dib file for reading.
if( !cf.Open( pszFilename, CFile::modeRead ) )
return( FALSE );

// Get the size of the file and store
// in a local variable. Subtract the
// size of the BITMAPFILEHEADER structure
// since we won't keep that in memory.
DWORD dwDibSize;
dwDibSize =cf.GetLength() - sizeof( BITMAPFILEHEADER );

// Attempt to allocate the Dib memory.
unsigned char *pDib;
pDib = new unsigned char [dwDibSize];
if( pDib == NULL )
return( FALSE );

BITMAPFILEHEADER BFH;

// Read in the Dib header and data.
try{
// Did we read in the entire BITMAPFILEHEADER?
if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) )
!= sizeof( BITMAPFILEHEADER ) ||

// Is the type 'MB'?
BFH.bfType != 'MB' ||

// Did we read in the remaining data?
cf.Read( pDib, dwDibSize ) != dwDibSize ){

// Delete the memory if we had any
// errors and return FALSE.
delete [] pDib;
return( FALSE );
}
}

// If we catch an exception, delete the
// exception, the temporary Dib memory,
// and return FALSE.
catch( CFileException *e ){
e->Delete();
delete [] pDib;
return( FALSE );
}

cf.Close();
// If we got to this point, the Dib has been
// loaded. If a Dib was already loaded into
// this class, we must now delete it.
if( m_pDib != NULL )
delete m_pDib;

// Store the local Dib data pointer and
// Dib size variables in the class member
// variables.
m_pDib = pDib;
m_dwDibSize = dwDibSize;

// Pointer our BITMAPINFOHEADER and RGBQUAD
// variables to the correct place in the Dib data.
m_pBIH = (BITMAPINFOHEADER *) m_pDib;
m_pPalette =
(RGBQUAD *) &m_pDib[sizeof(BITMAPINFOHEADER)];

// Calculate the number of palette entries.
m_nPaletteEntries = 1 << m_pBIH->biBitCount;
if( m_pBIH->biBitCount > 8 )
m_nPaletteEntries = 0;
else if( m_pBIH->biClrUsed != 0 )
m_nPaletteEntries = m_pBIH->biClrUsed;

// Point m_pDibBits to the actual Dib bits data.
m_pDibBits =
&m_pDib[sizeof(BITMAPINFOHEADER)+
m_nPaletteEntries*sizeof(RGBQUAD)];

// If we have a valid palette, delete it.
if( m_Palette.GetSafeHandle() != NULL )
m_Palette.DeleteObject();

// If there are palette entries, we'll need
// to create a LOGPALETTE then create the
// CPalette palette.
if( m_nPaletteEntries != 0 ){

// Allocate the LOGPALETTE structure.
LOGPALETTE *pLogPal = (LOGPALETTE *) new char
[sizeof(LOGPALETTE)+
m_nPaletteEntries*sizeof(PALETTEENTRY)];

if( pLogPal != NULL ){

// Set the LOGPALETTE to version 0x300
// and store the number of palette
// entries.
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = m_nPaletteEntries;

// Store the RGB values into each
// PALETTEENTRY element.
for( int i=0; i<m_nPaletteEntries; i++ ){
pLogPal->palPalEntry[i].peRed =
m_pPalette[i].rgbRed;
pLogPal->palPalEntry[i].peGreen =
m_pPalette[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue =
m_pPalette[i].rgbBlue;
}

// Create the CPalette object and
// delete the LOGPALETTE memory.
m_Palette.CreatePalette( pLogPal );
delete [] pLogPal;
}
}

m_BitCount = 8;
return( TRUE );

}

BOOL CDib::Save( const TCHAR *pszFilename )
{

// If we have no data, we can't save.
if( m_pDib == NULL )
return( FALSE );

CFile cf;

// Attempt to create the file.
if( !cf.Open( pszFilename,
CFile::modeCreate | CFile::modeWrite ) )
return( FALSE );

// Write the data.
try{

// First, create a BITMAPFILEHEADER
// with the correct data.
BITMAPFILEHEADER BFH;
memset( &BFH, 0, sizeof( BITMAPFILEHEADER ) );
BFH.bfType = 'MB';
BFH.bfSize = sizeof( BITMAPFILEHEADER ) + m_dwDibSize;
BFH.bfOffBits = sizeof( BITMAPFILEHEADER ) +
sizeof( BITMAPINFOHEADER ) +
m_nPaletteEntries * sizeof( RGBQUAD );

// Write the BITMAPFILEHEADER and the
// Dib data.
cf.Write( &BFH, sizeof( BITMAPFILEHEADER ) );
cf.Write( m_pDib, m_dwDibSize );
}

// If we get an exception, delete the exception and
// return FALSE.
catch( CFileException *e ){
e->Delete();
return( FALSE );
}

return( TRUE );

}
bool CDib::ConvertToTwoValue()
{
DWORD i,size;
unsigned char *p;
// 一个特别简单的二值化程序
// 以128为界划分

p = m_pDibBits;
size = m_dwDibSize - (m_pDibBits - m_pDib);
for (i = 0; i < size;i++)
{
if (*p < 128)
{
*p = 0;
}
else
{
*p = 255;
}
p++;
}
return true;

}

各位高手有没有好的bmp转成黑白两色的函数接口提供一下,成分感谢!!!
...全文
1014 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
orxor 2011-08-30
  • 打赏
  • 举报
回复
http://www.pudn.com/search_db.asp?keyword=%B6%FE%D6%B5%BB%AF
orxor 2011-08-30
  • 打赏
  • 举报
回复
搜索二值化,给你一堆代码
sjdev 2011-08-30
  • 打赏
  • 举报
回复
qjgdftxmu 2011-08-30
  • 打赏
  • 举报
回复
如果没有大小要求,就直修改像素值就行了

如果想节省大小,自己创建一下,然后像素值根据目标图判定一下。。。。
Eleven 2011-08-30
  • 打赏
  • 举报
回复
我的送神 2011-08-30
  • 打赏
  • 举报
回复
参考下:

if (!image->IsIndexed()) {
// 直接修改像素颜色
COLORREF pixel;
int maxY = image->GetHeight(), maxX = image->GetWidth();
byte r,g,b,avg;
for (int x=0; x<maxX; x++) {
for (int y=0; y<maxY; y++) {
pixel = image->GetPixel(x,y);
r = GetRValue(pixel);
g = GetGValue(pixel);
b = GetBValue(pixel);
avg = (int)((r + g + b)/3);
image->SetPixelRGB(x,y,avg,avg,avg);
}
}
}
morebread 2011-08-30
  • 打赏
  • 举报
回复
好像GDI+直接就可以转的。以前看gdi+教材的时候做过。

建议LZ去下个GDI+教材看看再说
fandh 2011-08-30
  • 打赏
  • 举报
回复
http://www.ooppoo.com/html/35/n-317635.html

arabicsara 2011-08-30
  • 打赏
  • 举报
回复
	if (iLine==LOGO_LINE)//logo:转成灰度图像的C51格式文件
{
CBitmap m_Bitmap;
//m_Bitmap.LoadBitmap()

m_Bitmap.m_hObject = LoadImage(NULL,strFilePath,IMAGE_BITMAP,0, 0,LR_LOADFROMFILE);
BITMAP btm;
m_Bitmap.GetBitmap(&btm);
if (btm.bmWidth!=104&&btm.bmHeight!=80)
{
AfxMessageBox(L"logo像素需符合:104*80!");
return 0;
}

Color color,colorTemp;
Bitmap Bimage(strFilePath);
int bWidth=Bimage.GetWidth();
int bHeight=Bimage.GetHeight();
//graphics.DrawImage(&Bimage,20,bHeight-10,bWidth,bHeight);
Bitmap* Bimage2=Bimage.Clone(0,0,bWidth,bHeight,PixelFormatDontCare);
int i,j,middle;
COLORREF myClr=0;
unsigned char szBmpRgb[1040*8]={0};//
unsigned char szBmp[1040]={0};//104*80/8,8个二进制1变成一个0xFF
int num=0;

for(i=0;i<bHeight;++i)
{
for(j=0;j<bWidth;++j)
{
Bimage.GetPixel(j,i,&color);
middle=(color.GetRed()+color.GetGreen()+color.GetBlue())/3;
if(middle<128)
{
myClr=RGB(0,0,0);
szBmpRgb[num]=1;
}
else
{
myClr=RGB(255,255,255);
}

Bimage2->SetPixel(j,i,myClr);
++num;
}
}
TraceShow(L"LOGO_prefor:",szBmpRgb,bWidth*bHeight,0);

for (int x=0;x< bWidth*bHeight;++x)
{
//unsigned int iVal=0;
if(szBmpRgb[x]==1)
{
szBmp[x/8] |= (0x01 <<(7-x%8) );
}
}


CLSID pngClsid;
GetEncoderClsid(L"image/bmp", &pngClsid);

Bimage2->Save(strFilePath+L"Show.tmp",&pngClsid,NULL);
int len=1040;
TraceShow(L"LOGO:",szBmp,len,0);
ZSaveFileU(szBmp,len,strFilePath+L"Down.tmp");
ok了,谢谢大家!
fengbingchun 2011-08-30
  • 打赏
  • 举报
回复
opencv的cvCvtColor即可实现或者用cvThreshold也可以

19,469

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧