bitmapregion2d.hh

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

HH
1,442
字号
#ifndef __BITMAPREGION2D_H__#define __BITMAPREGION2D_H__// This file (C) 2004 Steven Boswell.  All rights reserved.// Released to the public under the GNU General Public License.// See the file COPYING for more information.// BitmapRegion2D tracks a 2-dimensional region of arbitrary points,// implemented with a bitmap.#include <assert.h>#include <string.h>#include "Region2D.hh"// Define this to compile in code to double-check and debug the region.#ifndef NDEBUG//	#define DEBUG_BITMAPREGION2D#endif // NDEBUG// Part of BitmapRegion2D<> breaks gcc 2.95.  An earlier arrangement of// the code also broke gcc 3.3, but that seems to be in remission now.#if defined(__GNUC__) && defined(__GNUC_MINOR__)#if __GNUC__ == 2 && __GNUC_MINOR__ < 96#define GCC_295_WORKAROUND#endif#endif// The 2-dimensional region class.  Parameterized by the numeric type// to use for point indices, and the numeric type to use to count the// contained number of points.template <class INDEX, class SIZE>class BitmapRegion2D : public Region2D<INDEX,SIZE>{private:	typedef Region2D<INDEX,SIZE> BaseClass;		// Keep track of who our base class is.public:	typedef typename BaseClass::Extent Extent;		// (Wouldn't we automatically have access to Extent because		// we're a subclass of Region2D<>?  Why is this needed?)	BitmapRegion2D();		// Default constructor.  Must be followed by Init().	BitmapRegion2D (Status_t &a_reStatus, INDEX a_tnWidth,			INDEX a_tnHeight);		// Initializing constructor.  Creates an empty region with the		// given extent.	BitmapRegion2D (Status_t &a_reStatus,			const BitmapRegion2D<INDEX,SIZE> &a_rOther);		// Copy constructor.		void Init (Status_t &a_reStatus, INDEX a_tnWidth, INDEX a_tnHeight);		// Initializer.  Must be called on default-constructed regions.	template <class OTHER>	void Assign (Status_t &a_reStatus, const OTHER &a_rOther);		// Make the current region a copy of the other region.	void Assign (Status_t &a_reStatus,			const BitmapRegion2D<INDEX,SIZE> &a_rOther);		// Make the current region a copy of the other region.	virtual ~BitmapRegion2D();		// Destructor.	SIZE NumberOfPoints (void) const;		// Return the total number of points contained by the region.	void Clear (void);		// Clear the region, emptying it of all extents.	void Union (INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd);		// Add the given horizontal extent to the region.  Note that		// a_tnXEnd is technically one past the end of the extent.	void Union (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart,			INDEX a_tnXEnd);		// Add the given horizontal extent to the region.  Note that		// a_tnXEnd is technically one past the end of the extent.		// (This version is for interface compatibility with the		// set-based region.)	void Union (Status_t &a_reStatus,			const BitmapRegion2D<INDEX,SIZE> &a_rOther);		// Make the current region represent the union between itself		// and the other given region.	void Merge (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart,			INDEX a_tnXEnd);		// Merge this extent into the current region.		// The new extent can't intersect the region in any way.	void Merge (BitmapRegion2D<INDEX,SIZE> &a_rOther);		// Merge the other region into ourselves, emptying the other		// region.  Like Union(), but doesn't allocate any new memory.		// Also, the other region can't intersect us in any way, and		// both regions must use the same allocator.	void Move (BitmapRegion2D<INDEX,SIZE> &a_rOther);		// Move the contents of the other region into the current		// region.	bool CanMove (const BitmapRegion2D<INDEX,SIZE> &a_rOther) const;		// Returns true if the other region's contents can be moved		// into the current region.	bool CanMove (const Region2D<INDEX,SIZE> &a_rOther) const			{ return false; }	void Move (Region2D<INDEX,SIZE> &a_rOther) { assert (false); }		// (We can move between BitmapRegion2D<>s, but not any arbitrary		// Region2D<> subclass.)	void Intersection (Status_t &a_reStatus,			const BitmapRegion2D<INDEX,SIZE> &a_rOther);		// Make the current region represent the intersection between		// itself and the other given region.	void Subtract (Status_t &a_reStatus, INDEX a_tnY, INDEX a_tnXStart,			INDEX a_tnXEnd);		// Subtract the given horizontal extent from the region.  Note		// that a_tnXEnd is technically one past the end of the extent.	template <class OTHER>	void Subtract (Status_t &a_reStatus, const OTHER &a_rOther);		// Subtract the other region from the current region, i.e.		// remove from the current region any areas that exist in the		// other region.	void Subtract (Status_t &a_reStatus,			const BitmapRegion2D<INDEX,SIZE> &a_rOther);		// Subtract the other region from the current region, i.e.		// remove from the current region any areas that exist in the		// other region.		bool DoesContainPoint (INDEX a_tnY, INDEX a_tnX) const;		// Returns true if the region contains the given point.	// A structure that implements flood-fills using BitmapRegion2D<> to	// do the work.  (The definition of this class follows the	// definition of Region<>.)	class FloodFillControl;	template <class CONTROL>	void FloodFill (Status_t &a_reStatus, CONTROL &a_rControl,			bool a_bVerify);		// Flood-fill the current region.  All points bordering the		// current region are tested for inclusion; if a_bVerify is		// true, all existing region points are tested.	template <class OTHER>	void MakeBorder (Status_t &a_reStatus, const OTHER &a_rOther);		// Make the current region represent the border of the other		// region, i.e. every pixel that's adjacent to a pixel that's		// in the region, but isn't already in the region.	// An iterator for the bitmap-oriented region.	class ConstIterator	{	protected:		friend class BitmapRegion2D<INDEX,SIZE>;			// Let the region implement our operations.		const BitmapRegion2D<INDEX,SIZE> *m_pThis;			// The region that we're iterating through.		Extent m_oExtent;			// The extent we currently represent.	public:		ConstIterator() { m_pThis = NULL; }		ConstIterator (const ConstIterator &a_rOther)			: m_pThis (a_rOther.m_pThis),			m_oExtent (a_rOther.m_oExtent) {}		const Extent &operator*() const { return m_oExtent; }		ConstIterator& operator++();		ConstIterator operator++(int) { ConstIterator oTmp = *this;			++*this; return oTmp; }		ConstIterator& operator--();		ConstIterator operator--(int) { ConstIterator oTmp = *this;			--*this; return oTmp; }		bool operator== (const ConstIterator &a_rOther) const			{ return (m_pThis == a_rOther.m_pThis				&& m_oExtent == a_rOther.m_oExtent) ? true : false; }		bool operator!= (const ConstIterator &a_rOther) const			{ return (m_pThis != a_rOther.m_pThis				|| m_oExtent != a_rOther.m_oExtent) ? true : false; }	};	ConstIterator Begin (void) const;	ConstIterator End (void) const;		// Allow our client to iterate through the extents & get their		// values.	void UnionSurroundingExtents (Status_t &a_reStatus,			INDEX a_tnY, INDEX a_tnXStart, INDEX a_tnXEnd);		// Add all extents surrounding the given extent.		// Used by FloodFill() and MakeBorder().		void IteratorForward (ConstIterator &a_ritHere) const;		// Move one of our iterators forward.		void IteratorBackward (ConstIterator &a_ritHere) const;		// Move one of our iterators backward.		static int FindFirstSetBit (unsigned int a_nWord, int a_nSkip);	static int FindFirstClearBit (unsigned int a_nWord, int a_nSkip);	static int FindLastSetBit (unsigned int a_nWord, int a_nSkip);	static int FindLastClearBit (unsigned int a_nWord, int a_nSkip);		// Find the index of the first/last set/clear bit, skipping		// the first/last a_nSkip bits.		// Used to implement iterator increment/decrement.private:	INDEX m_tnWidth, m_tnHeight;		// The extent of the bitmap.		unsigned int *m_pnPoints;		// The bitmap representing the region.		SIZE m_tnBitmapInts;		// The number of integers in our bitmap.		static int8_t m_anSetBitsPerByte[256];		// The number of set bits in every possible byte value.		static bool m_bSetBitsPerByte;		// Whether the set-bits-per-byte table has been set up.#ifndef NDEBUG// Count the number of region objects in existence.private:	static uint32_t sm_ulInstances;public:	static uint32_t GetInstances (void) { return sm_ulInstances; }	#endif // NDEBUG};// A structure that implements flood-fills using BitmapRegion2D<> to// do the work.template <class INDEX, class SIZE>class BitmapRegion2D<INDEX,SIZE>::FloodFillControl#ifndef GCC_295_WORKAROUND	: public Region2D<INDEX,SIZE>::		template FloodFillControl<BitmapRegion2D<INDEX,SIZE> >#endif // ! GCC_295_WORKAROUND{public:#ifdef GCC_295_WORKAROUND	// (Although these fields are public, they should be considered	// opaque to the client.)	BitmapRegion2D<INDEX,SIZE> m_oToDo;		// Extents that still need to be be tested.	BitmapRegion2D<INDEX,SIZE> m_oAlreadyDone;		// Extents that have been tested.	BitmapRegion2D<INDEX,SIZE> m_oNextToDo;		// Extents contiguous with those that have just been added		// to the flood-filled area.	typedef typename BitmapRegion2D<INDEX,SIZE>::ConstIterator		ConstIterator;	typedef typename BitmapRegion2D<INDEX,SIZE>::Extent Extent;		// The iterator/extent type for running through the above		// regions.#endif // GCC_295_WORKAROUND	FloodFillControl();		// Default constructor.  Must be followed by a call to Init().		FloodFillControl (Status_t &a_reStatus, INDEX a_tnWidth,			INDEX a_tnHeight);		// Initializing constructor.		void Init (Status_t &a_reStatus, INDEX a_tnWidth, INDEX a_tnHeight);		// Initializer.  Must be called on default-constructed objects.#ifdef GCC_295_WORKAROUND	// Methods to be redefined by clients implementing specific	// flood-fills.	bool ShouldUseExtent (Extent &a_rExtent) { return true; }		// Return true if the flood-fill should examine the given		// extent.  Clients should redefine this to define their own		// criteria for when extents should be used, and to modify the		// extent as needed (e.g. to clip the extent to a bounding box).		bool IsPointInRegion (INDEX a_tnX, INDEX a_tnY) { return false; }		// Returns true if the given point should be included in the		// flood-fill.  Clients must redefine this to explain their		// flood-fill criteria.#endif // GCC_295_WORKAROUND};// Default constructor.  Must be followed by Init().template <class INDEX, class SIZE>BitmapRegion2D<INDEX,SIZE>::BitmapRegion2D(){#ifndef NDEBUG	// One more instance.	++sm_ulInstances;#endif // NDEBUG	// No bitmap yet.	m_tnWidth = m_tnHeight = INDEX (0);	m_pnPoints = NULL;	m_tnBitmapInts = SIZE (0);}// Initializing constructor.  Creates an empty region.template <class INDEX, class SIZE>BitmapRegion2D<INDEX,SIZE>::BitmapRegion2D (Status_t &a_reStatus,	INDEX a_tnWidth, INDEX a_tnHeight){#ifndef NDEBUG	// One more instance.	++sm_ulInstances;#endif // NDEBUG	// No bitmap yet.	m_tnWidth = m_tnHeight = INDEX (0);	m_pnPoints = NULL;	m_tnBitmapInts = SIZE (0);	// Save the width & height.	m_tnWidth = a_tnWidth;	m_tnHeight = a_tnHeight;	// Allocate the bitmap.	m_tnBitmapInts = (SIZE (m_tnWidth) * SIZE (m_tnHeight))		/ (g_knBitsPerByte * sizeof (unsigned int)) + 1;	m_pnPoints = new unsigned int[m_tnBitmapInts];	if (m_pnPoints == NULL)	{		a_reStatus = g_kOutOfMemory;		return;	}	// No points yet.	for (SIZE i = 0; i < m_tnBitmapInts; ++i)		m_pnPoints[i] = 0U;}// Copy constructor.template <class INDEX, class SIZE>BitmapRegion2D<INDEX,SIZE>::BitmapRegion2D (Status_t &a_reStatus,	const BitmapRegion2D<INDEX,SIZE> &a_rOther){#ifndef NDEBUG	// One more instance.	++sm_ulInstances;#endif // NDEBUG	// No bitmap yet.	m_tnWidth = m_tnHeight = INDEX (0);	m_pnPoints = NULL;	m_tnBitmapInts = SIZE (0);	// Copy the width & height.	m_tnWidth = a_rOther.m_tnWidth;	m_tnHeight = a_rOther.m_tnHeight;	// Allocate the bitmap.	m_tnBitmapInts = (SIZE (m_tnWidth) * SIZE (m_tnHeight))		/ (g_knBitsPerByte * sizeof (unsigned int)) + 1;	m_pnPoints = new unsigned int[m_tnBitmapInts];	if (m_pnPoints == NULL)	{		a_reStatus = g_kOutOfMemory;		return;	}	// Copy the bitmap.	memcpy (m_pnPoints, a_rOther.m_pnPoints,		m_tnBitmapInts * sizeof (unsigned int));}// Initializer.  Must be called on default-constructed regions.template <class INDEX, class SIZE>voidBitmapRegion2D<INDEX,SIZE>::Init (Status_t &a_reStatus, INDEX a_tnWidth,	INDEX a_tnHeight){	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// Save the width & height.	m_tnWidth = a_tnWidth;	m_tnHeight = a_tnHeight;	// Allocate the bitmap.	m_tnBitmapInts = (SIZE (m_tnWidth) * SIZE (m_tnHeight))		/ (g_knBitsPerByte * sizeof (unsigned int)) + 1;	m_pnPoints = new unsigned int[m_tnBitmapInts];	if (m_pnPoints == NULL)	{		a_reStatus = g_kOutOfMemory;		return;	}	// No points yet.	for (SIZE i = 0; i < m_tnBitmapInts; ++i)		m_pnPoints[i] = 0U;}// Make the current region a copy of the other region.template <class INDEX, class SIZE>template <class OTHER>voidBitmapRegion2D<INDEX,SIZE>::Assign (Status_t &a_reStatus,	const OTHER &a_rOther){	typename OTHER::ConstIterator itExtent;		// Used to loop through extents to copy.	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// Clear our contents, in preparation for being assigned.	Clear();	// Loop through the other region's extents, clip them to the current	// region's boundaries, and add them to the current region.	for (itExtent = a_rOther.Begin();		 itExtent != a_rOther.End();		 ++itExtent)	{		// Get the extent.		typename OTHER::Extent oExtent = *itExtent;		// Add it to the current region.		Union (a_reStatus, oExtent.m_tnY, oExtent.m_tnXStart,			oExtent.m_tnXEnd);		assert (a_reStatus == g_kNoError);	// (should always succeed.)		if (a_reStatus != g_kNoError)			return;	}}// Make the current region a copy of the other region.template <class INDEX, class SIZE>voidBitmapRegion2D<INDEX,SIZE>::Assign (Status_t &a_reStatus,	const BitmapRegion2D<INDEX,SIZE> &a_rOther){	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);	// If the region is not the exact same size, use the more	// generic version.	if (m_tnWidth != a_rOther.m_tnWidth		|| m_tnHeight != a_rOther.m_tnHeight)	{		Assign<BitmapRegion2D<INDEX,SIZE> > (a_reStatus, *this);		return;	}	// Make sure the region is the exact same size.	assert (m_tnWidth == a_rOther.m_tnWidth

⌨️ 快捷键说明

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