www.pudn.com > Gesture[20040824].rar > Image.cpp


// Image.cpp: implementation of the CImage class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "Image.h" 
 
#include  
#include  
using namespace std; 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CImage::CImage() 
{ 
    Clear(); 
} 
 
void CImage::Clear() 
{  
    memset( &m_img, 0, sizeof(m_img)); 
 
    m_memDC = 0;  
    m_old = 0; 
} 
 
void CImage::Destroy() 
{ 
    if( m_memDC ) 
    { 
        DeleteObject( SelectObject( m_memDC, m_old )); 
        DeleteDC( m_memDC ); 
    } 
    Clear(); 
} 
 
CImage::~CImage() 
{ 
    Destroy(); 
 
} 
 
void  FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp ) 
{ 
    ASSERT( bmi && width > 0 && height > 0 && 
            (bpp == 8 || bpp == 24 || bpp == 32) ); 
 
    BITMAPINFOHEADER* bmih = &(bmi->bmiHeader); 
 
    memset( bmih, 0, sizeof(*bmih)); 
    bmih->biSize   = sizeof(BITMAPINFOHEADER);  
    bmih->biWidth  = width; 
    bmih->biHeight = -abs(height); 
    bmih->biPlanes = 1;  
    bmih->biBitCount = bpp; 
    bmih->biCompression = BI_RGB; 
 
    if( bpp == 8 ) 
    { 
        RGBQUAD* palette = bmi->bmiColors; 
        int i; 
        for( i = 0; i < 256; i++ ) 
        { 
            palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i; 
            palette[i].rgbReserved = 0; 
        } 
    } 
} 
 
bool  CImage::Create( int w, int h, int bpp ) 
{ 
    char buffer[sizeof(BITMAPINFOHEADER) + 1024]; 
    BITMAPINFO* bmi = (BITMAPINFO*)buffer; 
    void* data = 0; 
    int new_step = (w*(bpp/8) + 3) & -4; 
     
    ASSERT( bpp == 8 || bpp == 24 || bpp == 32 ); 
	bool AlphaChannel = bpp==32; 
 
    if( (m_img.depth & 255) == bpp &&  
        m_img.width == w && m_img.height == h ) 
    { 
        return true; 
    } 
 
    Destroy(); 
     
    m_memDC = CreateCompatibleDC(0); 
    FillBitmapInfo( bmi, w, h, bpp ); 
 
    HBITMAP hbmp = CreateDIBSection( m_memDC, bmi, DIB_RGB_COLORS, &data, 0, 0 ); 
    if( !hbmp ) 
    { 
        DeleteDC( m_memDC ); 
        m_memDC = 0; 
    } 
    else 
    { 
        BITMAP bmp; 
        m_old = SelectObject( m_memDC, hbmp ); 
 
        GetObject( hbmp, sizeof(bmp), &bmp ); 
 
        /* prepare IPL header */ 
        memset( &m_img, 0, sizeof(m_img)); 
        m_img.nSize = sizeof( m_img ); 
        m_img.nChannels = bpp/8; 
        m_img.depth = IPL_DEPTH_8U; 
        strncpy( m_img.colorModel, bpp > 8 ? "RGB\0" : "GRAY", 4 ); 
        strncpy( m_img.channelSeq, bpp > 8 ? "BGR\0" : "GRAY", 4 ); 
        m_img.align = 8;///////////////////////////////////////////////// 
        m_img.width = w; 
        m_img.height = abs(h); 
        m_img.roi  = 0; 
        m_img.widthStep = (w*(bpp/8) + 3)& -4; 
        m_img.imageSize = m_img.widthStep*m_img.height; 
        m_img.imageData = m_img.imageDataOrigin = (char*)bmp.bmBits; 
 
        iplSetBorderMode( &m_img, IPL_BORDER_REPLICATE, IPL_SIDE_ALL, 0 );  
    } 
    return m_old != 0; 
} 
 
