⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 img2rgn.cpp

📁 PPC开发的代码
💻 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 + -