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

📄 dibdoc.cpp

📁 segmentation sample good luck
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// DIBDoc.cpp : implementation file
//

#include "stdafx.h"
#include "Segment.h"
#include "DIBDoc.h"
#include "MonochromeBitmap.h"
#include "Line.h"
#include "HistogramDlg.h"
#include <vector>
#include <algorithm>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//-----------------------------------------------------------------
//
// CDIBMonochromeBitmap - this forms the base class of the monochrome
//						  bitmaps that extract their rasters from
//						  device independent bitmaps
//
//-----------------------------------------------------------------

class CDIBMonochromeBitmap: public CMonochromeBitmap
{
protected:
	CDIBDoc *m_pDoc;
public:
	CDIBMonochromeBitmap() { m_pDoc = NULL; }
	void SetDoc(CDIBDoc &doc) {
		m_pDoc = &doc;
	}

	virtual int Width() const {
		ASSERT(m_pDoc);
		return m_pDoc->GetBitmapInfo()->bmiHeader.biWidth;
	}

	virtual int Height() const {
		ASSERT(m_pDoc);
		return m_pDoc->GetBitmapInfo()->bmiHeader.biHeight;
	}
};

class CDIB1MonochromeBitmap: public CDIBMonochromeBitmap
{
public:
	const BYTE *GetRaster(int nLine);
};

const BYTE *CDIB1MonochromeBitmap::GetRaster(int nLine)
{
	ASSERT(m_pDoc);
	return m_pDoc->GetRaster(nLine);
}

//-----------------------------------------------------------------
//
// CDIB4MonochromeBitmap - this is a monochrome bitmap that extracts
//						   its rasters from a 16 color DIB. 
//
// NOTE: This class really hasn't been tested.
//-----------------------------------------------------------------

class CDIB4MonochromeBitmap: public CDIBMonochromeBitmap
{
public:
	CDIB4MonochromeBitmap();
	virtual ~CDIB4MonochromeBitmap();

	const BYTE *GetRaster(int nLine);
protected:
	BYTE *m_pRaster;
};

CDIB4MonochromeBitmap::CDIB4MonochromeBitmap()
{
	m_pRaster = NULL;
}

CDIB4MonochromeBitmap::~CDIB4MonochromeBitmap()
{
	delete [] m_pRaster;
}

const BYTE *CDIB4MonochromeBitmap::GetRaster(int nLine)
{
	if (m_pRaster == NULL) {
		ASSERT(m_pDoc);
		m_pRaster = new BYTE [m_pDoc->GetRasterWidthInBytes()];
	}


	const CByteArray &bThreshold = m_pDoc->GetThresholdTable();
	int nLimit = Width();

	const BYTE *pSrc = m_pDoc->GetRaster(nLine);
	BYTE *pDest = m_pRaster;
	for (int i = 0; i < nLimit; i += 8) {
		BYTE b = 0;
		if (bThreshold[*pSrc & 15]) {
			b = 0x80;
		}
		if (bThreshold[*pSrc++ >> 4]) {
			b += 0x40;
		}
		if (bThreshold[*pSrc & 15]) {
			b += 0x20;
		}
		if (bThreshold[*pSrc++ >> 4]) {
			b += 0x10;
		}
		if (bThreshold[*pSrc & 15]) {
			b += 0x08;
		}
		if (bThreshold[*pSrc++ >> 4]) {
			b += 0x04;
		}
		if (bThreshold[*pSrc & 15]) {
			b += 0x02;
		}
		if (bThreshold[*pSrc++ >> 4]) {
			b += 0x01;
		}
		*pDest++ = b;
	}
	return m_pRaster;
}

//-----------------------------------------------------------------
//
// CDIB8MonochromeBitmap - this one is the 256 color bitmap, the one
//					most frequently used to store pictures and gray
//					scales.
//
//-----------------------------------------------------------------

class CDIB8MonochromeBitmap: public CDIBMonochromeBitmap
{
public:
	virtual void GetBrightnessHistogram(vector<int> &a,vector<int> &vBrightness);
	virtual  ~CDIB8MonochromeBitmap();
	 CDIB8MonochromeBitmap();
	virtual const BYTE *GetRaster(int nLine);
	virtual void BuildBlobList();
protected:
	CByteArray m_bCachedRaster;
	BYTE * m_pCachedRaster;
};

//-----------------------------------------------------------------
//
// CDIB8MonochromeBitmap::CDIB8MonochromeBitmap
//
//-----------------------------------------------------------------

CDIB8MonochromeBitmap::CDIB8MonochromeBitmap()
{
}

//-----------------------------------------------------------------
//
// CDIB8MonochromeBitmap::~CDIB8MonochromeBitmap
//
//-----------------------------------------------------------------

CDIB8MonochromeBitmap::~CDIB8MonochromeBitmap()
{
}

//-----------------------------------------------------------------
//
// CDIB8MonochromeBitmap::GetBrightnessHistogram - This creates
//					a histogram whose elements indicate the relative
//				    number of pixels at each brightness. You can use
//					this to determine where to threshold.
//
// a - Histogram of # of pixels at each index. Indices are in order of
//     lowest to highest brightness.
// aBrightness - Each element of this array contains the index into
//				 the histogram of the indexed element.
//-----------------------------------------------------------------