void  CImage::CopyOf( CImage& image, int desired_color ) 
{ 
    IplImage* img = image.GetImage(); 
    if( img ) 
    { 
        int color = desired_color; 
        if( color < 0 ) color = img->nChannels > 1; 
        Create( img->width, img->height, color ? 24 : 8 ); 
        if( m_img.nChannels == img->nChannels ) 
            iplCopy( img, &m_img ); 
        else 
        { 
            CImage tmp_image; 
             
            tmp_image.Create( m_img.width, m_img.height, img->nChannels*8 ); 
 
            IplImage* tmp_img = tmp_image.GetImage(); 
            iplCopy( img, tmp_img ); 
 
            if( color ) 
                iplGrayToColor( tmp_img, &m_img, 0, 0, 0 ); 
            else 
                iplColorToGray( tmp_img, &m_img ); 
        } 
    } 
} 
 
bool  CImage::LoadBMP2IPL( const char* filename, bool IsColor ) 
{ 
    int filter = 0; 
    int width = 0, height = 0; 
    bool result = false; 
    int color = 55; 
 
    if( gr_fmt_find_filter == 0 ) return false; 
 
    if( !(filter = gr_fmt_find_filter( filename ))) goto exit; 
    if( !gr_fmt_read_header( filter, &width, &height, &color )) goto exit; 
 
    Create( width, height, IsColor ? 24 : 8); 
    if( m_memDC == 0 ) goto exit; 
	if (IsColor==0)color=0; 
    result = gr_fmt_read_data( filter, m_img.imageData, m_img.widthStep, color ) != 0; 
exit: 
    gr_fmt_close_filter( filter ); 
    return result; 
} 
 
bool  CImage::LoadRect( const char* filename, 
                        int desired_color, RECT r ) 
{ 
    int filter = 0; 
    int width = 0, height = 0; 
    bool result = false; 
    int color = 0; 
    int r_width = r.right - r.left; 
    int r_height = r.bottom - r.top; 
    int tmp_step = 0; 
    char* tmp = 0; 
     
    if( r_width < 0 || r_height < 0 ) return false; 
    if( gr_fmt_find_filter == 0 ) return false; 
 
    if( !(filter = gr_fmt_find_filter( filename ))) goto exit; 
    if( !gr_fmt_read_header( filter, &width, &height, &color )) goto exit; 
 
    if( r_width == 0 || r_height == 0 ) 
    { 
        r_width = width; 
        r_height = height; 
    } 
 
    if( (unsigned)r.left >=  (unsigned)width || 
        (unsigned)r.top >=  (unsigned)height || 
        (unsigned)r.right >=  (unsigned)width || 
        (unsigned)r.bottom >=  (unsigned)height ) goto exit; 
 
    color = desired_color >=  0 ? desired_color : color > 0; 
     
    Create( r_width, r_height, color ? 24 : 8); 
    if( m_memDC == 0 ) goto exit; 
 
    if( r.left == 0 && r.top == 0 && 
        (r_width == 0 || r_width == width) && 
        (r_height == 0 || r_height == height)) 
    { 
        tmp = m_img.imageData; 
        tmp_step = m_img.widthStep; 
    } 
    else 
    { 
        tmp_step = (width*m_img.nChannels + 3) & -4; 
        tmp = (char*)malloc( tmp_step * height ); 
        if( !tmp ) goto exit; 
    } 
 
    result = gr_fmt_read_data( filter, tmp, tmp_step, color ) != 0; 
 
    if( result && tmp != m_img.imageData ) 
    { 
        int y; 
        for( y = 0; y < r_height; y++ ) 
        { 
            memcpy( m_img.imageData + y*m_img.widthStep, 
                    tmp + (r.top + y)*tmp_step + r.left*m_img.nChannels, 
                    r_width * m_img.nChannels ); 
        } 
    } 
 
exit: 
    gr_fmt_close_filter( filter ); 
    if( tmp != 0 && tmp != m_img.imageData ) free( tmp ); 
    return result; 
} 
 
void CImage::LoadIPL2IPL(IplImage *image) 
{ 
	Create(image->width, image->height, image->nChannels*8); 
	cvCopyImage(image, &m_img); 
} 
 
