region2d.hh

来自「Motion JPEG编解码器源代码」· HH 代码 · 共 1,013 行 · 第 1/2 页

HH
1,013
字号
		if (a_reStatus != g_kNoError)			return;	}}// Make the current region represent the union between itself// and the other given region.template <class INDEX, class SIZE>template <class REGION, class REGION_O, class REGION_TEMP>voidRegion2D<INDEX,SIZE>::UnionDebug (Status_t &a_reStatus,	REGION_O &a_rOther, REGION_TEMP &a_rTemp){	typename REGION::ConstIterator itHere;	typename REGION_O::ConstIterator itHereO;	typename REGION_TEMP::ConstIterator itHereT;	INDEX tnX;		// Used to loop through points.	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// Calculate the union.	a_rTemp.Assign (a_reStatus, *this);	if (a_reStatus != g_kNoError)		return;	a_rTemp.Union (a_reStatus, a_rOther);	if (a_reStatus != g_kNoError)		return;		// Loop through every point in the result, make sure it's in	// one of the two input regions.	for (itHereT = a_rTemp.Begin(); itHereT != a_rTemp.End(); ++itHereT)	{		const Extent &rHere = *itHereT;		for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX)		{			if (!a_rOther.DoesContainPoint (rHere.m_tnY, tnX)			&& !this->DoesContainPoint (rHere.m_tnY, tnX))				goto error;		}	}	// Loop through every point in the first input region, make sure	// it's in the result.	for (itHere = this->Begin(); itHere != this->End(); ++itHere)	{		const Extent &rHere = *itHere;		for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX)		{			if (!a_rTemp.DoesContainPoint (rHere.m_tnY, tnX))				goto error;		}	}	// Loop through every point in the second input region, make sure	// it's in the result.	for (itHereO = a_rOther.Begin();		 itHereO != a_rOther.End();		 ++itHereO)	{		const Extent &rHere = *itHereO;		for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX)		{			if (!a_rTemp.DoesContainPoint (rHere.m_tnY, tnX))				goto error;		}	}	// The operation succeeded.  Commit it.	Assign (a_reStatus, a_rTemp);	if (a_reStatus != g_kNoError)		return;	// All done.	return;error:	// Handle deviations.	fprintf (stderr, "Region2D::Union() failed\n");	fprintf (stderr, "First input region:\n");	PrintRegion (*this);	fprintf (stderr, "Second input region:\n");	PrintRegion (a_rOther);	fprintf (stderr, "Result:\n");	PrintRegion (a_rTemp);	assert (false);}// Subtract the other region from the current region, i.e.// remove from the current region any areas that exist in the// other region.template <class INDEX, class SIZE>template <class REGION>voidRegion2D<INDEX,SIZE>::Subtract (Status_t &a_reStatus,	const REGION &a_rOther){	typename REGION::ConstIterator itHere;		// Where we are in the other region's extents.	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// Run through the extents in the other region, subtract them from	// the current region.	for (itHere = a_rOther.Begin();		 itHere != a_rOther.End();		 ++itHere)	{		// Subtract this extent from the current region.		Subtract (a_reStatus, (*itHere).m_tnY, (*itHere).m_tnXStart,			(*itHere).m_tnXEnd, a_rOther, itHere.itNext);		if (a_reStatus != g_kNoError)			return;	}}// Subtract the other region from the current region, i.e.// remove from the current region any areas that exist in the// other region.template <class INDEX, class SIZE>template <class REGION, class REGION_O, class REGION_TEMP>voidRegion2D<INDEX,SIZE>::SubtractDebug (Status_t &a_reStatus,	REGION_O &a_rOther, REGION_TEMP &a_rTemp){	typename REGION::ConstIterator itHere;	typename REGION_O::ConstIterator itHereO;	typename REGION_TEMP::ConstIterator itHereT;	INDEX tnX;		// Used to loop through points.	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// Calculate the difference.	a_rTemp.Assign (a_reStatus, *this);	if (a_reStatus != g_kNoError)		return;	a_rTemp.Subtract (a_reStatus, a_rOther);	if (a_reStatus != g_kNoError)		return;		// Loop through every point in the result, make sure it's in	// the first input region but not the second.	for (itHereT = a_rTemp.Begin(); itHereT != a_rTemp.End(); ++itHereT)	{		const Extent &rHere = *itHereT;		for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX)		{			if (!(this->DoesContainPoint (rHere.m_tnY, tnX)			&& !a_rOther.DoesContainPoint (rHere.m_tnY, tnX)))				goto error;		}	}	// Loop through every point in the first input region, and if it's	// not in the second input region, make sure it's in the result.	for (itHere = this->Begin(); itHere != this->End(); ++itHere)	{		const Extent &rHere = *itHere;		for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX)		{			if (!a_rOther.DoesContainPoint (rHere.m_tnY, tnX))			{				if (!a_rTemp.DoesContainPoint (rHere.m_tnY, tnX))					goto error;			}		}	}	// Loop through every point in the second input region, make sure	// it's not in the result.	for (itHereO = a_rOther.Begin();		 itHereO != a_rOther.End();		 ++itHereO)	{		const Extent &rHere = *itHere;		for (tnX = rHere.m_tnXStart; tnX < rHere.m_tnXEnd; ++tnX)		{			if (a_rTemp.DoesContainPoint (rHere.m_tnY, tnX))				goto error;		}	}	// The operation succeeded.  Commit it.	Assign (a_reStatus, a_rTemp);	if (a_reStatus != g_kNoError)		return;	// All done.	return;error:	// Handle deviations.	fprintf (stderr, "Region2D::Subtract() failed\n");	fprintf (stderr, "First input region:\n");	PrintRegion (*this);	fprintf (stderr, "Second input region:\n");	PrintRegion (a_rOther);	fprintf (stderr, "Result:\n");	PrintRegion (a_rTemp);	assert (false);}// Flood-fill the current region.template <class INDEX, class SIZE>template <class CONTROL>voidRegion2D<INDEX,SIZE>::FloodFill (Status_t &a_reStatus,	CONTROL &a_rControl, bool a_bVerify){	typename CONTROL::ConstIterator itExtent;		// An extent we're examining.	Extent oFoundExtent;		// An extent we found to be part of the region.	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// How we set up depends on whether we're to verify all existing	// region extents.	if (a_bVerify)	{		// The to-do-list becomes the current region, and we empty		// out the current region too.		a_rControl.m_oAlreadyDone.Clear();		if (a_rControl.m_oToDo.CanMove (*this))		{			// Grab the extents right out of the current region.			a_rControl.m_oToDo.Clear();			a_rControl.m_oToDo.Move (*this);		}		else		{			// Copy the extents from the current region, then empty it.			a_rControl.m_oToDo.Assign (a_reStatus, *this);			if (a_reStatus != g_kNoError)				return;			Region2D<INDEX,SIZE>::Clear();		}	}	else	{		// The already-done list starts with the region, i.e. every		// extent already known to be in the region can avoid getting		// tested.		a_rControl.m_oAlreadyDone.Assign (a_reStatus, *this);		if (a_reStatus != g_kNoError)			return;			// Start the to-do list with a border around all the extents in		// the region.		a_rControl.m_oToDo.MakeBorder (a_reStatus, *this);		if (a_reStatus != g_kNoError)			return;	}	// Now pull each extent out of the to-do list.  Determine which	// sub-extents are part of the region.  Add those found extents	// to the region.  Then add all extent surrounding the found extents	// to the to-do-next list.	itExtent = a_rControl.m_oToDo.Begin();	while (itExtent != a_rControl.m_oToDo.End())	{		bool bStartedExtent;			// true if we've started finding an extent.		INDEX tnX;			// Where we're looking for extents.		// Get the extent, converting the type if necessary.		Extent oExtent;		oExtent.m_tnY = (*itExtent).m_tnY;		oExtent.m_tnXStart = (*itExtent).m_tnXStart;		oExtent.m_tnXEnd = (*itExtent).m_tnXEnd;		// We're about to check this extent.  Put it in the		// already-checked list now.		a_rControl.m_oAlreadyDone.Union (a_reStatus, oExtent.m_tnY,			oExtent.m_tnXStart, oExtent.m_tnXEnd);		if (a_reStatus != g_kNoError)			return;			// If this extent shouldn't be considered, skip it.		if (!a_rControl.ShouldUseExtent (oExtent))			goto nextExtent;		// Make sure our client left us with a valid extent.		assert (oExtent.m_tnXStart < oExtent.m_tnXEnd);				// Run through the pixels described by this extent, see if		// they can be added to the region, and remember where to		// search next.		oFoundExtent.m_tnY = oExtent.m_tnY;		bStartedExtent = false;		for (tnX = oExtent.m_tnXStart; tnX <= oExtent.m_tnXEnd; ++tnX)		{			// Is this point in the region?			if (tnX < oExtent.m_tnXEnd			&& a_rControl.IsPointInRegion (tnX, oExtent.m_tnY))			{				// This point is in the region.  Start a new extent				// if we didn't have one already, and add the point				// to it.				if (!bStartedExtent)				{					oFoundExtent.m_tnXStart = tnX;					bStartedExtent = true;				}				oFoundExtent.m_tnXEnd = tnX + 1;			}			// This point is not in the region.  Any extent we're			// building is done.			else if (bStartedExtent)			{				// Add this extent to the region.				Union (a_reStatus, oFoundExtent.m_tnY,					oFoundExtent.m_tnXStart, oFoundExtent.m_tnXEnd);				if (a_reStatus != g_kNoError)					return;				// Now add all surrounding extents to the to-do-next				// list.				a_rControl.m_oNextToDo.UnionSurroundingExtents					(a_reStatus, oFoundExtent.m_tnY,						oFoundExtent.m_tnXStart, oFoundExtent.m_tnXEnd);				if (a_reStatus != g_kNoError)					return;				// Look for another extent.				bStartedExtent = false;			}		}nextExtent:		// Move to the next extent.		++itExtent;		// If the to-do list needs to be replenished, do so.		if (itExtent == a_rControl.m_oToDo.End())		{			// Replenish the to-do list.			a_rControl.m_oNextToDo.Subtract (a_reStatus,				a_rControl.m_oAlreadyDone);			if (a_reStatus != g_kNoError)				return;			a_rControl.m_oToDo.Clear();			a_rControl.m_oToDo.Merge (a_rControl.m_oNextToDo);						// Start over at the beginning.			itExtent = a_rControl.m_oToDo.Begin();		}	}}// Make the current region represent the border of the other// region, i.e. every pixel that borders the region but isn't// already in the region.template <class INDEX, class SIZE>template <class REGION>voidRegion2D<INDEX,SIZE>::MakeBorder (Status_t &a_reStatus,	const REGION &a_rOther){	typename REGION::ConstIterator itExtent;		// Used to loop through the other region's extents.	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// Start with an empty region.	Region2D<INDEX,SIZE>::Clear();	// For every extent in the other region, add every surrounding	// extent.  That creates a region that looks like the other region,	// but also contains the border we're after.	for (itExtent = a_rOther.Begin();		 itExtent != a_rOther.End();		 ++itExtent)	{		UnionSurroundingExtents (a_reStatus, (*itExtent).m_tnY,			(*itExtent).m_tnXStart, (*itExtent).m_tnXEnd);		if (a_reStatus != g_kNoError)			return;	}	// Finally, subtract the other region.  That punches a hole in us,	// and creates the border region we're after.	Subtract (a_reStatus, a_rOther);	if (a_reStatus != g_kNoError)		return;}// Add all extents surrounding the given extent.  Used by FloodFill().template <class INDEX, class SIZE>voidRegion2D<INDEX,SIZE>::UnionSurroundingExtents (Status_t &a_reStatus,	INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd){	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// Add the extent above this one.	Union (a_reStatus, a_tnY - 1, a_tnXStart, a_tnXEnd);	if (a_reStatus != g_kNoError)		return;	// Add the extent in the middle.	Union (a_reStatus, a_tnY, a_tnXStart - 1, a_tnXEnd + 1);	if (a_reStatus != g_kNoError)		return;	// Add the extent below this one.	Union (a_reStatus, a_tnY + 1, a_tnXStart, a_tnXEnd);	if (a_reStatus != g_kNoError)		return;}// Less-than operator.template <class INDEX, class SIZE>inline boolRegion2D<INDEX,SIZE>::Extent::operator <	(const Region2D<INDEX,SIZE>::Extent &a_rOther) const{	// Compare on y, then x-start.	if (m_tnY < a_rOther.m_tnY)		return true;	if (m_tnY > a_rOther.m_tnY)		return false;	if (m_tnXStart < a_rOther.m_tnXStart)		return true;	// if (m_tnXStart >= a_rOther.m_tnXStart)		return false;}// Default constructor.  Must be followed by a call to Init().template <class INDEX, class SIZE>template <class REGION>Region2D<INDEX,SIZE>::FloodFillControl<REGION>::FloodFillControl(){	// Nothing to do.}// Initializing constructor.template <class INDEX, class SIZE>template <class REGION>Region2D<INDEX,SIZE>::FloodFillControl<REGION>::FloodFillControl	(Status_t &a_reStatus){	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// Initialize ourselves.	Init (a_reStatus);	if (a_reStatus != g_kNoError)		return;}// Initializer.  Must be called on default-constructed objects.template <class INDEX, class SIZE>template <class REGION>voidRegion2D<INDEX,SIZE>::FloodFillControl<REGION>::Init	(Status_t &a_reStatus){	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// Initialize our helper regions.	m_oToDo.Init (a_reStatus);	if (a_reStatus != g_kNoError)		return;	m_oAlreadyDone.Init (a_reStatus);	if (a_reStatus != g_kNoError)		return;	m_oNextToDo.Init (a_reStatus);	if (a_reStatus != g_kNoError)		return;}#endif // __REGION2D_H__

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?