void CDIB8MonochromeBitmap::GetBrightnessHistogram(vector<int> & a,vector<int> &aBrightness)
{
	// Here, we sample a bunch of random points to get an idea
	// of the brightness distribution.

	int nColors = m_pDoc->GetBitmapInfo()->bmiHeader.biClrUsed;
	if (nColors == 0) nColors = 256;
	RGBQUAD *pColors = m_pDoc->GetBitmapInfo()->bmiColors;

	a.resize(nColors);
	aBrightness.resize(nColors);
	for (int i = 0; i < nColors; i++) a[i] = 0;

	// We do a little trick here. We put the brightness in
	// bits 8+ of an int and the index in the low 7 bits.
	// We sort the array and we get the indices ordered by
	// brightness.

	vector<int> vBrightness;
	vBrightness.resize(nColors);
	for (i = 0; i < nColors; i++) {
		int nBrightness = pColors[i].rgbRed + pColors[i].rgbBlue + pColors[i].rgbGreen;
		vBrightness[i] = i + (nBrightness << 8);
	}

	sort(vBrightness.begin(), &vBrightness[vBrightness.size()]);

	// Now, we put the index in the top byte and put the ranking in the
	// bottom and sort. The "i"th index will contain the ranking of
	// the indexed color.

	for (i = 0; i < nColors; i++) {
		vBrightness[i] = ((vBrightness[i] & 0xFF) << 8) + i;
	}
	sort(vBrightness.begin(), &vBrightness[vBrightness.size()]);

	for (i = 0; i < nColors; i++) {
		vBrightness[i] &= 0xFF;
	}

	// Let's record the brightnesses in "aBrightness"

	for (i = 0; i < nColors; i++) {
		RGBQUAD *pClr = pColors + vBrightness[i];
		aBrightness[i] = pClr->rgbRed + pClr->rgbBlue + pClr->rgbGreen;
	}

	const int nWidth = Width();
	const int nHeight = Height();
	
	for (i = 0; i < 100; i++) {
		int nY = MulDiv(i,nHeight - 1,100);
		for (int j = 0; j < 100; j++) {
			int nX = MulDiv(j,nWidth - 1,100);
			BYTE bValue = m_pDoc->GetRaster(nY)[nX];
			ASSERT(vBrightness[bValue] >= 0);
			ASSERT(vBrightness[bValue] < nColors);
			a[vBrightness[bValue]]++;
		}
	}
}

//-----------------------------------------------------------------
//
// CDIB8MonochromeBitmap::GetRaster - return a pointer to a thresholded
//					monochrome raster (1 bit per pixel) for the indexed
//					line. NOTE: only one line is cached at a time, sorry.
//
// nLine - Y index of bitmap line to fetch.
//-----------------------------------------------------------------

const BYTE *CDIB8MonochromeBitmap::GetRaster(int nLine)
{
	if (m_bCachedRaster.GetSize() < Width()) {
		int nMonochromeWidth = m_pDoc->GetRasterWidthInBytes();
		m_bCachedRaster.SetSize(nMonochromeWidth);
		m_pCachedRaster = m_bCachedRaster.GetData();
		memset(m_pCachedRaster,0,nMonochromeWidth);
	}

	const CByteArray &m_bThreshold = m_pDoc->GetThresholdTable();

	BYTE *pDest = m_pCachedRaster;
	const BYTE *pSrc = m_pDoc->GetRaster(nLine);

	// We do 8 bit chunks here. We'll handle the end boundary
	// condition separately

	const int nWidth = Width() & ~ 7;
	BYTE b;
	for (int i = 0; i < nWidth; i += 8) {
		if (m_bThreshold[*pSrc++]) b = 0x80; else b = 0;
		if (m_bThreshold[*pSrc++]) b += 0x40;
		if (m_bThreshold[*pSrc++]) b += 0x20;
		if (m_bThreshold[*pSrc++]) b += 0x10;
		if (m_bThreshold[*pSrc++]) b += 0x08;
		if (m_bThreshold[*pSrc++]) b += 0x04;
		if (m_bThreshold[*pSrc++]) b += 0x02;
		if (m_bThreshold[*pSrc++]) b += 0x01;
		*pDest++ = b;
	}

	if (nWidth != Width()) {
		b = 0;
		BYTE bBit = 0x80;
		while(i++ < Width()) {
			if (m_bThreshold[*pSrc++]) b += bBit;
			bBit = bBit >> 1;
		}
		*pDest = b;
	}
	return m_pCachedRaster;
}

//-----------------------------------------------------------------
//
// CDIB8MonochromeBitmap::BuildBlobList - I've just duplicated the code
//									  pretty much for the x8 bitmap
//									  in order to make it go fast.
//
//-----------------------------------------------------------------

