VC++6.0 bmp 灰度二值化 25
用VC++6.0显示BMP文件,,A图2)在这个图旁边设一个0-100的条,随着灰度数值变化,图像变化,。。B图急求一个完成程序,好心的大哥大姐们帮帮忙吧...
用VC++6.0显示BMP文件,,A图
2)在这个图旁边设一个0-100的条,随着灰度数值变化,图像变化,。。B图
急求一个完成程序,好心的大哥大姐们帮帮忙吧 展开
2)在这个图旁边设一个0-100的条,随着灰度数值变化,图像变化,。。B图
急求一个完成程序,好心的大哥大姐们帮帮忙吧 展开
展开全部
class CBmp
{
public:
PBITMAPINFO pBmi; //位图信息头+调色板指针
PBYTE pBits; //图像数据指针
public:
CBmp();
//CBMp(const CBmp &bmpObj);
CBmp& operator=( const CBmp &bmpObj );
virtual ~CBmp();
public:
BOOL Read( const CString &Filename ); //读入一幅bmp图像
BOOL Write( const CString &Filename ); //保存一幅bmp图像
int GetWidth( ) const; //获得图像的宽度(像素)
int GetHeight( ) const; //获得图像的高度(像素)
int GetPaletteSize( ) const; //获得调色板长度
int GetBytesPerLine( ) const; //获得存储每行的字节数
BOOL IsValid( ) const; //判断图像是否存在该类对象中
BOOL IsGrayScaleImage( ) const; //判断是否灰度图
BOOL ToGrayScaleImage( ); //转化为灰度图
void Binarize( int threshold ); //对图像进行二值化处理
private:
BOOL ToGrayScaleImage_2Color( ); //单色图像转化为灰度图
BOOL ToGrayScaleImage_16Color( ); //4位位图转化为灰度图
BOOL ToGrayScaleImage_256Color( ); //8位位图转化为灰度图
BOOL ToGrayScaleImage_TrueColor( ); //真彩色位图转化为灰度图
};
CBmp::CBmp()
{
pBmi = NULL;
pBits = NULL;
}
/*
CBmp::CBMp(const CBmp &bmpObj)
{
int nInfoSize = sizeof(BITMAPINFOHEADER) + bmpObj.GetPaletteSize() * sizeof(RGBQUAD);
pBmi = (PBITMAPINFO)new BYTE[nInfoSize];
memcpy( (PVOID)pBmi, (PVOID)bmpObj.pBmi,nInfoSize);
int nImageSize = pBmi->bmiHeader.biSizeImage;
pBits = new BYTE[nImageSize];
memcpy((PVOID)pBits,(PVOID)bmpObj.pBits,nImageSize);
}
*/
CBmp& CBmp::operator=( const CBmp &bmpObj )
{
if ( this == &bmpObj ) //等号两边的对象若是同一个,则不必再做后续操作
return *this;
//销毁原数据
if ( pBmi ) delete pBmi;
if ( pBits ) delete pBits;
//生成新的位图信息头+调色板
int nInfoSize = sizeof( BITMAPINFO ) + bmpObj.GetPaletteSize( ) * sizeof( RGBQUAD );
pBmi = (PBITMAPINFO)new BYTE[ nInfoSize ];
memcpy( (PVOID)pBmi, (PVOID)bmpObj.pBmi, nInfoSize );
//生成新的位图数据
int nImageSize = pBmi->bmiHeader.biSizeImage;
pBits = new BYTE[ nImageSize ];
memcpy( (PVOID)pBits, (PVOID)bmpObj.pBits, nImageSize );
return *this;
}
CBmp::~CBmp()
{
if ( pBmi )
{
delete pBmi;
pBmi = NULL;
}
if ( pBits )
{
delete pBits;
pBits = NULL;
}
}
BOOL CBmp::Read( const CString &FileName )
{
CFile file;
BITMAPFILEHEADER bmfh;
//打开文件
if ( !file.Open(FileName,CFile::modeRead) )
{
AfxMessageBox( "文件打开错误!" );
return FALSE;
}
//读文件信息头
file.Read( (PVOID)&bmfh, sizeof(BITMAPFILEHEADER) );
if ( bmfh.bfType != 0x4d42 )
{
AfxMessageBox( "不是位图文件!");
return FALSE;
}
//销毁原数据
if ( pBmi )
{
delete pBmi;
pBmi = NULL;
}
if ( pBits )
{
delete pBits;
pBits = NULL;
}
//读位图信息头和调色板
int nInfoSize = bmfh.bfOffBits - sizeof( BITMAPFILEHEADER );
pBmi = (PBITMAPINFO)new BYTE[ nInfoSize ];
file.Read( (PVOID)pBmi, nInfoSize );
if ( pBmi->bmiHeader.biBitCount!=1 && pBmi->bmiHeader.biBitCount!=4 && \
pBmi->bmiHeader.biBitCount!=8 && pBmi->bmiHeader.biBitCount!=24 )
{
CString s;
s.Format( "%d", pBmi->bmiHeader.biBitCount );
AfxMessageBox( (CString)"颜色位数为"+s+(CString)"位,不满足处理要求!" );
delete pBmi;
pBmi = NULL;
return FALSE;
}
//读像素数据
int nImageSize = pBmi->bmiHeader.biSizeImage;
pBits = new BYTE[ nImageSize ];
file.Read( (PVOID)pBits, nImageSize );
file.Close( );
return TRUE;
}
BOOL CBmp::Write( const CString &Filename )
{
CFile file;
BITMAPFILEHEADER bmfh;
if ( !(pBmi && pBits ) )
{
AfxMessageBox( "数据无效!" );
return FALSE;
}
//创建文件
if ( !file.Open(Filename,CFile::modeWrite|CFile::modeCreate) )
{
AfxMessageBox( "创建文件错误!" );
return FALSE;
}
//计算长度数据
int nBitsSize = pBmi->bmiHeader.biSizeImage; //像素数据部分
int nInfoSize = sizeof(BITMAPINFOHEADER) + GetPaletteSize() * sizeof(RGBQUAD); //位图信息头+调色板
int nHeaderSize = sizeof(bmfh) + nInfoSize; //文件信息头+位图信息头+调色板
int nFileSize = nHeaderSize + nBitsSize; //文件信息头+位图信息头+调色板+像素数据部分
//填写文件信息头
bmfh.bfType = 0x4d42;
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
bmfh.bfOffBits = nHeaderSize;
bmfh.bfSize = nFileSize;
//文件信息头写入文件
file.Write( (PVOID)&bmfh, sizeof(bmfh) );
file.Write( (PVOID)pBmi, nInfoSize );
file.Write( (PVOID)pBits, nBitsSize );
file.Close( );
return TRUE;
}
//获得图像宽度(像素)
int CBmp::GetWidth( ) const
{
if ( pBmi )
return pBmi->bmiHeader.biWidth;
else
return 0;
}
//获得图像高度(像素)
int CBmp::GetHeight( ) const
{
if ( pBmi )
return pBmi->bmiHeader.biHeight;
else
return 0;
}
//获得调色板长度
int CBmp::GetPaletteSize( ) const
{
if ( !pBmi )
return -1;
switch ( pBmi->bmiHeader.biBitCount )
{
case 1: return 2;
case 4: return 16;
case 8: return 256;
case 24: return 0;
default: return -1;
}
}
//获得存储每行的字节数
int CBmp::GetBytesPerLine( ) const
{
if ( !pBmi )
return -1;
return
pBmi->bmiHeader.biSizeImage / pBmi->bmiHeader.biHeight;
}
//判断图像是否存在该类对象中
BOOL CBmp::IsValid( ) const
{
return ( pBmi && pBits );
}
//判断是否灰度图
BOOL CBmp::IsGrayScaleImage( ) const
{
if ( !pBmi || pBmi->bmiHeader.biBitCount!=8 )
return FALSE;
LPRGBQUAD pPalette = pBmi->bmiColors;
for ( int i = 0; i < 256; i++ )
if ( pPalette[i].rgbBlue!=pPalette[i].rgbGreen || pPalette[i].rgbGreen!=pPalette[i].rgbRed )
return FALSE;
return TRUE;
}
//转化为灰度图
BOOL CBmp::ToGrayScaleImage( )
{
switch ( pBmi->bmiHeader.biBitCount )
{
case 1: return ToGrayScaleImage_2Color( );
case 4: return ToGrayScaleImage_16Color( );
case 8: return ToGrayScaleImage_256Color( );
case 24: return ToGrayScaleImage_TrueColor( );
default: return FALSE;
}
}
//单色位图转为灰度图
BOOL CBmp::ToGrayScaleImage_2Color( )
{
//计算几组数据
int nBytesPerLine1 = GetBytesPerLine( ); //原 图像每行字节数
int nBytesPerLine2 = ( (GetWidth()+3)/4 ) * 4; //新 图像每行字节数
int nImageSize2 = nBytesPerLine2 * GetHeight( ); //新 像素数据长度
int nInfoSize2 = sizeof( BITMAPINFOHEADER ) + 256 * sizeof( RGBQUAD ); //新 位图信息头+调色板 长度
//定义新图像结构
PBITMAPINFO pBmi2 = (PBITMAPINFO)new BYTE[ nInfoSize2 ];
PBYTE pBits2 = new BYTE[ nImageSize2 ];
//为新位图信息头赋值
memcpy( (PVOID)&(pBmi2->bmiHeader), (PVOID)&(pBmi->bmiHeader), sizeof(BITMAPINFOHEADER) );
pBmi2->bmiHeader.biBitCount = 8;
pBmi2->bmiHeader.biSizeImage = nImageSize2;
//初始化新调色板
LPRGBQUAD pRGB2 = pBmi2->bmiColors;
for ( int i = 0; i < 256; i++ )
pRGB2[i].rgbRed = pRGB2[i].rgbGreen = pRGB2[i].rgbBlue = i;
//填写新图像的各像素
int nLineStart1; //原 图像每行的起始位置
int nLineStart2; //新 图像每行的起始位置
for ( int h = 0; h < GetHeight(); h++ )
{
nLineStart1 = nBytesPerLine1 * h;
nLineStart2 = nBytesPerLine2 * h;
BYTE tag;
for ( int w = 0; w < GetWidth(); w++ )
{
tag = BYTE( 0x80 ) >> ( w%8 );
if ( pBits[nLineStart1+w/8] & tag )
pBits2[ nLineStart2+w ] = 255;
else
pBits2[ nLineStart2+w ] = 0;
}
}
//删除原图像信息并赋新值
delete pBmi;
pBmi = pBmi2;
delete pBits;
pBits = pBits2;
return TRUE;
}
//4位位图转为灰度图
BOOL CBmp::ToGrayScaleImage_16Color( )
{
//计算几组数据
int nBytesPerLine1 = GetBytesPerLine( ); //原 图像每行字节数
int nBytesPerLine2 = ( (GetWidth()+3)/4 ) * 4; //新 图像每行字节数
int nImageSize2 = nBytesPerLine2 * GetHeight( ); //新 像素数据长度
int nInfoSize2 = sizeof( BITMAPINFOHEADER ) + 256 * sizeof( RGBQUAD ); //新 位图信息头+调色板 长度
//定义新图像结构
PBITMAPINFO pBmi2 = (PBITMAPINFO)new BYTE[ nInfoSize2 ];
PBYTE pBits2 = new BYTE[ nImageSize2 ];
//为新位图信息头赋值
memcpy( (PVOID)&(pBmi2->bmiHeader), (PVOID)&(pBmi->bmiHeader), sizeof(BITMAPINFOHEADER) );
pBmi2->bmiHeader.biBitCount = 8;
pBmi2->bmiHeader.biSizeImage = nImageSize2;
//初始化新调色板
LPRGBQUAD pRGB2 = pBmi2->bmiColors;
for ( int i = 0; i < 256; i++ )
pRGB2[i].rgbRed = pRGB2[i].rgbGreen = pRGB2[i].rgbBlue = i;
//填写新图像的各像素
int nLineStart1; //原 图像每行的起始位置
int nLineStart2; //新 图像每行的起始位置
LPRGBQUAD pRGB1 = pBmi->bmiColors; //原 调色板指针
for ( int h = 0; h < GetHeight(); h++ )
{
nLineStart1 = nBytesPerLine1 * h;
nLineStart2 = nBytesPerLine2 * h;
int nDbColors;
int nColor;
for ( int w = 0; w < GetWidth(); w++ )
{
nDbColors = pBits[ nLineStart1+w/2 ]; //包含两个像素信息
if ( w%2==0 ) //前一像素
{
nColor = nDbColors / 16;
pBits2[ nLineStart2+w ] = int( (float)pRGB1[nColor].rgbRed * 0.299 + \
(float)pRGB1[nColor].rgbGreen * 0.587 + \
(float)pRGB1[nColor].rgbBlue * 0.114 );
}
else //后一像素
{
nColor = nDbColors % 16;
pBits2[ nLineStart2+w ] = int( (float)pRGB1[nColor].rgbRed * 0.299 + \
(float)pRGB1[nColor].rgbGreen * 0.587 + \
(float)pRGB1[nColor].rgbBlue * 0.114 );
}
}
}
//删除原图像信息并赋新值
delete pBmi;
pBmi = pBmi2;
delete pBits;
pBits = pBits2;
return TRUE;
}
//8位位图转为灰度图
BOOL CBmp::ToGrayScaleImage_256Color( )
{
//修改像素值
int nLineStart;
LPRGBQUAD pRGB = pBmi->bmiColors;
for ( int h = 0; h < GetHeight(); h++ )
{
nLineStart = GetBytesPerLine( ) * h;
int nColor;
for ( int w = 0; w < GetWidth(); w++ )
{
nColor = pBits[ nLineStart+w ];
pBits[ nLineStart+w ] = int( (float)pRGB[nColor].rgbRed * 0.299 + \
(float)pRGB[nColor].rgbGreen * 0.587 + \
(float)pRGB[nColor].rgbBlue * 0.114 );
}
}
//修改调色板
for ( int i = 0; i < 256; i++ )
pRGB[i].rgbRed = pRGB[i].rgbGreen = pRGB[i].rgbBlue = i;
return TRUE;
}
//真彩色位图转为灰度图
BOOL CBmp::ToGrayScaleImage_TrueColor( )
{
//计算几组数据
int nBytesPerLine1 = GetBytesPerLine( ); //原 图像每行字节数
int nBytesPerLine2 = ( (GetWidth()+3)/4 ) * 4; //新 图像每行字节数
int nImageSize2 = nBytesPerLine2 * GetHeight( ); //新 像素数据长度
int nInfoSize2 = sizeof( BITMAPINFOHEADER ) + 256 * sizeof( RGBQUAD ); //新 位图信息头+调色板 长度
//定义新图像结构
PBITMAPINFO pBmi2 = (PBITMAPINFO)new BYTE[ nInfoSize2 ];
PBYTE pBits2 = new BYTE[ nImageSize2 ];
//为新位图信息头赋值
memcpy( (PVOID)&(pBmi2->bmiHeader), (PVOID)&(pBmi->bmiHeader),sizeof(BITMAPINFOHEADER) );
pBmi2->bmiHeader.biBitCount = 8;
pBmi2->bmiHeader.biSizeImage = nImageSize2;
//初始化新调色板
LPRGBQUAD pRGB = pBmi2->bmiColors;
for ( int i = 0; i < 256; i++ )
pRGB[i].rgbRed = pRGB[i].rgbGreen = pRGB[i].rgbBlue = i;
//填写新图像的各像素
int nLineStart1; //原 图像每行的起始位置
int nLineStart2; //新 图像每行的起始位置
for ( int h = 0; h < GetHeight(); h++ )
{
nLineStart1 = nBytesPerLine1 * h;
nLineStart2 = nBytesPerLine2 * h;
for ( int w = 0; w < GetWidth(); w++ )
pBits2[nLineStart2+w] = int( (float)pBits[nLineStart1 + 3 * w] * 0.114 + \
(float)pBits[nLineStart1 + 3 * w + 1] * 0.587 + \
(float)pBits[nLineStart1 + 3 * w + 2] * 0.299 );
}
//删除原图像信息并赋新值
delete pBmi;
pBmi = pBmi2;
delete pBits;
pBits = pBits2;
return TRUE;
}
//二值化
void CBmp::Binarize( int threshold )
{
if ( !IsGrayScaleImage() )
{
AfxMessageBox( "不是灰度图!" );
return;
}
int nLineStart; //每行开始的字节号
for ( int h = 0; h < GetHeight(); h++ )
{
nLineStart = GetBytesPerLine( ) * h;
for ( int w = 0; w < GetWidth(); w++ )
if ( pBits[nLineStart+w] < threshold )
pBits[ nLineStart+w ] = 0;
else
pBits[ nLineStart+w ] = 255;
}
}
{
public:
PBITMAPINFO pBmi; //位图信息头+调色板指针
PBYTE pBits; //图像数据指针
public:
CBmp();
//CBMp(const CBmp &bmpObj);
CBmp& operator=( const CBmp &bmpObj );
virtual ~CBmp();
public:
BOOL Read( const CString &Filename ); //读入一幅bmp图像
BOOL Write( const CString &Filename ); //保存一幅bmp图像
int GetWidth( ) const; //获得图像的宽度(像素)
int GetHeight( ) const; //获得图像的高度(像素)
int GetPaletteSize( ) const; //获得调色板长度
int GetBytesPerLine( ) const; //获得存储每行的字节数
BOOL IsValid( ) const; //判断图像是否存在该类对象中
BOOL IsGrayScaleImage( ) const; //判断是否灰度图
BOOL ToGrayScaleImage( ); //转化为灰度图
void Binarize( int threshold ); //对图像进行二值化处理
private:
BOOL ToGrayScaleImage_2Color( ); //单色图像转化为灰度图
BOOL ToGrayScaleImage_16Color( ); //4位位图转化为灰度图
BOOL ToGrayScaleImage_256Color( ); //8位位图转化为灰度图
BOOL ToGrayScaleImage_TrueColor( ); //真彩色位图转化为灰度图
};
CBmp::CBmp()
{
pBmi = NULL;
pBits = NULL;
}
/*
CBmp::CBMp(const CBmp &bmpObj)
{
int nInfoSize = sizeof(BITMAPINFOHEADER) + bmpObj.GetPaletteSize() * sizeof(RGBQUAD);
pBmi = (PBITMAPINFO)new BYTE[nInfoSize];
memcpy( (PVOID)pBmi, (PVOID)bmpObj.pBmi,nInfoSize);
int nImageSize = pBmi->bmiHeader.biSizeImage;
pBits = new BYTE[nImageSize];
memcpy((PVOID)pBits,(PVOID)bmpObj.pBits,nImageSize);
}
*/
CBmp& CBmp::operator=( const CBmp &bmpObj )
{
if ( this == &bmpObj ) //等号两边的对象若是同一个,则不必再做后续操作
return *this;
//销毁原数据
if ( pBmi ) delete pBmi;
if ( pBits ) delete pBits;
//生成新的位图信息头+调色板
int nInfoSize = sizeof( BITMAPINFO ) + bmpObj.GetPaletteSize( ) * sizeof( RGBQUAD );
pBmi = (PBITMAPINFO)new BYTE[ nInfoSize ];
memcpy( (PVOID)pBmi, (PVOID)bmpObj.pBmi, nInfoSize );
//生成新的位图数据
int nImageSize = pBmi->bmiHeader.biSizeImage;
pBits = new BYTE[ nImageSize ];
memcpy( (PVOID)pBits, (PVOID)bmpObj.pBits, nImageSize );
return *this;
}
CBmp::~CBmp()
{
if ( pBmi )
{
delete pBmi;
pBmi = NULL;
}
if ( pBits )
{
delete pBits;
pBits = NULL;
}
}
BOOL CBmp::Read( const CString &FileName )
{
CFile file;
BITMAPFILEHEADER bmfh;
//打开文件
if ( !file.Open(FileName,CFile::modeRead) )
{
AfxMessageBox( "文件打开错误!" );
return FALSE;
}
//读文件信息头
file.Read( (PVOID)&bmfh, sizeof(BITMAPFILEHEADER) );
if ( bmfh.bfType != 0x4d42 )
{
AfxMessageBox( "不是位图文件!");
return FALSE;
}
//销毁原数据
if ( pBmi )
{
delete pBmi;
pBmi = NULL;
}
if ( pBits )
{
delete pBits;
pBits = NULL;
}
//读位图信息头和调色板
int nInfoSize = bmfh.bfOffBits - sizeof( BITMAPFILEHEADER );
pBmi = (PBITMAPINFO)new BYTE[ nInfoSize ];
file.Read( (PVOID)pBmi, nInfoSize );
if ( pBmi->bmiHeader.biBitCount!=1 && pBmi->bmiHeader.biBitCount!=4 && \
pBmi->bmiHeader.biBitCount!=8 && pBmi->bmiHeader.biBitCount!=24 )
{
CString s;
s.Format( "%d", pBmi->bmiHeader.biBitCount );
AfxMessageBox( (CString)"颜色位数为"+s+(CString)"位,不满足处理要求!" );
delete pBmi;
pBmi = NULL;
return FALSE;
}
//读像素数据
int nImageSize = pBmi->bmiHeader.biSizeImage;
pBits = new BYTE[ nImageSize ];
file.Read( (PVOID)pBits, nImageSize );
file.Close( );
return TRUE;
}
BOOL CBmp::Write( const CString &Filename )
{
CFile file;
BITMAPFILEHEADER bmfh;
if ( !(pBmi && pBits ) )
{
AfxMessageBox( "数据无效!" );
return FALSE;
}
//创建文件
if ( !file.Open(Filename,CFile::modeWrite|CFile::modeCreate) )
{
AfxMessageBox( "创建文件错误!" );
return FALSE;
}
//计算长度数据
int nBitsSize = pBmi->bmiHeader.biSizeImage; //像素数据部分
int nInfoSize = sizeof(BITMAPINFOHEADER) + GetPaletteSize() * sizeof(RGBQUAD); //位图信息头+调色板
int nHeaderSize = sizeof(bmfh) + nInfoSize; //文件信息头+位图信息头+调色板
int nFileSize = nHeaderSize + nBitsSize; //文件信息头+位图信息头+调色板+像素数据部分
//填写文件信息头
bmfh.bfType = 0x4d42;
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
bmfh.bfOffBits = nHeaderSize;
bmfh.bfSize = nFileSize;
//文件信息头写入文件
file.Write( (PVOID)&bmfh, sizeof(bmfh) );
file.Write( (PVOID)pBmi, nInfoSize );
file.Write( (PVOID)pBits, nBitsSize );
file.Close( );
return TRUE;
}
//获得图像宽度(像素)
int CBmp::GetWidth( ) const
{
if ( pBmi )
return pBmi->bmiHeader.biWidth;
else
return 0;
}
//获得图像高度(像素)
int CBmp::GetHeight( ) const
{
if ( pBmi )
return pBmi->bmiHeader.biHeight;
else
return 0;
}
//获得调色板长度
int CBmp::GetPaletteSize( ) const
{
if ( !pBmi )
return -1;
switch ( pBmi->bmiHeader.biBitCount )
{
case 1: return 2;
case 4: return 16;
case 8: return 256;
case 24: return 0;
default: return -1;
}
}
//获得存储每行的字节数
int CBmp::GetBytesPerLine( ) const
{
if ( !pBmi )
return -1;
return
pBmi->bmiHeader.biSizeImage / pBmi->bmiHeader.biHeight;
}
//判断图像是否存在该类对象中
BOOL CBmp::IsValid( ) const
{
return ( pBmi && pBits );
}
//判断是否灰度图
BOOL CBmp::IsGrayScaleImage( ) const
{
if ( !pBmi || pBmi->bmiHeader.biBitCount!=8 )
return FALSE;
LPRGBQUAD pPalette = pBmi->bmiColors;
for ( int i = 0; i < 256; i++ )
if ( pPalette[i].rgbBlue!=pPalette[i].rgbGreen || pPalette[i].rgbGreen!=pPalette[i].rgbRed )
return FALSE;
return TRUE;
}
//转化为灰度图
BOOL CBmp::ToGrayScaleImage( )
{
switch ( pBmi->bmiHeader.biBitCount )
{
case 1: return ToGrayScaleImage_2Color( );
case 4: return ToGrayScaleImage_16Color( );
case 8: return ToGrayScaleImage_256Color( );
case 24: return ToGrayScaleImage_TrueColor( );
default: return FALSE;
}
}
//单色位图转为灰度图
BOOL CBmp::ToGrayScaleImage_2Color( )
{
//计算几组数据
int nBytesPerLine1 = GetBytesPerLine( ); //原 图像每行字节数
int nBytesPerLine2 = ( (GetWidth()+3)/4 ) * 4; //新 图像每行字节数
int nImageSize2 = nBytesPerLine2 * GetHeight( ); //新 像素数据长度
int nInfoSize2 = sizeof( BITMAPINFOHEADER ) + 256 * sizeof( RGBQUAD ); //新 位图信息头+调色板 长度
//定义新图像结构
PBITMAPINFO pBmi2 = (PBITMAPINFO)new BYTE[ nInfoSize2 ];
PBYTE pBits2 = new BYTE[ nImageSize2 ];
//为新位图信息头赋值
memcpy( (PVOID)&(pBmi2->bmiHeader), (PVOID)&(pBmi->bmiHeader), sizeof(BITMAPINFOHEADER) );
pBmi2->bmiHeader.biBitCount = 8;
pBmi2->bmiHeader.biSizeImage = nImageSize2;
//初始化新调色板
LPRGBQUAD pRGB2 = pBmi2->bmiColors;
for ( int i = 0; i < 256; i++ )
pRGB2[i].rgbRed = pRGB2[i].rgbGreen = pRGB2[i].rgbBlue = i;
//填写新图像的各像素
int nLineStart1; //原 图像每行的起始位置
int nLineStart2; //新 图像每行的起始位置
for ( int h = 0; h < GetHeight(); h++ )
{
nLineStart1 = nBytesPerLine1 * h;
nLineStart2 = nBytesPerLine2 * h;
BYTE tag;
for ( int w = 0; w < GetWidth(); w++ )
{
tag = BYTE( 0x80 ) >> ( w%8 );
if ( pBits[nLineStart1+w/8] & tag )
pBits2[ nLineStart2+w ] = 255;
else
pBits2[ nLineStart2+w ] = 0;
}
}
//删除原图像信息并赋新值
delete pBmi;
pBmi = pBmi2;
delete pBits;
pBits = pBits2;
return TRUE;
}
//4位位图转为灰度图
BOOL CBmp::ToGrayScaleImage_16Color( )
{
//计算几组数据
int nBytesPerLine1 = GetBytesPerLine( ); //原 图像每行字节数
int nBytesPerLine2 = ( (GetWidth()+3)/4 ) * 4; //新 图像每行字节数
int nImageSize2 = nBytesPerLine2 * GetHeight( ); //新 像素数据长度
int nInfoSize2 = sizeof( BITMAPINFOHEADER ) + 256 * sizeof( RGBQUAD ); //新 位图信息头+调色板 长度
//定义新图像结构
PBITMAPINFO pBmi2 = (PBITMAPINFO)new BYTE[ nInfoSize2 ];
PBYTE pBits2 = new BYTE[ nImageSize2 ];
//为新位图信息头赋值
memcpy( (PVOID)&(pBmi2->bmiHeader), (PVOID)&(pBmi->bmiHeader), sizeof(BITMAPINFOHEADER) );
pBmi2->bmiHeader.biBitCount = 8;
pBmi2->bmiHeader.biSizeImage = nImageSize2;
//初始化新调色板
LPRGBQUAD pRGB2 = pBmi2->bmiColors;
for ( int i = 0; i < 256; i++ )
pRGB2[i].rgbRed = pRGB2[i].rgbGreen = pRGB2[i].rgbBlue = i;
//填写新图像的各像素
int nLineStart1; //原 图像每行的起始位置
int nLineStart2; //新 图像每行的起始位置
LPRGBQUAD pRGB1 = pBmi->bmiColors; //原 调色板指针
for ( int h = 0; h < GetHeight(); h++ )
{
nLineStart1 = nBytesPerLine1 * h;
nLineStart2 = nBytesPerLine2 * h;
int nDbColors;
int nColor;
for ( int w = 0; w < GetWidth(); w++ )
{
nDbColors = pBits[ nLineStart1+w/2 ]; //包含两个像素信息
if ( w%2==0 ) //前一像素
{
nColor = nDbColors / 16;
pBits2[ nLineStart2+w ] = int( (float)pRGB1[nColor].rgbRed * 0.299 + \
(float)pRGB1[nColor].rgbGreen * 0.587 + \
(float)pRGB1[nColor].rgbBlue * 0.114 );
}
else //后一像素
{
nColor = nDbColors % 16;
pBits2[ nLineStart2+w ] = int( (float)pRGB1[nColor].rgbRed * 0.299 + \
(float)pRGB1[nColor].rgbGreen * 0.587 + \
(float)pRGB1[nColor].rgbBlue * 0.114 );
}
}
}
//删除原图像信息并赋新值
delete pBmi;
pBmi = pBmi2;
delete pBits;
pBits = pBits2;
return TRUE;
}
//8位位图转为灰度图
BOOL CBmp::ToGrayScaleImage_256Color( )
{
//修改像素值
int nLineStart;
LPRGBQUAD pRGB = pBmi->bmiColors;
for ( int h = 0; h < GetHeight(); h++ )
{
nLineStart = GetBytesPerLine( ) * h;
int nColor;
for ( int w = 0; w < GetWidth(); w++ )
{
nColor = pBits[ nLineStart+w ];
pBits[ nLineStart+w ] = int( (float)pRGB[nColor].rgbRed * 0.299 + \
(float)pRGB[nColor].rgbGreen * 0.587 + \
(float)pRGB[nColor].rgbBlue * 0.114 );
}
}
//修改调色板
for ( int i = 0; i < 256; i++ )
pRGB[i].rgbRed = pRGB[i].rgbGreen = pRGB[i].rgbBlue = i;
return TRUE;
}
//真彩色位图转为灰度图
BOOL CBmp::ToGrayScaleImage_TrueColor( )
{
//计算几组数据
int nBytesPerLine1 = GetBytesPerLine( ); //原 图像每行字节数
int nBytesPerLine2 = ( (GetWidth()+3)/4 ) * 4; //新 图像每行字节数
int nImageSize2 = nBytesPerLine2 * GetHeight( ); //新 像素数据长度
int nInfoSize2 = sizeof( BITMAPINFOHEADER ) + 256 * sizeof( RGBQUAD ); //新 位图信息头+调色板 长度
//定义新图像结构
PBITMAPINFO pBmi2 = (PBITMAPINFO)new BYTE[ nInfoSize2 ];
PBYTE pBits2 = new BYTE[ nImageSize2 ];
//为新位图信息头赋值
memcpy( (PVOID)&(pBmi2->bmiHeader), (PVOID)&(pBmi->bmiHeader),sizeof(BITMAPINFOHEADER) );
pBmi2->bmiHeader.biBitCount = 8;
pBmi2->bmiHeader.biSizeImage = nImageSize2;
//初始化新调色板
LPRGBQUAD pRGB = pBmi2->bmiColors;
for ( int i = 0; i < 256; i++ )
pRGB[i].rgbRed = pRGB[i].rgbGreen = pRGB[i].rgbBlue = i;
//填写新图像的各像素
int nLineStart1; //原 图像每行的起始位置
int nLineStart2; //新 图像每行的起始位置
for ( int h = 0; h < GetHeight(); h++ )
{
nLineStart1 = nBytesPerLine1 * h;
nLineStart2 = nBytesPerLine2 * h;
for ( int w = 0; w < GetWidth(); w++ )
pBits2[nLineStart2+w] = int( (float)pBits[nLineStart1 + 3 * w] * 0.114 + \
(float)pBits[nLineStart1 + 3 * w + 1] * 0.587 + \
(float)pBits[nLineStart1 + 3 * w + 2] * 0.299 );
}
//删除原图像信息并赋新值
delete pBmi;
pBmi = pBmi2;
delete pBits;
pBits = pBits2;
return TRUE;
}
//二值化
void CBmp::Binarize( int threshold )
{
if ( !IsGrayScaleImage() )
{
AfxMessageBox( "不是灰度图!" );
return;
}
int nLineStart; //每行开始的字节号
for ( int h = 0; h < GetHeight(); h++ )
{
nLineStart = GetBytesPerLine( ) * h;
for ( int w = 0; w < GetWidth(); w++ )
if ( pBits[nLineStart+w] < threshold )
pBits[ nLineStart+w ] = 0;
else
pBits[ nLineStart+w ] = 255;
}
}
东莞大凡
2024-11-19 广告
2024-11-19 广告
作为东莞市大凡光学科技有限公司的工作人员,对于halcon标定板有所了解。Halcon标定板是高精度相机标定的关键工具,通常采用实心圆点或方格作为标志点。我们公司提供的halcon标定板,具有高精度、稳定可靠的特点,适用于机器视觉领域的各种...
点击进入详情页
本回答由东莞大凡提供
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询