void CImage::SaveIPL2BMP(const char *fout, IplImage *image) 
{ 
    if ( (image->nChannels != 3 && image->nChannels != 1) || image->depth != IPL_DEPTH_8U ) return; 
 
    gr_fmt_write_image( image->imageData, image->widthStep, 
                        iplWidth( image ), iplHeight( image ), 
                        image->nChannels == 3, fout, "BMP" ); 
} 
void CImage::Show( HDC dc, int x, int y) 
{ 
Show(dc, x,y,Width(),Height(),0,0 ); 
} 
void CImage::Show( HDC dc, int x, int y, int w, int h, int from_x, int from_y ) 
{ 
    if( m_img.width > 0 ) 
    { 
        uchar buffer[sizeof(BITMAPINFOHEADER) + 1024]; 
        BITMAPINFO* bmi = (BITMAPINFO*)buffer; 
        int bmp_w = Width(); 
        int bmp_h = Height(); 
 
        FillBitmapInfo( bmi, bmp_w, bmp_h, m_img.nChannels*8 ); 
 
        int sw = MAX( MIN( bmp_w - from_x, w ), 0 ); 
        int sh = MAX( MIN( bmp_h - from_y, h ), 0 ); 
 
        int res = SetDIBitsToDevice( 
              dc,                        // handle to DC 
              x,                         // x-coord of destination upper-left corner 
              y,                         // y-coord of destination upper-left corner  
              sw,                        // source rectangle width 
              sh,                        // source rectangle height 
              from_x,                    // x-coord of source lower-left corner 
              from_y,                    // y-coord of source lower-left corner 
              from_y,                    // first scan line in array 
              sh,                        // number of scan lines 
              m_img.imageData + from_y*m_img.widthStep/* + 
              from_x*m_img.nChannels*/,    // array of DIB bits 
              (BITMAPINFO*)bmi,          // bitmap information 
              DIB_RGB_COLORS );          // RGB or palette indexes 
    } 
} 
 
void  CImage::Fill( COLORREF color ) 
{ 
    if( m_memDC ) 
    { 
        HBRUSH br = CreateSolidBrush( color ); 
        RECT rect; 
        GetClipBox( m_memDC, &rect ); 
        FillRect( m_memDC, &rect, br ); 
        DeleteObject( br ); 
    } 
} 
 
 
 
 
IplImage *Getchannel(IplImage *image,int channel) 
{   ASSERT(channel>= 0&&channel<3); 
	IplROI *ROI; 
	CvSize size; 
	size.width = image->width; 
	size.height = image->height; 
    ROI = iplCreateROI(0, 0, 0, 0, 0);  
	IplImage *channelimg = cvCreateImage(size,8,1); 
	iplSetROI(ROI,channel+1, 0, 0, size.width,size.height); 
	image->roi = ROI; 
	iplCopy(image,channelimg); 
	image->roi = NULL; 
	iplDeleteROI(ROI); 
	return channelimg; 
} 
 
IplImage *GetBchannel(IplImage *image) 
{ 
	return Getchannel(image,0); 
} 
 
IplImage *GetGchannel(IplImage *image) 
{ 
	return Getchannel(image,1); 
} 
 
IplImage *GetRchannel(IplImage *image) 
{ 
	return Getchannel(image,2); 
} 
 
CSize CImage::GetSize() 
{ 
return CSize(Width(),Height()); 
} 
 
void CImage::Save2Bmp(const char * filename) 
{ 
SaveIPL2BMP(filename,&m_img); 
} 
 
 
CImage * CImage::GetRect(CRect a) 
{ 
  CImage * output=new CImage(); 
    IplROI *ROI1; 
    ROI1 = iplCreateROI(0, a.left ,a.top, a.Width(),a.Height());  
    m_img.roi = ROI1; 
    output->Create(a.Width(),a.Height(),24); 
	iplCopy(&m_img,&output->m_img); 
    m_img.roi = NULL; 
	iplDeleteROI(ROI1); 
return output; 
} 
 
void drawrectangle(CPoint p1, CPoint p2, COLORREF color, CDC * pDC,int method) 
{   int meth; 
	if (method==0)meth=PS_SOLID; 
	else  
		meth=PS_DOT; 
	CPen penBlack; 
	penBlack.CreatePen(meth, 1, color); 
	CPen* pOldPen = pDC->SelectObject(&penBlack); 
	CRect m_rect(p1,p2); 
	pDC->MoveTo(m_rect.left,m_rect.top); 
	pDC->LineTo(m_rect.left,m_rect.bottom); 
	pDC->LineTo(m_rect.right,m_rect.bottom); 
	pDC->LineTo(m_rect.right,m_rect.top); 
	pDC->LineTo(m_rect.left,m_rect.top); 
	pDC->SelectObject(pOldPen); 
} 
 
