/******************************************************************************
Copyright (C) 2005 Matteo Lucarelli
                   Angelo Moro

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
******************************************************************************/

#include "cvBlobFinder.h"

cvBlobFinder::cvBlobFinder()
{
	m_Blob=NULL;
	m_BlobCount=0;
	m_Mask=NULL;
}

cvBlobFinder::~cvBlobFinder()
{
	Reset();
}

long cvBlobFinder::FindBlobs(IplImage* img,uchar threshold,double minarea,int mode,bool UseMask)
{
	CvPoint seed;
	CvConnectedComp lastblob;
	uchar val;
	int flags;
	CvScalar new_val,lo_diff,up_diff;
	
	Reset();
	
	if (UseMask){
		m_Mask=cvCreateImage(cvSize(img->width+2,img->height+2),IPL_DEPTH_8U,1);
		cvZero(m_Mask);
		flags=(255<<8)+CV_FLOODFILL_MASK_ONLY+CV_FLOODFILL_FIXED_RANGE+4;
	}
	else flags=CV_FLOODFILL_FIXED_RANGE+4;
	
	for ( seed.x=0 ; seed.x < img->width ; seed.x++ )
	{
		for ( seed.y=0 ; seed.y < img->height ; seed.y++ )
		{
			if (UseMask&&(*(cvPtr2D(m_Mask,seed.y+1,seed.x+1))!=0)) continue;
				
			val=*(cvPtr2D(img,seed.y,seed.x));
			
			if (((mode==1)&&(val>=threshold))||
			    ((mode==0)&&(val==threshold))||
			    ((mode==-1)&&(val<=threshold)))
			{
				if (mode==1) {
					new_val=cvScalarAll(0);
					lo_diff=cvScalarAll(val-threshold);
					up_diff=cvScalarAll(255-val);
				}else if (mode==0) {
					new_val=cvScalarAll(!threshold);
					lo_diff=cvScalarAll(0);
					up_diff=cvScalarAll(0);	
				}else if (mode==-1) {
					new_val=cvScalarAll(255);
					lo_diff=cvScalarAll(val);
					up_diff=cvScalarAll(threshold-val);	
				}

				cvFloodFill(	img,
						seed,
			 			new_val,
						lo_diff,
						up_diff,
						&lastblob,
						flags,
						m_Mask);
				if (lastblob.area>=minarea){
					m_Blob=(CvBlob*)realloc((void*)m_Blob,sizeof(CvBlob)*(m_BlobCount+1));
					m_Blob[m_BlobCount].x=lastblob.rect.x;
					m_Blob[m_BlobCount].y=lastblob.rect.y;
					m_Blob[m_BlobCount].width=lastblob.rect.width;
					m_Blob[m_BlobCount].height=lastblob.rect.height;
					m_Blob[m_BlobCount].area=lastblob.area;
					m_BlobCount++;
				}	
			}
		}
	}
	
	return m_BlobCount;	
}

CvBlob* cvBlobFinder::GetBlobs()
{
	return m_Blob;	
}

IplImage* cvBlobFinder::GetMask()
{
	return m_Mask;	
}

long cvBlobFinder::GetBlobCount()
{
	return m_BlobCount;
}

void cvBlobFinder::Reset()
{
	if (m_Mask!=NULL) cvReleaseImage(&m_Mask);
	m_Mask=NULL;
	if (m_Blob!=NULL) free(m_Blob);
	m_Blob=NULL;
	m_BlobCount=0;
}