void CDIB8MonochromeBitmap::BuildBlobList()
{
	const CByteArray &bThresholdTable = m_pDoc->GetThresholdTable();

	CLineVectorIterator clviNew,clviEnd;
	AllocateLineBlock(clviNew,clviEnd);
	m_pBlob.reserve(eBlobsPerBlock);

	// Create two vectors of pointers to lines to hold the new line list
	// and the old line list. We initialize them to hold Width()/2 members.
	// This is the maximum possible number of lines.

	CLinePointerVector clpvRaster[2];
	clpvRaster[0].reserve(Width()/2);
	clpvRaster[1].reserve(Width()/2);

	int nOldLineIndex = 0;
	int nNewLineIndex = 1;

	// At the start, the old line list has no members.
	CLinePointerVectorIterator clpviOldEnd = clpvRaster[nOldLineIndex].begin();

	for (int nY = 0; nY < Height(); nY++) {

		CLinePointerVector &clpvOld = clpvRaster[nOldLineIndex];
		CLinePointerVector &clpvNew = clpvRaster[nNewLineIndex];
		nOldLineIndex = nOldLineIndex ^ 1;
		nNewLineIndex = nNewLineIndex ^ 1;

		CLinePointerVectorIterator clpviOld = clpvOld.begin();
		CLine *pLineOld;
		if (clpviOld == clpviOldEnd) {
			pLineOld = NULL;
		} else {
			pLineOld = *clpviOld++;
		}

		CLinePointerVectorIterator clpviNew = clpvNew.begin();

		// Get the raster to process and set up for the first byte
		const BYTE *pRaster = m_pDoc->GetRaster(nY);

		//  Set up the X extents.
		int nX = 0;
		const int nXEnd = Width();

		while(nX < nXEnd) {
			CBlob *pBlobOld;
			// Search for the start of a line.

			while(bThresholdTable[*pRaster++] == 0) {
				if (++nX == nXEnd) goto linedone;
			}

			// Start a line.

			if (clviNew == clviEnd) {
				// need more memory for lines.

				AllocateLineBlock(clviNew,clviEnd);
			}

			CLine &lineNew = *clviNew++;
			lineNew.m_nXStart = nX;
			lineNew.m_pNextLineSameBlob = 0;
			lineNew.m_nY = nY;
			
			// Put it on the new list.

			*clpviNew++ = &lineNew;

			// Find the extent of the line.

			nX++;
			while (nX != nXEnd) {
				if (bThresholdTable[*pRaster++] == 0) break;
				nX++;
			}

			lineNew.m_nXEnd = nX++;

			// Now finish all old lines wholly before our new line

			if (pLineOld) {
				while (pLineOld->m_nXEnd < lineNew.m_nXStart) {

					pBlobOld = pLineOld->m_pBlob;
					if (--(pBlobOld->m_nOpenLines) == 0) {
						AddBlob(pBlobOld);
					}
					if (clpviOld == clpviOldEnd) {
						pLineOld = NULL;
						break;
					} else {
						pLineOld = *clpviOld++;
					}
				}
			}

			// Do the first line that overlaps our new line

			if (pLineOld && pLineOld->m_nXStart <= lineNew.m_nXEnd) {
				pBlobOld = pLineOld->m_pBlob;
				lineNew.m_pBlob = pBlobOld;
				*(pBlobOld->m_ppLastLine) = &lineNew;
				pBlobOld->m_ppLastLine = &(lineNew.m_pNextLineSameBlob);

				// See if the new line ends the old line or vice-versa.

				if (pLineOld->m_nXEnd > lineNew.m_nXEnd) {
					// the old line extends past the new line.
					// the new line gives the old line's blob another open line.

					pBlobOld->m_nOpenLines++;
					continue;
				} else {
					// we close the old line and extend the blob at the
					// same time. We continue to close old lines.

					if (clpviOld == clpviOldEnd) {
						pLineOld = NULL;
					} else {
						pLineOld = *clpviOld++;
						while(pLineOld->m_nXEnd <= lineNew.m_nXEnd) {
							// End this line too. We have two cases:
							CBlob *pBlobOther;
							if ((pBlobOther = pLineOld->m_pBlob) == pBlobOld) {
								// the old line is part of the new line's blob.
								// This is just a loop.

								pBlobOld->m_nLoops++;
								pBlobOld->m_nOpenLines--;
							} else {
								// This is the merge case

								pBlobOld->Merge(pBlobOther);
								delete pBlobOther;
								pBlobOld->m_nOpenLines--;
							}
							if (clpviOld == clpviOldEnd) {
								pLineOld = NULL;
								break;
							} else {
								pLineOld = *clpviOld++;
							}
						}
						if (pLineOld && pLineOld->m_nXStart <= lineNew.m_nXEnd) {
							// This last old line overlaps and ends the new line.

							CBlob *pBlobOther = pLineOld->m_pBlob;
							if (pBlobOther == pBlobOld) {
								pBlobOld->m_nLoops++;
							} else {
								pBlobOld->Merge(pBlobOther);
								delete pBlobOther;
							}
						}
					}
				}
			} else {
				// This is the case where no line overlaps the new line.

⌨️ 快捷键说明

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