void CImage::Mean(int color[3],CRect rectoi) 
{ 
	IplROI *ROI1; 
	ROI1 = iplCreateROI(0,rectoi.left,rectoi.top,rectoi.Width(),rectoi.Height());  
	for (int i=0;i<3;i++) 
		{iplSetROI(ROI1,i+1,rectoi.left,rectoi.top,rectoi.Width(),rectoi.Height()); 
		m_img.roi = ROI1; 
		color[i]=cvMean(&m_img); 
		} 
	m_img.roi=NULL; 
	iplDeleteROI(ROI1); 
 
} 
 
void Thinning(IplImage *Img,CvSize size) 
{ 
	static int erasetable[256]={ 
                0,0,0,1,0,0,1,1, 
                0,1,1,1,0,0,1,1, 
                0,0,1,1,1,0,1,1, 
                0,0,1,1,0,0,1,1, 
 
                0,0,0,0,0,0,0,0, 
                1,1,1,1,0,0,1,1, 
                0,0,0,0,0,0,0,0, 
                0,0,1,1,0,0,1,1, 
 
                0,0,0,0,0,0,0,0, 
                1,1,1,1,0,0,1,1, 
                1,0,1,1,1,0,1,1, 
                1,1,0,0,1,1,0,0, 
 
                1,0,0,0,0,0,0,0, 
                1,1,1,1,0,0,1,1, 
                1,0,1,1,1,0,1,1, 
                1,1,0,0,1,1,0,0, 
 
                0,0,0,0,0,0,0,0, 
                0,0,0,0,0,0,0,0, 
                1,0,1,1,1,0,1,1, 
                0,0,1,1,0,0,1,1, 
 
                0,0,0,0,0,0,0,0, 
                0,0,0,0,0,0,0,0, 
                0,0,0,0,0,0,0,0, 
                0,0,1,1,0,0,1,1, 
 
                1,0,0,0,0,0,0,0, 
                1,1,1,1,0,0,1,1, 
                1,0,1,1,1,0,1,1, 
                1,1,0,0,1,1,0,0, 
 
                1,0,0,0,0,0,0,0, 
                1,1,1,1,0,0,1,1, 
                1,0,1,1,1,0,1,1, 
                1,1,0,0,1,1,0,0 
  };  
 
  int                x,y; 
	int			           num; 
	int                Finished; 
	int                nw,n,ne,w,e,sw,s,se; 
   
  IplImage *tImg; 
  char *ImgStart, *tImgStart, *lpPtr, *lpTempPtr; 
  int LineBytes; 
 
  LineBytes = Img->width; 
 
  tImg = cvCreateImage(size, 8, 1); 
  iplCopy(Img, tImg); 
   
  ImgStart = Img->imageData;     
	tImgStart = Img->imageData; 
 
  Finished=FALSE; 
  while(!Finished){ 
  	Finished=TRUE; 
		for (y=1; yheight-1;y++) 
    {  
			lpPtr = ImgStart + y*LineBytes; 
			lpTempPtr = tImgStart + y*LineBytes; 
			x=1;  
			while(xwidth-1) 
      { 
				if(*(lpPtr+x)){ 
          w=(BYTE)*(lpPtr+x-1)?255:0; 
          e=(BYTE)*(lpPtr+x+1)?255:0; 
					if( (w==0)|| (e==0)){ 
            nw=(unsigned char)*(lpPtr+x+LineBytes-1)?255:0; 
						n=(unsigned char)*(lpPtr+x+LineBytes)?255:0; 
						ne=(unsigned char)*(lpPtr+x+LineBytes+1)?255:0; 
						sw=(unsigned char)*(lpPtr+x-LineBytes-1)?255:0; 
						s=(unsigned char)*(lpPtr+x-LineBytes)?255:0; 
						se=(unsigned char)*(lpPtr+x-LineBytes+1)?255:0; 
						num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+sw/255*32+s/255*64+se/255*128; 
						if(erasetable[num]==1){ 
							*(lpPtr+x)= 0; 
							*(lpTempPtr+x)= 0; 
							Finished=FALSE; 
							x++; 
						} 
					} 
				} 
				x++; 
			} 
		} 
 
		for (x=1;xwidth-1;x++){  
			y=1; 
			while(yheight-1){ 
  			lpPtr = ImgStart + y*LineBytes; 
	  		lpTempPtr = tImgStart + y*LineBytes; 
				if(*(lpPtr+x)){ 
					n=(unsigned char)*(lpPtr+x+LineBytes)?255:0; 
					s=(unsigned char)*(lpPtr+x-LineBytes)?255:0; 
					if( (n==0)|| (s==0)){ 
						nw=(unsigned char)*(lpPtr+x+LineBytes-1)?255:0; 
						ne=(unsigned char)*(lpPtr+x+LineBytes+1)?255:0; 
						w=(unsigned char)*(lpPtr+x-1)?255:0; 
						e=(unsigned char)*(lpPtr+x+1)?255:0; 
						sw=(unsigned char)*(lpPtr+x-LineBytes-1)?255:0; 
						se=(unsigned char)*(lpPtr+x-LineBytes+1)?255:0; 
						num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+sw/255*32+s/255*64+se/255*128; 
						if(erasetable[num]==1){ 
							*(lpPtr+x)=0; 
							*(lpTempPtr+x)=0; 
							Finished=FALSE; 
							y++; 
						} 
					} 
				} 
				y++; 
			} 
		}  
	}//end of while 
 
  cvReleaseImage(&tImg); 
} 
 
 
 
/*ipl 应用函数 (非cimage类成员函数)*/ 
/*typedef enum { Error = -1, Fail = 0, Good = 1 } ipStatus; 
//static ThreadDataArray g_threads; 
BITMAPINFOHEADER* ipLoad( const char* fname ) { 
 
   if( !fname ) return NULL; 
    
   BITMAPINFOHEADER *infohdr = NULL; 
 
   ifstream fsrc; 
 
   try { 
      BITMAPFILEHEADER filehdr; 
      BITMAPINFOHEADER bmphdr; 
 
      fsrc.open( fname, ios::in | ios::binary ); 
      if( fsrc.fail() ) throw runtime_error("Problem to open source file"); 
 
 
      fsrc.read( (char*)&filehdr, sizeof(BITMAPFILEHEADER) ); 
      if( fsrc.fail() ) throw runtime_error("Problem to read bmp-file header from source file"); 
 
      if( 0x4d42 != filehdr.bfType ) throw runtime_error("Wrong type of source file"); 
 
      fsrc.read( (char*)&bmphdr, sizeof(BITMAPINFOHEADER) ); 
      if( fsrc.fail() ) throw runtime_error("Problem to read bmp-header from source file"); 
 
      if( 0 == bmphdr.biSizeImage ) 
         bmphdr.biSizeImage = 
            (((( bmphdr.biWidth * bmphdr.biBitCount ) + 31) & ~31) >> 3) * bmphdr.biHeight; 
 
      if( 0 == bmphdr.biClrUsed ) { 
         if( BI_BITFIELDS == bmphdr.biCompression ) 
            bmphdr.biClrUsed = 3; 
         else  
            bmphdr.biClrUsed = bmphdr.biBitCount < 16 ? 1 << bmphdr.biBitCount : 256; 
      } 
 
      int colorbytes = sizeof(RGBQUAD) * bmphdr.biClrUsed; 
      int totalbytes = sizeof(BITMAPINFOHEADER) + colorbytes + bmphdr.biSizeImage; 
 
      infohdr = (BITMAPINFOHEADER*)malloc( totalbytes ); 
      if( !infohdr ) throw runtime_error("Problem to allocate memory for DIB data"); 
       
      char* quads = (char*)infohdr + sizeof(BITMAPINFOHEADER); 
      char* pixels = (char*)quads + colorbytes; 
 
      memcpy( infohdr, &bmphdr, sizeof( bmphdr) ); 
 
      fsrc.read( (char*)quads, colorbytes ); 
      fsrc.read( (char*)pixels, bmphdr.biSizeImage ); 
 
      fsrc.close(); 
   } 
   catch( runtime_error e ) { 
      TRACE0( e.what() ); 
      if( infohdr ) {  
         free( infohdr ); 
         infohdr = 0; 
      } 
   } 
 
   return infohdr; 
} 
 
IplImage* cloneImageHeader( const IplImage* src, int width, int height ) { 
 
   IplImage* clone = NULL; 
   if( src ) { 
      clone = iplCreateImageHeader( src->nChannels, src->alphaChannel, 
         src->depth, (char*)src->colorModel, (char*)src->channelSeq, src->dataOrder, 
         src->origin, src->align, width, height,  
         NULL, NULL, NULL, NULL); 
   } 
   return clone; 
} 
 
IplImage* cloneImageHeader( const IplImage* src ) { 
   if( !src ) return NULL; 
   return cloneImageHeader( src, src->width, src->height ); 
} 
 
void ipInflateRoi( IplROI *roi, int step ) { 
   roi->xOffset -= step; 
   roi->yOffset -= step; 
   roi->width += (step*2); 
   roi->height += (step*2); 
} 
 
int ipSetImageROI( IplImage *img, int coi, int x, int y, int w, int h ) { 
 
   if( !img ) return 0; 
   if( !img->roi ) 
      img->roi = iplCreateROI( coi, x,y, w,h ); 
   else 
      iplSetROI( img->roi, coi, x,y, w,h ); 
   return !img->roi; 
} 
 
int ipSetROItoWholeImage( IplImage *img ) { 
 
   if( !img ) return 0; 
   img->roi = iplCreateROI( 0, 0,0, img->width, img->height ); 
   return !img->roi; 
} 
 
extern "C" __int64 winrdtsc(); 
 
__int64 getPentiumCounter() {  
  // winrdtsc(); 
   __asm mov   ecx, edx 
   __asm mov   edx, eax 
   __asm mov   eax, ecx 
} 
 
static ipStatus ipDraw( HDC hdc, IplImage* img ) { 
 
   if( !img || !img->imageData ) return Error; 
    
   bool isrgb = 
      'R' == toupper( img->colorModel[0] ) &&  
      'G' == toupper( img->colorModel[1] ) &&  
      'B' == toupper( img->colorModel[2] ); 
    
   bool isgray = 'G' == toupper( img->colorModel[0] ); 
 
   if( !isgray && !isrgb ) return Fail; 
   if( (1 == img->nChannels) != isgray ) return Fail; 
 
   char buf[ sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256 ]; 
   BITMAPINFOHEADER* dibhdr = (BITMAPINFOHEADER*)buf; 
   COLORREF* rgb = (COLORREF*)( buf + sizeof(BITMAPINFOHEADER) ); 
 
   if( isgray ) for( int i = 0; i < 256; i++) rgb[i] = RGB( i,i,i ); 
 
   dibhdr->biSize = sizeof( BITMAPINFOHEADER ); 
   dibhdr->biWidth = img->width; 
   dibhdr->biHeight = img->height; 
   dibhdr->biPlanes = 1; 
   dibhdr->biBitCount = (DWORD)(8 * img->nChannels); 
   dibhdr->biCompression = BI_RGB; 
   dibhdr->biSizeImage = img->imageSize; 
   dibhdr->biXPelsPerMeter = 0; 
   dibhdr->biYPelsPerMeter = 0; 
   dibhdr->biClrUsed = 0; 
   dibhdr->biClrImportant = 0;  
 
   ::SetDIBitsToDevice( hdc, 0,0,img->width,img->height,  
      0,0,0,img->height, img->imageData, (BITMAPINFO*)dibhdr, DIB_RGB_COLORS ); 
 
   return Good; 
} 
 
HANDLE ipView( const IplImage* img, const char* caption, bool isModalView ) { 
 
   if( !img ) return 0; 
 
   if( g_threads.isfull() ) { 
      MessageBox( NULL, "Too many threads are beign executed. " 
         "Please decrease number of viewers or use Modal mode.",  
         g_name, MB_OK | MB_ICONSTOP ); 
      return 0; 
   } 
 
   IplImage *clone = NULL, *img8u = NULL; 
   HANDLE hThread = 0; 
 
   /// Note we need not clone in the DEPTH_1U case 
 
   if( NULL == (clone = iplCloneImage( img ))) return 0; 
   /// Since this moment we should take care about clone pointer 
 
   try { 
      /// Create header for the image to be drawn 
      img8u = iplCreateImageHeader( 
         img->nChannels, 
         img->alphaChannel, 
         IPL_DEPTH_8U,                          /// fixed 8u 
         (char*)img->colorModel,  
         (char*)img->channelSeq,  
         IPL_DATA_ORDER_PIXEL,                  /// fixed pixel 
         img->origin, 
         IPL_ALIGN_DWORD, 
         img->width, img->height,  
         NULL, NULL, NULL, NULL ); 
       
      if( !img8u ) throw bexception( false ); 
    
      iplAllocateImage( img8u, 0,0 ); 
      if( !img8u->imageData ) throw bexception( true ); 
    
      /// convert to 8u,plane image for viewing 
      if( IPL_DEPTH_1U == img->depth ) 
         iplBitonalToGray( (IplImage*)img, img8u, 0,255 ); 
      else if( IPL_DEPTH_8U != img->depth ) 
         iplScale( img, img8u ); 
      else 
         iplCopy( (IplImage*)img, img8u ); 
 
      if( IPL_StsOk != iplGetErrStatus()) throw bexception( true ); 
 
      static ThreadData param; 
      lstrcpy( param.text, NULL == caption ? "IPLib image" : caption ); 
      param.img = img8u; 
      param.isModalView = isModalView; 
 
      /// prepare for wainting 
      ::ResetEvent( g_threads.m_hevent ); 
 
      hThread = CreateThread(  
         NULL,                                  // pointer to thread security attributes 
         0,                                     // initial thread stack size, in bytes 
         (LPTHREAD_START_ROUTINE) ViewerThread, // pointer to thread function 
         (LPVOID)(0),                           // argument for new thread 
         0,                                     // creation flags, runs immediately 
         ¶m.id);                            // pointer to returned thread identifier 
       
      if( !hThread ) throw bexception( true ); 
 
      /// set thread data for thread has been started 
      if( false == g_threads.open( param )) { 
         ::CloseHandle( hThread ); 
         throw bexception( true ); 
      } 
       
      if( isModalView ) { 
         /// wait for the thread will be ended 
         ::WaitForSingleObject( hThread, INFINITE ); 
         ::CloseHandle( hThread ); 
         return 0; 
      } 
      else 
         /// wait for dialog window will be initialized 
         /// thread will be alive after that 
         ::WaitForSingleObject ( g_threads.m_hevent, 10000 ); 
   } 
   catch( bexception e ) { 
      /// if success then img8u is deleted by the close procedure 
      /// when dialog window will be closed by user 
      /// else we should delete img8u 
      if( e.m_should_delete ) iplDeallocate( img8u, IPL_IMAGE_HEADER ); 
   } 
   ///  
   if( clone ) iplDeallocate( clone, IPL_IMAGE_HEADER ); 
 
   return hThread; 
} 
 
void create_translate_dib( const char* fname ) { 
 
   BITMAPINFOHEADER* bmphdr = ipLoad( fname ); 
   if( bmphdr ) { 
      int clone; 
      IplImage* img = iplTranslateDIB( bmphdr, &clone ); 
      if( img ) { 
         ipView( img, fname, is_modal ); 
         iplDeallocate( img, clone ? IPL_IMAGE_ALL : IPL_IMAGE_HEADER ); 
      } 
      free( bmphdr ); 
   } 
   else { 
      TRACE0( "Problem to read bmp-file" ); 
   } 
} 
 
void create_convert_dib( const char* fname ) { 
 
   BITMAPINFOHEADER* bmphdr = ipLoad( fname ); 
   if( bmphdr ) { 
 
      IplImage* img = iplCreateImageHeader(  
         3,                            // number of channels 
         0,                            // alpha channel 
         IPL_DEPTH_8U,                 // data of byte type  
         "RGB", "BGR",                 // color model and channel seq 
         IPL_DATA_ORDER_PIXEL,         // channel arrangement 
         IPL_ORIGIN_TL,                // top left orientation 
         IPL_ALIGN_DWORD,              // 4 bytes align 
         bmphdr->biWidth, bmphdr->biHeight, 
         NULL,                         // ROI 
         NULL, NULL, NULL );           // no mask ROI, image ID, not tiled 
      if( img ) { 
         iplConvertFromDIB( bmphdr, img ); 
         ipView( img, fname, is_modal ); 
         iplDeallocate( img, IPL_IMAGE_ALL ); 
      } 
      free( bmphdr ); 
   } 
   else { 
      TRACE0( "Problem to read bmp-file" ); 
   } 
} 
 
 
void testCOI( IplImage* srcAimg, IplImage* srcBimg, IplImage* dstimg,  
   int roiOffset, int roiSize )  
{ 
 
   IplImage* dstimgRGBA = NULL; 
    
   /// Note that ROI is created in stack and you should not 
   /// use the ALL mode in Deallocate function without 
   /// setting the image COI to NULL. It is useful to know 
   /// but not necessarily to use. 
   IplROI roi = { 1, 0,0, width, height }; 
 
   __try { 
 
      dstimgRGBA = iplCreateImageHeader( 
         4,                      // number of channels 
         4,                      // alpha channel number 
         IPL_DEPTH_8U,           // depth of data image 
         "RGBA", "RGBA",         // color model and channel sequence 
         IPL_DATA_ORDER_PIXEL,   // image is defined as pixels 
         IPL_ORIGIN_TL,          // origin is in the top left corner 
         IPL_ALIGN_QWORD,        // image width is aligned  
         width, height,          // width and height of image 
         &roi,                   // region of interest 
         NULL,                   // no mask ROI here 
         NULL, NULL              // image id, not tiled 
         ); 
      if( !dstimgRGBA ) return; 
       
      iplAllocateImage( dstimgRGBA, 1, 128 ); 
      if( !dstimgRGBA->imageData ) return; 
       
      // Using Channel of Interest, copy one channel at a  
      // time from source to destination for 3 channels. 
 
      ipSetROItoWholeImage( srcAimg ); 
      ipSetROItoWholeImage( srcBimg ); 
 
      /// channels 1 and 2 from source A 
      srcAimg->roi->coi = 1; 
      dstimgRGBA->roi->coi = 1; 
      iplCopy( srcAimg, dstimgRGBA ); 
       
      srcAimg->roi->coi = 2; 
      dstimgRGBA->roi->coi = 2; 
      iplCopy( srcAimg, dstimgRGBA ); 
       
      /// channel 3 from source B 
      srcBimg->roi->coi = 3; 
      ipSetImageROI( dstimgRGBA, 3, roiOffset, roiOffset, roiSize, roiSize ); 
      iplCopy( srcBimg, dstimgRGBA ); 
 
      /// copy channel 3 of source to channel 4 (alpha channel) of destination 
      dstimgRGBA->roi->coi = 4; 
      iplCopy( srcAimg, dstimgRGBA ); 
       
      /// destination image RGBA is copy of channels 
      ipView( dstimgRGBA, "RGBA is copy of A.1 A.2 B.3 A.3", is_modal ); 
 
   } 
   __finally { 
      ///  restore roi 
      ipSetROItoWholeImage( srcAimg ); 
      ipSetROItoWholeImage( srcBimg ); 
      /// set roi to NULL to protect automatic variable against of freeing 
      if( dstimgRGBA) { 
         dstimgRGBA->roi = NULL;                        
         iplDeallocate( dstimgRGBA, IPL_IMAGE_ALL ); 
      } 
   } 
} 
 
int countObjects( IplImage *img ) { 
   int x, y; 
 
   static const int WHITE = 255;    // color of an object on enter 
   static const int GRAY  = 128;    // color of an object on exit 
 
   unsigned char *prev = (unsigned char*)img->imageData; 
   unsigned char *line = prev + img->widthStep; 
 
   /// find and fill objects by gray color, label is one white pixel 
   for( y=1; yheight; ++y ) { 
      x = 1; 
      while( x < img->width-1 ) { 
         /// check if there is an object 
         if( WHITE == line[x] ) { 
            /// skip first point but maybe we'll return to it 
            int xx = x+1; 
            /// paint the object 
            do { 
               /// check point above and on the left 
               /// paint the first point if we are inside of the object  
               if( 0 != prev[xx-1] || 0 != prev[xx] ) line[x] = GRAY; 
               line[xx++] = GRAY; 
            } 
            while( xx < img->width-1 && WHITE == line[xx] ); 
            x = xx; 
         } 
         else 
            x++; 
      } 
      prev = line; 
      line += img->widthStep; 
   } 
 
   /// count the marked objects, one white point is one object 
   int count = 0; 
   line = (unsigned char*)img->imageData; 
   for( y=1; yheight-1; ++y ) { 
      for( x=1; xwidth; ++x ) if( WHITE == line[x] ) count++; 
      line += img->widthStep; 
   } 
 
   return count; 
} 
 
*/ 
 
unsigned char ** CImage::ProcessArray() 
{//最多可以处理500 行图象 //仅仅对灰度 
	static unsigned char* image[500]; 
 
    for (int i=0;i< m_img.height;i++) 
	{ 
		image[i]=(unsigned char *)((m_img.imageData)+i*m_img.width); 
	} 
	return &image[0]; 
}