📄 img2rgn.cpp
字号:
#include "stdafx.h"
#include "Img2Rgn.h"
///////////////////////////////////////////////
// CImg2Rgn : 用于从BMP中提取区域
CImg2Rgn::CImg2Rgn()
{
m_bmpMaskClr = RGB( 255, 0, 255 );
m_cMask = 0;
m_cIMG = 255;
m_cMark = 1;
m_pointGrow = 1024;
m_pointSize = m_pointGrow;
m_curPointID = 0;
m_pPoint = new POINT[ m_pointSize ];
m_pImgData = NULL;
m_isAttachData = FALSE;
m_bmWidth = 0;
m_bmHeight = 0;
m_isAttachData = FALSE;
}
CImg2Rgn::~CImg2Rgn()
{
ResizePoint( 0 );
SetBMP( NULL );
}
void CImg2Rgn::FreeImgData()
{
//清空以前的数据
if( m_pImgData != NULL && !m_isAttachData )
{
delete m_pImgData;
}
m_pImgData = NULL;
m_bmWidth = m_bmHeight = 0;
m_isAttachData = FALSE;
}
void CImg2Rgn::AttachData( LPVOID pData, long width, long height )
{
FreeImgData();
m_pImgData = (unsigned char*)pData;
m_bmWidth = width;
m_bmHeight = height;
m_isAttachData = TRUE;
}
void CImg2Rgn::SetBMP( CBitmap * pBMP )
{
FreeImgData();
if( pBMP == NULL )
{//没有BMP,返回
return;
}
//取得BMP的大小
BITMAP bmp;
pBMP->GetBitmap( &bmp );
m_bmWidth = bmp.bmWidth;
m_bmHeight = bmp.bmHeight;
if( m_bmWidth * m_bmHeight <= 0 )
{//BMP是空的
return;
}
//申请新的空间
m_pImgData = new unsigned char[m_bmWidth*m_bmHeight];
memset( m_pImgData, m_cIMG, m_bmWidth*m_bmHeight );
//取得BMP的MASK
CDC dc;
dc.CreateCompatibleDC( NULL );;
//准备内存设备用于读取位图
CBitmap * pOldBMP = dc.SelectObject( pBMP );
//取得位图中的MASK
POINT p;
for( p.x = 0; p.x < m_bmWidth; p.x++ )
{
for( p.y = 0; p.y < m_bmHeight; p.y++ )
{
if( dc.GetPixel( p ) == m_bmpMaskClr )
{
SetCell( p, m_cMask );
}
}
}
//清除内存设备中的位图
dc.SelectObject( pOldBMP );
}
BOOL CImg2Rgn::GetRgn( CRgn & rgn )
{
if( m_pImgData == NULL )
{
return FALSE;
}
//取得位图中区域的链点
if( !GetBoundaryPoint() )
{
return FALSE;
}
//用链点来建立区域
rgn.DeleteObject();
return rgn.CreatePolygonRgn( m_pPoint, m_curPointID, ALTERNATE );
}
void CImg2Rgn::ResizePoint( long newSize )
{
if( newSize <= 0 )
{//仅清空此区域
if( m_pPoint != NULL )
{
delete m_pPoint;
}
m_pointSize = 0;
m_curPointID = 0;
return;
}
LPPOINT newPoint = new POINT[newSize];
long copySize = min( newSize, m_pointSize );
memcpy( newPoint, m_pPoint, copySize );
delete m_pPoint;
m_pPoint = newPoint;
m_pointSize = newSize;
m_curPointID = min( m_curPointID, m_pointSize-1 );
}
void CImg2Rgn::AddPoint( POINT point )
{
if( m_curPointID >= m_pointSize )
{
ResizePoint( m_pointSize+m_pointGrow );
}
m_pPoint[m_curPointID] = point;
m_curPointID++;
}
BOOL CImg2Rgn::IsBoundary( POINT point )
{
//超出边界的点不处理,肯定不是边界点
if( point.x < 0 || point.x >= m_bmWidth
|| point.y < 0 || point.y >= m_bmHeight )
{
return FALSE;
}
if( GetCell( point ) != m_cIMG )
{
return FALSE;
}
//位图外边框一定是边界点
if( point.x == 0 || point.x == m_bmWidth-1
|| point.y == 0 || point.y == m_bmHeight-1 )
{
return TRUE;
}
//查看周边情况,左看右看,上看下看,看有没有MASK像素
point.x--;//左边
if( GetCell( point ) == m_cMask )
{
return TRUE;
}
point.x+=2;//右边
if( GetCell( point ) == m_cMask )
{
return TRUE;
}
point.x--;
point.y--;//上边
if( GetCell( point ) == m_cMask )
{
return TRUE;
}
point.y+=2;//下边
if( GetCell( point ) == m_cMask )
{
return TRUE;
}
return FALSE;
}
//搜索周边点用的算子
//顺序:左上,上,右上,右,右下,下,左下,左
static long sxOff[8] = { -1, 0, 1, 1, 1, 0, -1, -1 };
static long syOff[8] = { -1, -1, -1, 0, 1, 1, 1, 0 };
BOOL CImg2Rgn::FindNextPoint( POINT & point )
{
long i, offID = 0;
long dx, dy;
long x0 = point.x, y0 = point.y;
if( m_curPointID >= 2 )
{
dx = m_pPoint[m_curPointID-2].x - point.x;
dy = m_pPoint[m_curPointID-2].y - point.y;
}
else
{
dx = -1;
dy = -1;
}
//求算子的起始点
switch( dx )
{
case -1:
switch( dy )
{
case -1: offID = 0; break;//左上
case 0: offID = 7; break;//左中
case 1: offID = 6; break;//左下
}
break;
case 0:
switch( dy )
{
case -1: offID = 1; break;//上中
case 1: offID = 5; break;//下中
}
break;
case 1:
switch( dy )
{
case -1: offID = 2; break;//右上
case 0: offID = 3; break;//右中
case 1: offID = 4; break;//右下
}
}
offID++;
for( i = 0; i < 7; i++ )
{//按顺时针的方向找周边的点
if( offID >= 8 )
{
offID -= 8;
}
point.x = x0 + sxOff[offID];
point.y = y0 + syOff[offID];
offID++;
if( IsBoundary( point ) )
{
SetCell( point, m_cMark );
AddPoint( point );
return TRUE;
}
}
return FALSE;
}
BOOL CImg2Rgn::GetBoundaryPoint()
{
POINT point;
//使边界点记录器归零
m_curPointID = 0;
//找到第一个边界点
for( point.y = 0; point.y < m_bmHeight; point.y++ )
{
for( point.x = 0; point.x < m_bmWidth; point.x++ )
{
if( IsBoundary( point ) )
{
SetCell( point, m_cMark );
AddPoint( point );
goto firstOK;
}
}
}
//没有找到第一个点,返回假值
return FALSE;
firstOK:
while( FindNextPoint( point ) )
{}
if( PrevPoint( point ) )
{//回逆成功
goto firstOK;
}
//已逆到起点
return TRUE;
}
BOOL CImg2Rgn::PrevPoint( POINT & point )
{
long i, maxID = m_curPointID - 1;
POINT p;
point = m_pPoint[maxID];
for( i = 0; i < maxID; i++ )
{//不找最后一个点
p = m_pPoint[i];
if( labs(point.x-p.x) <= 1 && labs(point.y-p.y) <= 1 )
{//已找到与point相邻的点
break;
}
}
while( i > 1 )
{
point = m_pPoint[i];
//将回逆点加入记录器
AddPoint( point );
if( FindNextPoint( point ) )
{//已找到下一个边界点
return TRUE;
}
i--;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -