www.pudn.com > 医学图像处理示例源代码.rar > Image.cpp


 
//这里是"image.h"的实现函数定义 
#include "stdafx.h" 
#include  
#include  
#include  
#include "image.h" 
#include  
 
FloatImage::FloatImage() 
{ 
	lp_data   = NULL; 
	lp_AddRow = NULL; 
	Width     = Height = 0; 
} 
FloatImage::~FloatImage() 
{ 
	DeleteData(); 
} 
FloatImage::FloatImage(unsigned int w, unsigned int h) 
{ 
	Width  = w; 
	Height = h; 
	ImageSize = w * h; 
	lp_data   = NULL; 
	lp_AddRow = NULL; 
	Construct(w, h); 
} 
void FloatImage::Construct(unsigned int w, unsigned int h) 
{ 
	DeleteData(); 
	if( ImageSize > 0 ) lp_data   = new  float[ImageSize]; 
	memset(lp_data, 0, ImageSize* sizeof(float) ); 
	if( Height    > 0 ) lp_AddRow = new float*[Height]; 
	lp_AddRow[0] = lp_data; 
	for( UINT i= 1; i < Height; i++) 
		lp_AddRow[i] = lp_AddRow[i- 1] + Width; 
 
} 
void FloatImage::DeleteData() 
{ 
	if(lp_data   != NULL) delete []lp_data; 
	if(lp_AddRow != NULL) delete []lp_AddRow; 
} 
//--------------------------CImage class declaration -------------------// 
//*********************************************************** 
//*********************************************************** 
C2DArray::C2DArray() 
{ 
    m_lpDibArray = NULL; 
	RowAddress   = NULL; 
} 
//*********************************************************** 
 
//*********************************************************** 
C2DArray::~C2DArray() 
{ 
    if(m_lpDibArray != NULL)  ReleaseDibArray();     
} 
//*********************************************************** 
 
//*********************************************************** 
void C2DArray::ReleaseDibArray() 
{ 
	if( m_lpDibArray != NULL ) 
    { 
		delete []m_lpDibArray; 
        m_lpDibArray = NULL; 
    } 
	if( RowAddress != NULL)   
	{ 
		delete []RowAddress; 
		RowAddress = NULL; 
	} 
} 
//*********************************************************** 
 
//*********************************************************** 
C2DArray::C2DArray(P_LONG width, P_LONG height) 
{ 
    m_nDibWidth  = width; 
    m_nDibHeight = height; 
    m_lpDibArray = NULL; 
    RowAddress   = NULL; 
     
	m_lpDibArray = new P_BYTE[width * height]; 
	if( m_lpDibArray == NULL) AfxThrowMemoryException(); 
 
	RowAddress    = new P_BYTE*[m_nDibHeight]; 
	RowAddress[0] = m_lpDibArray; 
    for(int i=1; i= m_nDibWidth) || (y < 0) || ( y >= m_nDibHeight) ) 
	{ 
		if( x < 0 ) x = 0; 
		else if( x >= m_nDibWidth )  x = m_nDibWidth-1; 
 
		if(y<0) y = 0; 
		else if( y >= m_nDibHeight ) y = m_nDibHeight-1; 
 
		return false; 
	} 
	else 
		return true; 
} 
BOOL C2DArray::CheckDataRange(CPoint pt) 
{ 
	return CheckDataRange(pt.x, pt.y); 
} 
//*********************************************************** 
 
//*********************************************************** 
P_BYTE C2DArray::SGetXYValue(P_LONG x, P_LONG y) 
{	 
#ifdef _DEBUG 
	if(!CheckDataRange(x, y))  
	{ 
		AfxMessageBox("下标越界!!!"); 
		AfxAbort(); 
	} 
#endif     
	return RowAddress[y][x]; 
} 
P_BYTE C2DArray::SGetXYValue(CPoint pt) 
{	 
    return SGetXYValue(pt.x, pt.y); 
} 
//*********************************************************** 
 
//*********************************************************** 
void  C2DArray::SSetXYValue(P_LONG x, P_LONG y, P_BYTE value) 
{  
#ifdef _DEBUG	 
	if(!CheckDataRange(x,y))  
	{ 
		AfxMessageBox("下标越界!!!"); 
		AfxAbort(); 
	} 
#endif 
	RowAddress[y][x] = value;  
} 
void  C2DArray::SSetXYValue(CPoint pt, P_BYTE value) 
{	 
	SSetXYValue(pt.x, pt.y, value); 
} 
 
BOOL  CImage::CheckPoint(P_LONG &x, P_LONG &y) 
{ 
	if( (x<0)||(x>=m_ImageWidth)||(y<0)||(y>=m_ImageHeight) ) 
	{ 
		if( x < 0) x = 0; 
		else if( x >= m_ImageWidth )  x = m_ImageWidth-1; 
 
		if( y < 0 ) y = 0; 
		else if( y >= m_ImageHeight ) y = m_ImageHeight-1; 
 
		return false; 
	} 
	else 
		return true; 
} 
BOOL CImage::CheckPoint(CPoint &pt)           
{ 
	return CheckPoint(pt.x, pt.y); 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::CheckRect(CPoint &p1,CPoint &p2) 
{ 
	if(!CheckPoint(p1) || !CheckPoint(p2))  
		return false; 
	P_LONG tempx, tempy, temp; 
    tempx = p2.x - p1.x; 
	tempy = p2.y - p1.y; 
     
	if( tempx < 0 ) 
	{ 
		temp = p1.x;  
		p1.x = p2.x;  
		p2.x = temp; 
	} 
	if( tempy < 0) 
	{ 
		temp = p1.y;  
		p1.y = p2.y;  
		p2.y = temp; 
	} 
	if( labs(tempx)<5||labs(tempy)<5)  
		return false; 
	else 
		return true; 
} 
BOOL CImage::CheckRect(CRect &ImageRect) 
{ 
	if( ImageRect.left < 0 )  
	{ 
		ImageRect.left = 0; 
	} 
	else if( ImageRect.right > (m_ImageWidth-1) )  
	{ 
		ImageRect.right = m_ImageWidth- 1; 
	} 
	if( ImageRect.top < 0 ) 
	{ 
		ImageRect.top = 0; 
	} 
	else if( ImageRect.bottom > (m_ImageHeight-1) ) 
	{ 
		ImageRect.bottom = m_ImageHeight- 1; 
	} 
 
	if( ImageRect.Width()<5||ImageRect.Height()<5)  
		return false; 
	else 
		return true; 
} 
//*********************************************************** 
 
//*********************************************************** 
void CImage::ConstructInit() 
{ 
 	m_fScale         = 1.0; 
	m_bImgModified   = FALSE;     
    m_wColorMapNum   = 0; 
    m_lpDibInfo      = NULL; 
	m_lpHSIArray     = NULL; 
    m_lpDibArrayBuff = NULL;  
	m_hDIB           = NULL; 
	m_Bright		 = -1; 
	m_Contrast		 = -1; 
	m_SorceType		 = 0; 
} 
// 释放全部的内存 
void CImage::DeleteMe() 
{ 
	if(          m_hDIB != NULL) ReleaseCopyHandle(); 
	if(     m_lpDibInfo != NULL) ReleaseDibPalInfo(); 
	if(    m_lpDibArray != NULL) ReleaseDibArray();     
	if(    m_lpHSIArray != NULL) ReleaseHueImg(); 
    if(m_lpDibArrayBuff != NULL) ReleaseBuffer();   
} 
//释放m_lpDibInfo内存 
void CImage::ReleaseDibPalInfo() 
{ 
	if( m_pUseful != NULL ) 
	{		 
		delete []m_pUseful; 
		m_lpDibInfo = NULL; 
		m_pUseful   = NULL; 
	} 
} 
//释放m_lpDibArrayBuff内存 
void CImage::ReleaseBuffer() 
{ 
	if( m_lpDibArrayBuff != NULL ) 
	{ 
		delete []m_lpDibArrayBuff ; 
		m_lpDibArrayBuff = NULL; 
	} 
} 
//释放m_lpHSIArray内存 
void CImage::ReleaseHueImg() 
{ 
	if( m_lpHSIArray != NULL ) 
	{ 
		delete []m_lpHSIArray; 
		m_lpHSIArray = NULL; 
    } 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::NewBuffer() 
{ 
	if( m_lpDibArrayBuff != NULL )  
		ReleaseBuffer(); 
	if( m_ImageSize ) 
	{ 
		m_lpDibArrayBuff = new P_BYTE[m_ImageSize]; 
		if( m_lpDibArrayBuff == NULL ) 
		{ 
			AfxThrowMemoryException();  // especial  exception handle  
		    return false;  
		} 
		else 
			return true; 
	} 
	else 
		return false;  
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::NewHSIImg() 
{ 
	if( m_lpHSIArray != NULL )  
		ReleaseHueImg(); 
	if( m_HSIImageWidth*m_HSIImageHeight ) 
	{ 
		m_lpHSIArray = new P_BYTE[m_HSIImageWidth*m_HSIImageHeight]; 
		if( m_lpHSIArray  == NULL ) 
		{ 
			AfxThrowMemoryException();  // especial  exception handle  
		    return false;  
		} 
		else 
			return true; 
	} 
	else 
		return false;  
} 
//*********************************************************** 
 
//*********************************************************** 
CImage::CImage() 
{ 
    ConstructInit(); 
} 
//*********************************************************** 
 
//*********************************************************** 
CImage::~CImage() 
{     
	if(          m_hDIB != NULL) ReleaseCopyHandle(); 
	if(     m_lpDibInfo != NULL) ReleaseDibPalInfo(); 
	if(    m_lpHSIArray != NULL) ReleaseHueImg(); 
    if(m_lpDibArrayBuff != NULL) ReleaseBuffer();   
} 
CImage::CImage(CImage &source) 
{ 
	ConstructInit(); 
 
    m_ImageSize      = source.m_ImageSize; 
    m_ImageWidth     = source.m_ImageWidth;	 
    m_ImageHeight    = source.m_ImageHeight;	 
    m_nDibWidth      = source.m_nDibWidth; 
    m_nDibHeight     = source.m_nDibHeight; 
	m_wImageDepth    = source.m_wImageDepth; 
	m_wColorMapNum   = source.m_wColorMapNum;   
    m_HSIImageWidth  = source.m_HSIImageWidth; 
	m_HSIImageHeight = source.m_HSIImageHeight; 
     
	m_dwRBitMask	 = source.m_dwRBitMask;	 
	m_dwGBitMask 	 = source.m_dwGBitMask; 	 
	m_dwBBitMask	 = source.m_dwBBitMask;	 
	m_wlowRedBit	 = source.m_wlowRedBit;	 
	m_wlowGreenBit	 = source.m_wlowGreenBit;	 
	m_wlowBlueBit    = source.m_wlowBlueBit;    
	m_wNumRedBits	 = source.m_wNumRedBits;	 
	m_wNumGreenBits  = source.m_wNumGreenBits;  
	m_wNumBlueBits	 = source.m_wNumBlueBits; 
 
	AllocateMemory(); 
     
	if( m_lpDibInfo != NULL ) //create the bitmap info 
	{ 
		m_lpDibInfo->bmiHeader = source.m_lpDibInfo->bmiHeader; 
    	if(m_wColorMapNum) //create the color table 
		{ 
			for(int i=0; ibmiColors[i] = source.m_lpDibInfo->bmiColors[i]; 
			} 
			BakupColorIndex(); 
		} 
	} 
	memcpy(m_lpDibArray, source.m_lpDibArray, m_ImageSize);     
	GenerateRowAddress(); 
}    
  
CImage::CImage(CImage &source, CPoint <p, CPoint &RBp) 
{ 
#ifdef _DEBUG 
	if(!source.CheckRect(LTp, RBp)) 
	{ 
		AfxMessageBox("下标越界!!!"); 
		AfxAbort(); 
	} 
#endif   
 
	ConstructInit(); 
 
	m_wImageDepth    = source.m_wImageDepth; 
	m_wColorMapNum   = source.m_wColorMapNum;  
	m_HSIImageWidth  = source.m_HSIImageWidth; 
	m_HSIImageHeight = source.m_HSIImageHeight; 
     
 	P_LONG width     = RBp.x - LTp.x + 1; 
    P_LONG height    = RBp.y - LTp.y + 1; 
 
    m_ImageWidth     = width;	 
    m_ImageHeight    = height;	 
    m_nDibWidth      = (width* m_wImageDepth/ 8 + 3) & ~3; 
    m_nDibHeight     = height; 
	m_ImageSize      = m_nDibWidth* m_nDibHeight; 
	 
	AllocateMemory(); 
    if( m_lpDibInfo != NULL ) //create the bitmap info      
	{ 
		m_lpDibInfo->bmiHeader          = source.m_lpDibInfo->bmiHeader; 
		m_lpDibInfo->bmiHeader.biWidth  = width; 
		m_lpDibInfo->bmiHeader.biHeight = source.m_IsImageDownUp ? m_nDibHeight : -m_nDibHeight;; 
		if( m_wColorMapNum )  
		{ 
			for(int i= 0; i< m_wColorMapNum; i++) 
			{ 
				m_lpDibInfo->bmiColors[i] = source.m_lpDibInfo->bmiColors[i]; 
			} 
			BakupColorIndex(); 
		} 
	} 
	GenerateRowAddress(); 
 
	BYTE *bpSourceAdd; 
	int   OffSet      = LTp.x * m_wImageDepth/ 8; 
	int   DataLength  = width * m_wImageDepth/ 8; 
    for( P_LONG y = 0;  y < height; y++) 
	{ 
		bpSourceAdd = source.RowAddress[LTp.y + y] + OffSet; 
		memcpy( RowAddress[y], bpSourceAdd, DataLength );		 
	}	 
} 
 
CImage::CImage(P_LONG width, P_LONG height, int PixelDepth, DWORD colornum) 
{ 
	ConstructInit();     
	CreateEmpty(width, height, PixelDepth, colornum);        
} 
     
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::CreateEmpty(P_LONG width, P_LONG height, int PixelDepth, DWORD colornum) 
{ 
	DeleteMe(); 
	ConstructInit();     
 
    m_wImageDepth    = PixelDepth;     
    m_ImageWidth     = width;	 
    m_ImageHeight    = height;	 
    m_nDibWidth      = (width* m_wImageDepth/ 8 + 3) & ~3; 
    m_nDibHeight     = height; 
	m_ImageSize      = m_nDibWidth* m_nDibHeight; 
    m_wColorMapNum   = GetColorMapNum(m_wImageDepth); 
    m_HSIImageWidth  = (width + 3) & ~3; 
	m_HSIImageHeight = height; 
 
	if( m_wImageDepth == 16 || m_wImageDepth == 32 ) 
		AllocateMemory(true); 
	else  
		AllocateMemory(); 
    if(m_lpDibInfo!=NULL && m_lpDibArray!=NULL) //create the bitmap info      
	{   
		m_lpDibInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER); 
		m_lpDibInfo->bmiHeader.biWidth         = width; 
		m_lpDibInfo->bmiHeader.biHeight        = height; 
		m_lpDibInfo->bmiHeader.biPlanes        = 1; 
		m_lpDibInfo->bmiHeader.biBitCount      = m_wImageDepth; 
		m_lpDibInfo->bmiHeader.biCompression   = BI_RGB; 
		m_lpDibInfo->bmiHeader.biSizeImage     = m_ImageSize; 
		m_lpDibInfo->bmiHeader.biXPelsPerMeter = 0; 
		m_lpDibInfo->bmiHeader.biYPelsPerMeter = 0; 
		m_lpDibInfo->bmiHeader.biClrUsed       = m_wColorMapNum; 
		m_lpDibInfo->bmiHeader.biClrImportant  = 0; 
 
		GenerateRowAddress(); 
	 
		if( m_wImageDepth <= 8 ) //create the color table 
		{ 
			for(int i= 0; i< m_wColorMapNum; i++) 
			{ 
				m_lpDibInfo->bmiColors[i].rgbBlue     = (P_BYTE)i; 
				m_lpDibInfo->bmiColors[i].rgbGreen    = (P_BYTE)i; 
				m_lpDibInfo->bmiColors[i].rgbRed      = (P_BYTE)i; 
				m_lpDibInfo->bmiColors[i].rgbReserved = 0; 
			}  
			BakupColorIndex(); 
			memset(m_lpDibArray, (P_BYTE)colornum, m_ImageSize); 
		}       
		else if( m_wImageDepth == 16 ) 
		{ 
			m_dwBBitMask    = 0x1F; 
			m_dwGBitMask    = 0x3E0; 
			m_dwRBitMask    = 0x7C00;  
			m_wlowRedBit    = 10;	 
			m_wlowGreenBit  = 5;	 
			m_wlowBlueBit   = 0; 
			m_wNumRedBits   = 5; 	 
			m_wNumGreenBits = 5; 
			m_wNumBlueBits  = 5;	 
			DWORD *Mask  =  (DWORD *)m_lpDibInfo->bmiColors; 
			Mask[0] = m_dwRBitMask; 
			Mask[1] = m_dwGBitMask; 
			Mask[2] = m_dwBBitMask; 
 
			RGBTRIPLE  Pixel3; 
			BYTE      *RGB  = (BYTE * )&colornum; 
			Pixel3.rgbtRed   = RGB[0] / 8; 
			Pixel3.rgbtGreen = RGB[1] / 8; 
			Pixel3.rgbtBlue  = RGB[2] / 8; 
			WORD Pixel2 = Pixel3.rgbtRed<bmiHeader.biSize          = sizeof(BITMAPINFOHEADER); 
		m_lpDibInfo->bmiHeader.biWidth         = width; 
		m_lpDibInfo->bmiHeader.biHeight        = source.m_IsImageDownUp ? height : -height; 
		m_lpDibInfo->bmiHeader.biPlanes        = 1; 
		m_lpDibInfo->bmiHeader.biBitCount      = m_wImageDepth; 
		m_lpDibInfo->bmiHeader.biCompression   = BI_RGB; 
		m_lpDibInfo->bmiHeader.biSizeImage     = m_ImageSize; 
		m_lpDibInfo->bmiHeader.biXPelsPerMeter = 0; 
		m_lpDibInfo->bmiHeader.biYPelsPerMeter = 0; 
		m_lpDibInfo->bmiHeader.biClrUsed       = m_wColorMapNum; 
		m_lpDibInfo->bmiHeader.biClrImportant  = 0; 
	 
		if( m_wImageDepth <= 8 )// create the color table 
		{ 
			for(int i= 0; i< m_wColorMapNum; i++) 
			{ 
				m_lpDibInfo->bmiColors[i] = source.m_lpDibInfo->bmiColors[i]; 
			}  
			BakupColorIndex(); 
		}         
	} 
	GenerateRowAddress(); 
	//下面开始用插值方法来产生放大的图像 
	P_LONG   xx, yy, tx, ty; 
	float    alpha, belta;     
	float   *coef = new float[nScale]; 
 
	for(int i= 0; i< nScale; i++) 
        coef[i] = (float)i / (float)nScale; 
 
    if( m_wImageDepth == 8 ) 
	{ 
		P_BYTE I11, I12, I21, I22, I; 
		for( P_LONG y0 = 0; y0 < SourceH  ; y0++)     
		{ 
			yy = y0 * nScale; 
			ty = y0 + LTp.y; 
			for( P_LONG x0 = 0; x0 < SourceW; x0++)   
			{ 
				xx = x0 * nScale;             
				tx = x0 + LTp.x; 
				 
				I11 = source.RowAddress[ ty ][ tx ]; 
				I12 = source.RowAddress[ ty ][tx+1]; 
				I21 = source.RowAddress[ty+1][ tx ]; 
				I22 = source.RowAddress[ty+1][tx+1]; 
				for(P_LONG j = 0; j < nScale; j ++) 
				{ 
					belta = coef[j]; 
					for( P_LONG i = 0; i <  nScale; i ++) 
					{					 
						alpha = coef[i]; 
						I = (P_BYTE)(  (float)(I11  + (I12-I11) * alpha) * (1.0 - belta) +  
									   (float)(I21  + (I22-I21) * alpha) * belta+0.5); 
						RowAddress[yy+ j][xx+ i] = I; 
					} 
				}				 
			}		 
		} 
		int LineRemain = m_nDibWidth - m_ImageWidth; 
		if(LineRemain) 
		{ 
			for(P_LONG j = 0; j < m_ImageHeight  ; j ++) 
			{ 
				P_BYTE *lp = RowAddress[j] + width-1; 
				P_BYTE gray = *lp++; 
				memset(lp, gray, LineRemain); 
			} 
		} 
	}//end of if(m_wImageDepth==8) 
	else if( m_wImageDepth == 24 ) 
	{ 
		int        g11, g12, g21, g22; 
		RGBTRIPLE  I11, I12, I21, I22, I, *RGBRowAddress; 
 		for( P_LONG y0 = 0; y0 < SourceH; y0 ++)     
		{ 
			yy = y0 * nScale; 
			ty = y0 + LTp.y; 
			 
			for( P_LONG x0 = 0; x0 < SourceW; x0 ++)   
			{ 
				xx = x0 * nScale;             
				tx = x0 + LTp.x; 
 
				I11 = source.GetRGBPixel(tx,   ty ); 
				I12 = source.GetRGBPixel(tx+1, ty); 
				I21 = source.GetRGBPixel(tx,   ty+1); 
				I22 = source.GetRGBPixel(tx+1, ty+1); 
				for(P_LONG j = 0; j < nScale; j ++) 
				{ 
					RGBRowAddress =	(RGBTRIPLE*)(RowAddress[yy+ j]); 
					belta = coef[j]; 
					for( P_LONG i = 0; i <  nScale; i ++) 
					{					 
						alpha = coef[i]; 
						 
						g11 = I11.rgbtRed; 
						g12 = I12.rgbtRed; 
						g21 = I21.rgbtRed; 
						g22 = I22.rgbtRed; 
						I.rgbtRed= (P_BYTE)((float)(g11  + (g12-g11) * alpha) * (1.0 - belta) +  
									        (float)(g21  + (g22-g21) * alpha) * belta+0.5); 
						g11 = I11.rgbtGreen; 
						g12 = I12.rgbtGreen; 
						g21 = I21.rgbtGreen; 
						g22 = I22.rgbtGreen; 
						I.rgbtGreen= (P_BYTE)((float)(g11  + (g12-g11) * alpha) * (1.0 - belta) +  
									          (float)(g21  + (g22-g21) * alpha) * belta+0.5); 
						g11 = I11.rgbtBlue; 
						g12 = I12.rgbtBlue; 
						g21 = I21.rgbtBlue; 
						g22 = I22.rgbtBlue; 
						I.rgbtBlue= (P_BYTE)((float)(g11  + (g12-g11) * alpha) * (1.0 - belta) +  
									         (float)(g21  + (g22-g21) * alpha) * belta+0.5); 
					    RGBRowAddress[xx+ i] = I; 
					} 
				}				 
			} 
		} 
		int LineRemain = m_nDibWidth - m_ImageWidth * 3; 
		if( LineRemain ) 
		{ 
			for(P_LONG j =1; j <= m_ImageHeight  ; j++) 
			{ 
				P_BYTE *lp = RowAddress[j] - 1 - LineRemain; 
				memset(lp, 255, LineRemain); 
			} 
		} 
	} 
	if( coef != NULL ) delete []coef; 
	return TRUE; 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::CreateMicroImg(CImage &source, P_LONG MicroW, P_LONG MicroH) 
{ 
	//还需要加入高彩的放大处理 
	DeleteMe(); 
 
	m_wImageDepth    = source.m_wImageDepth; 
	m_wColorMapNum   = source.m_wColorMapNum;  
 
    m_ImageWidth     = MicroW;	 
    m_ImageHeight    = MicroH;	 
    m_nDibWidth      = (m_ImageWidth* m_wImageDepth/ 8 + 3) & ~3;; 
    m_nDibHeight     = MicroH; 
    m_ImageSize      = m_nDibWidth * m_nDibHeight; 
	 
    m_HSIImageWidth  = (MicroW + 3) & ~3; 
	m_HSIImageHeight = MicroH; 
     
	AllocateMemory(); 
    if( m_lpDibInfo!=NULL && m_lpDibArray != NULL ) //create the bitmap info      
	{   
		m_lpDibInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER); 
		m_lpDibInfo->bmiHeader.biWidth         = MicroW; 
		m_lpDibInfo->bmiHeader.biHeight        = source.m_IsImageDownUp ? MicroH : -MicroH; 
		m_lpDibInfo->bmiHeader.biPlanes        = 1; 
		m_lpDibInfo->bmiHeader.biBitCount      = m_wImageDepth; 
		m_lpDibInfo->bmiHeader.biCompression   = BI_RGB; 
		m_lpDibInfo->bmiHeader.biSizeImage     = m_ImageSize; 
		m_lpDibInfo->bmiHeader.biXPelsPerMeter = 0; 
		m_lpDibInfo->bmiHeader.biYPelsPerMeter = 0; 
		m_lpDibInfo->bmiHeader.biClrUsed       = m_wColorMapNum; 
		m_lpDibInfo->bmiHeader.biClrImportant  = 0; 
	 
		if( m_wImageDepth <= 8 )// create the color table 
		{ 
			for(int i= 0; i< m_wColorMapNum; i++) 
			{ 
				m_lpDibInfo->bmiColors[i] = source.m_lpDibInfo->bmiColors[i]; 
			}  
			BakupColorIndex(); 
		}         
	} 
	GenerateRowAddress(); 
	//下面开始用插值方法来产生缩小的图像 
	P_LONG   x0, y0, xx, yy; 
	float    dx = (float)source.m_ImageWidth/  (float)MicroW; 
	float    dy = (float)source.m_ImageHeight/ (float)MicroH; 
	float    OrgPtx, OrgPty; 
    if( m_wImageDepth == 8 ) 
	{ 
		for(OrgPty = 0, y0 = 0; y0 < MicroH  ; y0++)     
		{			  
			yy = int(OrgPty + 0.5); 
			for(OrgPtx = 0, x0 = 0; x0 < MicroW  ; x0++)   
			{ 
				xx                 = int(OrgPtx + 0.5);             
				RowAddress[y0][x0] = source.RowAddress[ yy ][ xx ]; 
				OrgPtx            += dx; 
			} 
			OrgPty += dy; 
		}		 
	} //end of if(m_wImageDepth==8) 
	else if( m_wImageDepth == 24 ) 
	{ 
		RGBTRIPLE *RGBRowAddress; 
		for(OrgPty = 0, y0 = 0; y0 < MicroH  ; y0++)     
		{ 
			yy = int(OrgPty + 0.5); 
			RGBRowAddress = (RGBTRIPLE *)RowAddress[y0]; 
			for(OrgPtx = 0, x0 = 0; x0 < MicroW  ; x0++)   
			{ 
				xx                = int(OrgPtx + 0.5);             
				RGBRowAddress[x0] = source.GetRGBPixel(xx, yy); 
				OrgPtx           += dx; 
			} 
			OrgPty += dy; 
		}		 
	} //end of if(m_wImageDepth==24) 
	 
	return TRUE; 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::ConvertToGrayImage() 
{ 
	eImageType dImageType = GetImageType(); 
	if( m_wImageDepth ==  IndexGrayImage) return false; 
	 
	P_LONG i, j, GrayImagewidth = (m_ImageWidth + 3) & ~3; 
	BYTE *tempBMP = new BYTE[GrayImagewidth * m_ImageHeight];   
	memset(tempBMP, 0, GrayImagewidth * m_ImageHeight); 
 
	BYTE *lAdd = tempBMP + GrayImagewidth * (m_ImageHeight - 1); 
	RGBTRIPLE   rgbV; 
	for(j= 0; j< m_ImageHeight; j++) 
	{ 
		for(i= 0; i< m_ImageWidth; i++) 
		{ 
			rgbV    = GetRGBPixel(i, j); 
			lAdd[i] =  (rgbV.rgbtBlue+ rgbV.rgbtGreen + rgbV.rgbtRed + 2)/3; 
		} 
		lAdd -= GrayImagewidth; 
	} 
	m_wImageDepth    = 8; 
	m_nDibWidth      = GrayImagewidth; 
	m_nDibHeight     = m_ImageHeight; 
	m_ImageSize      = m_nDibWidth * m_nDibHeight; 
 
	m_wColorMapNum   = GetColorMapNum(m_wImageDepth); 
	m_HSIImageWidth  = (m_ImageWidth + 3) & ~3; 
	m_HSIImageHeight = m_ImageHeight; 
 
	m_bmfHeader.bfType      = DIB_HEADER_MARKER;        // "BM" 
	m_bmfHeader.bfOffBits   = sizeof(BITMAPFILEHEADER) + 
		                      sizeof(BITMAPINFOHEADER) +  
						      m_wColorMapNum * sizeof(RGBQUAD); 
	m_bmfHeader.bfSize      = m_bmfHeader.bfOffBits + m_ImageSize; 
	m_bmfHeader.bfReserved1 = 0; 
	m_bmfHeader.bfReserved2 = 0; 
 
	AllocateMemory(); 
	InitGrayImageInfo(); 
	GenerateRowAddress(); 
	memcpy(m_lpDibArray, tempBMP, m_ImageSize); 
	if( tempBMP!= NULL ) delete[]tempBMP; 
	return true;	 
} 
//*********************************************************** 
 
//*********************************************************** 
void  CImage::GetImageDimensions(LPCTSTR fileName, unsigned int &width,  
							                       unsigned int &height, 
												   unsigned int &Depth) 
{ 
	CString FileName(fileName); 
	if(FileName.Right(3) == "img" ||FileName.Right(3) == "IMG") 
	{ 
		CFile  pReadFile(fileName, CFile::modeRead | CFile::shareCompat); 
		DWORD  dwBitsSize = pReadFile.GetLength(); 
		double multi = sqrt(dwBitsSize) / IMG_FORMAT_BASE_LENGTH; 
 
		width    = IMG_FORMAT_BASE_LENGTH * int(multi); 
		height   = dwBitsSize / width; 
	} 
	else 
	{ 
		FILE    *rf = fopen(fileName, "r"); 
		if ( rf == NULL) return; 
		 
		if(FileName.Right(3) == "bmp" ||FileName.Right(3) == "BMP") 
		{     
			BITMAPFILEHEADER    BMP_Header;  
			BITMAPINFOHEADER    BMP_InfoHeader; 
			fread( (LPSTR)&BMP_Header,     sizeof(BITMAPFILEHEADER), 1, rf ); 
			fread( (LPSTR)&BMP_InfoHeader, sizeof(BITMAPINFOHEADER), 1, rf ); 
			if ( BMP_Header.bfType != DIB_HEADER_MARKER )     
			{ 
				AfxMessageBox("您所指定的不是一个BMP文件!"); 
				return ; 
			} 
			width  = BMP_InfoHeader.biWidth;	 
			height = abs(BMP_InfoHeader.biHeight); 
			Depth  = BMP_InfoHeader.biBitCount; 
		} 
		else if(FileName.Right(3) == "pbm" ||FileName.Right(3) == "PBM") 
		{     
			char    P14[4]; 
			//读出图像的宽度和高度 
			int     w = 0, h = 0; 
			fscanf(rf, "%s\n", P14); 
			if ( (P14[0] != 'P') && (P14[1] != '1'&&P14[1] != '4') ) 
			{ 
				AfxMessageBox("您所指定的不是一个PBM文件!"); 
				return; 
			} 
			fscanf(rf, "%d %d\n", &w, &h);	 
			width  = w;	 
			height = h; 
			Depth  = 8; 
		}  
		else if(FileName.Right(3) == "pgm" ||FileName.Right(3) == "PGM") 
		{ 
			char    P5[4]; 
			fscanf(rf, "%s\n", P5); 
			if ( (P5[0] != 'P') && (P5[1] != '5') )  
			{ 
				AfxMessageBox("您所指定的不是一个PGM文件!"); 
				return; 
			} 
			//读出图像的宽度和高度 
			int     w = 0, h = 0, MaxGray = 255; 
			fscanf(rf, "%d %d\n", &w, &h); 
			fscanf(rf, "%d\n", &MaxGray); 
			width  = w;	 
			height = h; 
			Depth  = 8; 
		} 
		fclose(rf); 
	} 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::ReadImageFromFile(LPCTSTR lpszFileName) 
{ 
    CFile * pReadFile; 
    TRY {  pReadFile = new CFile( lpszFileName, CFile::modeRead | CFile::shareCompat); } 
    CATCH( CFileException, e ) 
    { 
		return false; 
    } 
    END_CATCH 
 
	if( pReadFile == NULL || pReadFile->GetLength( )<54) 
	{ 
		AfxMessageBox("文件类指针或文件格式错误!!!");         
		if( pReadFile != NULL ) 
		{ 
			pReadFile->Close(); delete pReadFile;  pReadFile = NULL; 
		} 
		return false; 
	} 
	else 
	{ 
		BOOL    result = false; 
 		CString FileName(lpszFileName); 
		if(FileName.Right(3) == "img" ||FileName.Right(3) == "IMG") 
		{ 
			result = ReadImageAsIMG( pReadFile); 
		} 
		else if(FileName.Right(3) == "bmp" ||FileName.Right(3) == "BMP") 
		{     
			result = ReadImageAsBMP( pReadFile); 
		} 
		 
		if(pReadFile != NULL) 
		{ 
			pReadFile->Close(); delete pReadFile;  pReadFile = NULL; 
		} 
		return result; 
	} 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::SaveImageToFile(LPCTSTR lpszFileName) 
{ 
    if(m_lpDibArray==NULL) return FALSE; 
    CFile * pWriteFile = NULL; 
    TRY {pWriteFile = new CFile( lpszFileName, CFile::modeCreate | CFile::modeWrite); } 
    CATCH( CFileException, e ) 
    { 
        AfxMessageBox(" 文件错误"); 
		if(pWriteFile != NULL) 
		{ 
			pWriteFile->Close(); delete pWriteFile;  pWriteFile = NULL; 
		} 
        THROW_LAST(); 
    } 
    END_CATCH 
 
	BOOL    result = false; 
    CString FileName(lpszFileName); 
    if(FileName.Right(3) == "img" || FileName.Right(3) == "IMG") 
    { 
        result = SaveImageAsIMG( pWriteFile ); 
    } 
    else if(FileName.Right(3) == "bmp" || FileName.Right(3) == "BMP") 
    {     
        result = SaveImageAsBMP( pWriteFile ); 
    } 
	 
    if( pWriteFile != NULL ) 
	{ 
		pWriteFile->Close(); delete pWriteFile;  pWriteFile = NULL; 
	} 
 
    return true; 
} 
 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::ReadImageAsBMP(CFile * pReadFile) 
{ 
    pReadFile->SeekToBegin();          // Set the file pointer to the begin of the file 
 
    //Check if the file header is "BM" 
	if ((pReadFile->Read((LPSTR)&m_bmfHeader, sizeof(BITMAPFILEHEADER)) != 
		 sizeof(BITMAPFILEHEADER)) || (m_bmfHeader.bfType != DIB_HEADER_MARKER))     
    { 
        AfxMessageBox("您所指定的不是一个BMP文件!"); 
        return FALSE; 
    }   
    BITMAPINFOHEADER    bmiHeader; 
	pReadFile->Read((LPSTR)&bmiHeader, sizeof(BITMAPINFOHEADER)); 
     
    m_ImageWidth     = bmiHeader.biWidth;	 
    m_ImageHeight    = abs(bmiHeader.biHeight); 
	m_wImageDepth    = bmiHeader.biBitCount; 
    m_nDibWidth      = (m_ImageWidth* m_wImageDepth/ 8 + 3) & ~3; 
    m_nDibHeight     = m_ImageHeight; 
	m_ImageSize      = m_nDibWidth * m_nDibHeight; 
    m_wColorMapNum   = GetColorMapNum(m_wImageDepth); 
    m_HSIImageWidth  = (m_ImageWidth + 3) & ~3; 
	m_HSIImageHeight = m_ImageHeight; 
	 
	if(bmiHeader.biCompression != BI_BITFIELDS&&bmiHeader.biCompression != BI_RGB) 
	{ 
		AfxMessageBox("不支持RLE4 or RLE8 压缩格式"); 
		return FALSE; 
	} 
	if(bmiHeader.biCompression == BI_BITFIELDS&&(m_bmfHeader.bfOffBits-54)==12) 
		AllocateMemory(TRUE); 
	else 
		AllocateMemory();  
 
	if(m_lpDibInfo!=NULL) //create the bitmap info      
	{ 
		m_lpDibInfo->bmiHeader = bmiHeader; 
 
		if(m_wImageDepth<=8&&m_wColorMapNum>0) 
			pReadFile->Read((LPSTR)m_lpDibInfo->bmiColors, m_wColorMapNum* sizeof(RGBQUAD)); 
		BakupColorIndex(); 
	} 
	GenerateRowAddress(); 
 
	m_IsExistRGBMask = m_Is565RGBImage = FALSE; 
	if(m_wImageDepth==16) 
	{ 
		m_dwBBitMask    = 0x1F; 
		m_dwGBitMask    = 0x3E0; 
		m_dwRBitMask    = 0x7C00;  
		m_wlowRedBit    = 10;	 
		m_wlowGreenBit  = 5;	 
		m_wlowBlueBit   = 0; 
		m_wNumRedBits   = 5; 	 
		m_wNumGreenBits = 5; 
		m_wNumBlueBits  = 5;	 
		 
		if(bmiHeader.biCompression == BI_BITFIELDS && (m_bmfHeader.bfOffBits-54)==12) 
		{ 
			pReadFile->Read((LPSTR)m_lpDibInfo->bmiColors, 12); 
			m_IsExistRGBMask = true; 
			DWORD *Mask  =  (DWORD *)m_lpDibInfo->bmiColors; 
			m_dwRBitMask = Mask[0]; 
			m_dwGBitMask = Mask[1]; 
			m_dwBBitMask = Mask[2]; 
			if(m_dwGBitMask != 0x3E0 ) 
			{ 
				m_Is565RGBImage = TRUE; 
				m_wlowRedBit    = 11; 
				m_wNumGreenBits = 6; 
			}			  
		} 
	} 
	else if(m_wImageDepth==32) 
	{ 
		m_dwBBitMask    = 0xFF; 
		m_dwGBitMask    = 0xFF00; 
		m_dwRBitMask    = 0xFF0000;  
		m_wlowRedBit    = 16;	 
		m_wlowGreenBit  = 8;	 
		m_wlowBlueBit   = 0; 
		m_wNumRedBits   = 8; 	 
		m_wNumGreenBits = 8; 
		m_wNumBlueBits  = 8;	 
 
		if(bmiHeader.biCompression == BI_BITFIELDS && (m_bmfHeader.bfOffBits-54)==12) 
		{ 
			pReadFile->Read((LPSTR)m_lpDibInfo->bmiColors,12); 
			m_IsExistRGBMask = TRUE; 
			DWORD *Mask  =  (DWORD *)m_lpDibInfo->bmiColors; 
			m_dwBBitMask = Mask[0]; 
			m_dwGBitMask = Mask[1]; 
			m_dwRBitMask = Mask[2];			  
		} 
	} 
	 
	pReadFile->Seek(m_bmfHeader.bfOffBits, CFile::begin); 
	if(m_lpDibArray!=NULL) 
	{ 
		TRY	{ pReadFile->ReadHuge(m_lpDibArray, m_ImageSize); } 
		CATCH(CFileException, e) 
		{ 
			AfxMessageBox("读文件错误"); 
			THROW_LAST(); 
		}	  	                   
		END_CATCH 
	}		 
    return true; 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::SaveImageAsBMP(CFile * pSaveFile) 
{ 
    if( pSaveFile == NULL||m_lpDibArray==NULL ) 
    { 
        AfxMessageBox("文件类指针或图像数据错误!"); 
        return FALSE; 
    }  
	m_bmfHeader.bfType      = DIB_HEADER_MARKER; 
	m_bmfHeader.bfOffBits   = sizeof(BITMAPFILEHEADER) + 
							  m_lpDibInfo->bmiHeader.biSize + 
							  m_wColorMapNum * sizeof(RGBQUAD); 
	m_bmfHeader.bfSize      = m_bmfHeader.bfOffBits + m_ImageSize; 
	m_bmfHeader.bfReserved1 = 0; 
	m_bmfHeader.bfReserved2 = 0; 
	TRY 
	{   // Write the file header 
		pSaveFile->Write( (LPSTR)&m_bmfHeader, sizeof(BITMAPFILEHEADER)); 
		// write bmp info header. 
	    pSaveFile->Write( (LPSTR)&(m_lpDibInfo->bmiHeader), sizeof(BITMAPINFOHEADER)); 
        //Write palette info 
		if(m_wColorMapNum) 
			pSaveFile->Write( (LPSTR)m_lpDibInfo->bmiColors, m_wColorMapNum*sizeof(RGBQUAD)); 
		else if(m_IsExistRGBMask) 
			pSaveFile->Write( (LPSTR)m_lpDibInfo->bmiColors, 3*sizeof(RGBQUAD));  
		// Write the DIB  bits 
		pSaveFile->WriteHuge(m_lpDibArray, m_ImageSize); 
	} 
	CATCH (CFileException, e) 
	{ 
        AfxMessageBox(" 存文件时出错"); 
		THROW_LAST(); 
	} 
	END_CATCH 
 
	return TRUE; 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::ReadImageAsIMG(CFile * pReadFile) 
{ 
	//get length of DIB in bytes for use when reading 
	DWORD  dwBitsSize = pReadFile->GetLength(); 
    double multi=sqrt(dwBitsSize)/IMG_FORMAT_BASE_LENGTH; 
 
	m_ImageWidth    = IMG_FORMAT_BASE_LENGTH*int(multi); 
    m_ImageHeight   = dwBitsSize / m_ImageWidth; 
 
	if( dwBitsSize % m_ImageWidth  ) 
	{ 
		AfxMessageBox(" Not IMG format or file error"); 
		return FALSE;                               
	} 
     
	m_wImageDepth   = 8; 
	m_wColorMapNum  = GetColorMapNum(m_wImageDepth); 
	m_nDibWidth     = (m_ImageWidth* m_wImageDepth/ 8 + 3) & ~3; 
	m_nDibHeight    = m_ImageHeight; 
	m_ImageSize     = m_nDibWidth * m_nDibHeight; 
	 
	AllocateMemory(); 
    InitGrayImageInfo(); 
	GenerateRowAddress(); 
	 
    TRY //Go read the bits. 
    {                      
  	    pReadFile->ReadHuge(m_lpDibArray, dwBitsSize); 
    } 
    CATCH(CFileException, e) 
    { 
        AfxMessageBox("读文件错误"); 
        THROW_LAST(); 
	}	  	                   
	END_CATCH 
 
	return TRUE; 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::SaveImageAsIMG(CFile * pSaveFile) 
{	 
    if( pSaveFile == NULL||m_lpDibArray==NULL )//Check if the file pointer is valid 
    { 
        AfxMessageBox("文件类指针或图像数据错误!"); 
        return FALSE; 
    }  
     
	TRY 
	{	// Write the IMG  bits 
		pSaveFile->WriteHuge(m_lpDibArray, m_ImageSize); 
	} 
	CATCH (CFileException, e) 
	{ 
        AfxMessageBox(" 存文件时出错"); 
		THROW_LAST(); 
	} 
	END_CATCH 
 
	return TRUE; 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::ShowCurrentImage(CDC *pMpDc,CRect ShowRect) 
{ 
	BOOL   bSuccess=FALSE;      // Success or fail flag	 
	// Check for valid image data* 
	if( m_lpDibArray == NULL)         
		return  bSuccess;   
	UINT Mode; 
	if(m_lpDibInfo->bmiHeader.biCompression == BI_RGB) 
		Mode = DIB_RGB_COLORS; 
	else if(m_lpDibInfo->bmiHeader.biCompression == BI_BITFIELDS) 
		Mode = DIB_PAL_COLORS; 
	// Make sure to use the stretching mode best for color pictures  
	pMpDc->SetStretchBltMode(COLORONCOLOR); 
     
	BOOL Show1to1 = fabs(m_fScale - 1.0)<0.05 && 
		            abs(ShowRect.Width() - m_ImageWidth)<5 && 
					abs(ShowRect.Height() - m_ImageHeight)<5;//*/ 
    if(Show1to1) 
	{ 
  		bSuccess = ::SetDIBitsToDevice(pMpDc->m_hDC,       // hDC 
  									   ShowRect.left,	   //DestX 
  									   ShowRect.top,	   //DestY 
  									   (int)m_ImageWidth,  //最好是图像的宽度 
									   (int)m_ImageHeight, //最好是图像的高度 
									   0,                  //SrcX 
									   0,                  //SrcY 
									   0,                  //nStartScan 
									   (int)m_nDibHeight,  //nNumScans 
									   m_lpDibArray,       //lpBits 
									   m_lpDibInfo,		   //lpBitsInfo 
									   Mode);    //wUsage //*/ 
	} 
	else 
	{ 
		double tmpscalex = ShowRect.Width()/(double)m_ImageWidth; 
		double tmpscaley = ShowRect.Height()/(double)m_ImageHeight; 
		if(tmpscalexm_hDC,           // hDC 
								   ShowRect.left,          // DestX 
								   ShowRect.top,           // DestY 
								   ShowRect.Width(),	   // nDestWidth 
								   ShowRect.Height(),	   // nDestHeight 
								   0,	  	               // SrcX 
								   0,                      // SrcY 
								   (int)m_ImageWidth,      // wSrcWidth 
								   (int)m_ImageHeight,     // wSrcHeight 
								   m_lpDibArray,           // lpBits 
								   m_lpDibInfo,            // lpBitsInfo 
								   Mode,         // wUsage 
								   SRCCOPY);               // dwROP//*/ 
	} 
	return bSuccess; 
}   
BOOL CImage::ShowCurrentImage(CDC *pMpDc,CPoint LTp, CPoint RBp) 
{ 
	return ShowCurrentImage( pMpDc, CRect(LTp,RBp) ); 
} 
BOOL CImage::ShowCurrentImage(CDC *pMpDc,int x1, int y1, int x2, int y2) 
{ 
	return ShowCurrentImage( pMpDc, CRect(x1,y1,x2,y2) ); 
} 
//*********************************************************** 
 
//*********************************************************** 
BOOL CImage::ShowPartialImage(CDC *pMpDc,CRect ShowRect,CPoint LTp,CPoint RBp, BOOL Is1to1) 
{ 
#ifdef _DEBUG 
	if(!CheckRect(LTp,RBp)||m_lpDibArray == NULL) 
	{ 
		AfxMessageBox("下标越界!!!"); 
		AfxAbort(); 
	} 
#endif   
	BOOL   bSuccess=FALSE;      // Success/fail flag	 
	// Make sure to use the stretching mode best for color pictures  
	pMpDc->SetStretchBltMode(COLORONCOLOR); 
 
    int width   = RBp.x - LTp.x + 1; 
    int height  = RBp.y - LTp.y + 1; 
	if(Is1to1) 
	{ 
		bSuccess = ::SetDIBitsToDevice(pMpDc->m_hDC,       // hDC 
  									   ShowRect.left,		   // DestX 
									   ShowRect.top,		   // DestY 
								       ShowRect.Width(),	   // nDestWidth 
								       ShowRect.Height(),	   // nDestHeight 
									   LTp.x,                  //SrcX 
									   m_nDibHeight - RBp.y -1,   //SrcY 
									   0,                       //nStartScan 
									   (int)m_nDibHeight- RBp.y - 1 + height,  //nNumScans 
									   m_lpDibArray,       //lpBits 
									   m_lpDibInfo,		   //lpBitsInfo 
									   DIB_RGB_COLORS);    //wUsage //*/ 
	} 
	else 
	{ 
  		bSuccess = ::StretchDIBits(pMpDc->m_hDC,           // hDC 
								   ShowRect.left,		   // DestX 
								   ShowRect.top,		   // DestY 
								   ShowRect.Width(),	   // nDestWidth 
								   ShowRect.Height(),	   // nDestHeight 
								   LTp.x,		           // SrcX 
								   m_ImageHeight - RBp.y -1,// SrcY 
								   width,                  // wSrcWidth 
								   height,                 // wSrcHeight 
								   m_lpDibArray,           // lpBits 
								   m_lpDibInfo,            // lpBitsInfo 
								   DIB_RGB_COLORS,         // wUsage 
								   SRCCOPY);               // dwROP	 
	} 
    return bSuccess; 
} 
//*********************************************************** 
 
//*********************************************************** 
void CImage::SelectChannel(DWORD channel) 
{ 
#ifdef _DEBUG 
	if(m_lpDibArray     == NULL)   
	{ 
		AfxMessageBox("下标越界!!!"); 
		AfxAbort(); 
	} 
#endif 
	static BOOL HaveShowChannel = FALSE; // 是否已经显示过单色分量图 
	if(!HaveShowChannel) 
	{ 
		BackUp(); 
		HaveShowChannel=true; 
	} 
	else 
	{ 
		ImgSwap(); 
		BackUp(); 
	} 
     
	switch(channel) 
	{ 
	    case  REDCOMPONENT:  
		{ 
			if( m_wImageDepth == 24 ) 
			{ 
				for(int j= 0; j< m_ImageHeight; j++) 
				{ 
					RGBTRIPLE* pixptr = (RGBTRIPLE*)(RowAddress[j]); 
					for(int i= 0; i< m_ImageWidth; i++) 
					{ 
						pixptr[i].rgbtGreen = pixptr[i].rgbtRed; 
						pixptr[i].rgbtBlue  = pixptr[i].rgbtRed; 
					} 
				} 
			}	 
			break; 
		} 
		case  GREENCOMPONENT: 
		{ 
			if( m_wImageDepth == 24 ) 
			{ 
				for(int j= 0; j< m_ImageHeight; j++) 
				{ 
					RGBTRIPLE* pixptr = (RGBTRIPLE*)(RowAddress[j]); 
					for(int i= 0; i< m_ImageWidth; i++) 
					{ 
						pixptr[i].rgbtRed  = pixptr[i].rgbtGreen; 
						pixptr[i].rgbtBlue = pixptr[i].rgbtGreen; 
					} 
				} 
			}	 
			break; 
		} 
		case  BLUECOMPONENT:  
		{ 
			if( m_wImageDepth == 24) 
			{ 
				for(int j= 0; j< m_ImageHeight; j++) 
				{ 
					RGBTRIPLE* pixptr = (RGBTRIPLE*)(RowAddress[j]); 
					for(int i= 0; i< m_ImageWidth; i++) 
					{ 
						pixptr[i].rgbtGreen = pixptr[i].rgbtBlue; 
						pixptr[i].rgbtRed   = pixptr[i].rgbtBlue; 
					} 
				} 
			}	 
			break; 
		} 
		case  REDCOMPONENT | GREENCOMPONENT:  
		{ 
			if( m_wImageDepth == 24 ) 
			{ 
				for(int j= 0; j< m_ImageHeight; j++) 
				{ 
					RGBTRIPLE* pixptr = (RGBTRIPLE*)(RowAddress[j]); 
					for(int i= 0; i< m_ImageWidth; i++) 
					{ 
						pixptr[i].rgbtBlue  = 0; 
					}  
				} 
			}	 
			break; 
		} 
		case  GREENCOMPONENT | BLUECOMPONENT: 
		{ 
			if( m_wImageDepth == 24) 
			{ 
				for(int j= 0; j< m_ImageHeight; j++) 
				{ 
					RGBTRIPLE* pixptr = (RGBTRIPLE*)(RowAddress[j]); 
					for(int i= 0; i< m_ImageWidth; i++) 
					{ 
						pixptr[i].rgbtRed =0 ; 
					} 
				} 
			}	 
			break; 
		} 
		case  BLUECOMPONENT | REDCOMPONENT:  
		{ 
			if( m_wImageDepth == 24) 
			{ 
				for(int j= 0; j< m_ImageHeight; j++) 
				{ 
					RGBTRIPLE* pixptr = (RGBTRIPLE*)(RowAddress[j]); 
					for(int i= 0; i< m_ImageWidth; i++) 
					{ 
						pixptr[i].rgbtGreen = 0; 
					}  
				} 
			}	 
			break; 
		} 
		case  HUEIMAGE:  
		{ 
			CreateHSIImage( HUEIMAGE ); 
			if( m_wImageDepth == 24) 
			{ 
				for(int j= 0, k= 0; j< m_ImageHeight; j++, k += m_HSIImageWidth) 
				{ 
					RGBTRIPLE* pixptr = (RGBTRIPLE*)( RowAddress[j] ); 
 
					for(int i= 0; i< m_ImageWidth; i++) 
					{ 
						pixptr[i].rgbtRed   = 
						pixptr[i].rgbtBlue  = 
						pixptr[i].rgbtGreen = m_lpHSIArray[k + i]; 
					}  
				} 
			}	 
			break; 
		} 
		case  SATURATIONIMAGE:  
		{ 
			CreateHSIImage( SATURATIONIMAGE ); 
			if( m_wImageDepth == 24 ) 
			{ 
				for(int j= 0, k= 0; j< m_ImageHeight; j++, k += m_HSIImageWidth) 
				{ 
					RGBTRIPLE* pixptr=(RGBTRIPLE*)( RowAddress[j] ); 
					for(int i= 0; i< m_ImageWidth; i++) 
					{ 
						pixptr[i].rgbtRed   = 
						pixptr[i].rgbtBlue  = 
						pixptr[i].rgbtGreen = m_lpHSIArray[k + i]; 
					}  
				} 
			}	 
			break; 
		} 
		case  INTENSITYIMAGE:  
		{ 
			CreateHSIImage( INTENSITYIMAGE ); 
			if( m_wImageDepth == 24 ) 
			{ 
				for(int j= 0, k= 0; j< m_ImageHeight; j++, k += m_HSIImageWidth) 
				{ 
					RGBTRIPLE* pixptr = (RGBTRIPLE*)( RowAddress[j] ); 
					for(int i= 0; i< m_ImageWidth; i++) 
					{ 
						pixptr[i].rgbtRed   = 
						pixptr[i].rgbtBlue  = 
						pixptr[i].rgbtGreen = m_lpHSIArray[k + i]; 
					}  
				} 
			}	 
			break; 
		} 
	} 
} 
//*********************************************************** 
 
//*********************************************************** 
void CImage::BackUp() 
{ 
	if( m_lpDibArrayBuff == NULL) 
	{ 
	    NewBuffer();           
    }   	 
    memcpy(m_lpDibArrayBuff, m_lpDibArray, m_ImageSize); 
} 
//*********************************************************** 
 
//*********************************************************** 
void CImage::ImgSwap() 
{ 
	if(m_lpDibArray     == NULL)  return; 
	if(m_lpDibArrayBuff == NULL)  BackUp(); 
 
	P_BYTE *tmpImgPt = m_lpDibArray; 
	m_lpDibArray     = m_lpDibArrayBuff; 
	m_lpDibArrayBuff = tmpImgPt; 
	tmpImgPt         = NULL; 
 
	GenerateRowAddress(); 
} 
//*********************************************************** 
 
//*********************************************************** 
void CImage::CreateHSIImage(DWORD dwType) 
{ 
	if( m_lpHSIArray == NULL ) NewHSIImg(); 
#ifdef _DEBUG 
	if( m_wImageDepth != 24 || m_lpHSIArray == NULL ) 
	{  
		AfxMessageBox("下标越界或图像色彩不对!!!"); 
		AfxAbort(); 
	}  
#endif 
	//static  DWORD OldType = 0; 
	//double   dRED, dGREEN, dBLUE; 
	P_LONG   i, j; 
    P_BYTE  *rgb;    
    P_BYTE  *Line = m_lpHSIArray; 
 
    switch( dwType ) 
	{ 
	    case  HUEIMAGE:  
		{ 
			//	Hue = (P_BYTE)( atan2( 0.7071 * (dGREEN - dBLUE), 0.816496 * dRED - 0.40824 * (dGREEN + dBLUE) )  
			//                 * 90.0 * 2.0 / 3.1415926 * 255.0 / 360.0); 
			double temp = 90.0 * 2.0 / 3.1415926 * 255.0 / 360.0; 
			double table1[512], table2[512], table3[512]; 
			P_BYTE tmpr, tmpg, tmpb;   
			for( j= 0; j< 512; j++ ) 
			{ 
				table1[j] =  0.7071 * (j-255); 
				table2[j] =  0.816496 * j; 
				table3[j] =  0.40824 * j; 
			} 
			for( j= 0; j< m_HSIImageHeight; j++, Line += m_HSIImageWidth) 
			{				 
				rgb  = RowAddress[j]; 
				for(i=0; i>4; 
			rv            = ColorIndex[index];  
			break; 
		} 
		case  8: 
		{ 
			int    index = RowAddress[y][x]; 
			rv           = ColorIndex[index];  
			break; 
		} 
		case 16: 
		{ 
			WORD *pixptr = (WORD*)RowAddress[y]; 
			WORD  temp   = pixptr[x]; 
			rv.rgbtRed   = (P_BYTE)( (temp&m_dwRBitMask) >> m_wlowRedBit );  
			rv.rgbtGreen = (P_BYTE)( (temp&m_dwGBitMask) >> m_wlowGreenBit ); 
			rv.rgbtBlue  = (P_BYTE)( (temp&m_dwBBitMask) ); 
			break; 
		} 
		case 24:  
		{ 
			RGBTRIPLE* pixptr = (RGBTRIPLE*)RowAddress[y]; 
			rv                = pixptr[x]; 
			break; 
		} 
		case 32:  
		{ 
			DWORD *pixptr = (DWORD*)RowAddress[y]; 
			DWORD temp    = pixptr[x]; 
			rv.rgbtRed    = (P_BYTE)( (temp&m_dwRBitMask) >> m_wlowRedBit );  
			rv.rgbtGreen  = (P_BYTE)( (temp&m_dwGBitMask) >> m_wlowGreenBit ); 
			rv.rgbtBlue   = (P_BYTE)( temp&m_dwBBitMask ); 
			break; 
		} 
	} 
	return rv; 
} 
//*********************************************************** 
 
//*********************************************************** 
void CImage::SetRGBPixel(P_LONG x, P_LONG y,RGBTRIPLE color) 
{ 
#ifdef _DEBUG 
	if(!CheckPoint(x,y)||m_lpDibArray==NULL) 
	{ 
		AfxMessageBox("下标越界或图像色彩不对!!!"); 
		AfxAbort(); 
	} 
#endif   
    switch(m_wImageDepth) 
    { 
		case  8: 
		{ 
			int       index  = RowAddress[y][x]; 
			RowAddress[y][x] = (color.rgbtRed + color.rgbtGreen + color.rgbtBlue)/ 3;  
			break; 
		} 
		case 16: 
		{ 
			WORD *pixptr = (WORD*)RowAddress[y]; 
			WORD  temp   = color.rgbtRed<> 8; 
	rv.rgbtBlue  = (P_BYTE) (color&0x00FF0000) >> 16; 
    SetRGBPixel(x, y, rv); 
} 
 
//*********************************************************** 
 
//*********************************************************** 
P_BYTE CImage::GetGrayV(P_LONG x, P_LONG y) 
{ 
#ifdef _DEBUG 
	if(!CheckPoint(x,y)||m_wImageDepth!=8||m_lpDibArray==NULL) 
	{ 
		AfxMessageBox("下标越界或非灰度图像!!!"); 
		AfxAbort(); 
	} 
#endif   
    return RowAddress[y][x]; 
} 
 
P_BYTE CImage::GetGrayV(double x, double y) 
{ 
	int		ix = int(x); 
	int		iy = int(y); 
	double  dx = x - ix; 
	double  dy = y - iy; 
 
	if( ix < 0)	 
	{ 
		ix = 0; 
	} 
	else if( ix >= (m_ImageWidth-1) ) 	 
	{ 
		ix = m_ImageWidth - 2; 
	} 
 
	if( iy < 0) 
	{ 
		iy = 0; 
	} 
	else if( iy >= (m_ImageHeight- 1) ) 
	{ 
		iy = m_ImageHeight - 2; 
	} 
	 
	BYTE I11, I12, I21, I22; 
	int  I; 
	I11 = RowAddress[ iy ][ ix ]; 
	I12 = RowAddress[ iy ][ix+1]; 
	I21 = RowAddress[iy+1][ ix ]; 
	I22 = RowAddress[iy+1][ix+1]; 
	I = (int)(  (float)(I11  + (I12-I11) * dx) * (1.0 - dy) +  
			    (float)(I21  + (I22-I21) * dx) * dy + 0.5); 
	return I>255 ? 255 : BYTE(I); 
} 
//*********************************************************** 
  
//*********************************************************** 
void CImage::SetGrayV(P_LONG x, P_LONG y,P_BYTE gray) 
{ 
#ifdef _DEBUG 
	if(!CheckPoint(x,y)||m_wImageDepth!=8||m_lpDibArray==NULL) 
	{ 
		AfxMessageBox("下标越界或非灰度图像!!!"); 
		AfxAbort(); 
	} 
#endif   
	RowAddress[y][x] = gray; 
} 
//*********************************************************** 
 
//*********************************************************** 
P_BYTE CImage::GetXYHueValue(P_LONG x, P_LONG y) 
{  
#ifdef _DEBUG 
	if(!CheckPoint(x,y)||m_wImageDepth!=24||m_lpHSIArray==NULL) 
	{ 
		AfxMessageBox("下标越界或非灰度图像!!!"); 
		AfxAbort(); 
	} 
#endif   
	P_LONG y1 = m_HSIImageHeight - 1 - y; 
	return m_lpHSIArray[y1 * m_HSIImageWidth + x];     
} 
//*********************************************************** 
 
//*********************************************************** 
void  CImage::ImageInfo() 
{ 
	CString msg; 
	msg.Format("图像宽度: %5d\n图像高度: %5d\n数据宽度: %5d\n数据高度: %5d\n像素深度: %5d\n",m_ImageWidth,m_ImageHeight,m_nDibWidth,m_nDibHeight,m_wImageDepth); 
	eImageType dImageType = GetImageType(); 
	switch(dImageType) 
    { 
        case  BinaryImage:  
			{ 
				msg+="颜色数目:    2\n图像类型: 二值图像"; 
				break; 
			} 
        case  FourBitsImage: 
			{ 
				msg+="颜色数目:     16\n图像类型: 4位彩色值图像"; 
				break; 
			} 
        case  IndexColorImage: 
			{ 
				msg+="颜色数目:   256\n图像类型: 8位彩色图像"; 
				break; 
			} 
		case  IndexGrayImage: 
			{ 
				msg+="颜色数目:   256\n图像类型: 8位灰度图像"; 
				break; 
			} 
        case  HighColorImage:  
			{ 
				if(m_Is565RGBImage) 
					msg+="颜色数目:    64K\n图像类型: 16位图像(565)"; 
				else 
					msg+="颜色数目:    64K\n图像类型: 16位图像(555)"; 
				break; 
			} 
        case  TrueColorImage:  
			{ 
				msg+="颜色数目:   16M\n图像类型: 24位彩色图像"; 
				break; 
			} 
		case  UltraColorImage: 
			{ 
				msg+="颜色数目:    4G\n图像类型: 32位彩色图像"; 
				break; 
			} 
    }  
	AfxMessageBox(msg); 
} 
//*********************************************************** 
 
//*********************************************************** 
WORD CImage::GetColorMapNum(int Depth) 
{ 
	switch(Depth) 
    { 
        case  1: return 2; 
        case  4: return 16; 
        case  8: return 256; 
        default: return 0; 
    }    
} 
//*********************************************************** 
 
//*********************************************************** 
eImageType CImage::GetImageType() 
{ 
	switch(m_wImageDepth) 
    { 
        case  1: return BinaryImage; 
        case  4: return FourBitsImage; 
        case  8:  
			{ 
				int IsColorImage = 0; 
				for(int gray= 0; gray < COLORCOUNT; gray++) 
				{ 
					P_BYTE tr, tg, tb; 
					tr = m_lpDibInfo->bmiColors[gray].rgbBlue; 
					tg = m_lpDibInfo->bmiColors[gray].rgbGreen; 
					tb = m_lpDibInfo->bmiColors[gray].rgbRed; 
					BOOL bt =!( (tr==tg)&&(tg==tb)&&(tb==tr) ); 
					if( bt )  
					{  
						IsColorImage=1; 
						break; 
					} 
				}     
				if(IsColorImage) 
					return IndexColorImage; 
				else 
					return IndexGrayImage; 
			} 
        case 16: return HighColorImage; 
        case 24: return TrueColorImage; 
		case 32: return UltraColorImage; 
		default: return IllegalImage; 
    }    
} 
//*********************************************************** 
 
//*********************************************************** 
void  CImage::InitTrueColorInfo() 
{ 
	if( m_lpDibInfo != NULL ) 
	{ 
		m_lpDibInfo->bmiHeader.biSize			= sizeof(BITMAPINFOHEADER); 
		m_lpDibInfo->bmiHeader.biWidth			= m_ImageWidth; 
		m_lpDibInfo->bmiHeader.biHeight			= m_ImageHeight; 
		m_lpDibInfo->bmiHeader.biPlanes			= 1; 
		m_lpDibInfo->bmiHeader.biBitCount       = 24; 
		m_lpDibInfo->bmiHeader.biCompression    = BI_RGB; 
		m_lpDibInfo->bmiHeader.biSizeImage		= m_ImageSize; 
		m_lpDibInfo->bmiHeader.biXPelsPerMeter  = 0; 
		m_lpDibInfo->bmiHeader.biYPelsPerMeter  = 0; 
		m_lpDibInfo->bmiHeader.biClrUsed		= m_wColorMapNum; 
		m_lpDibInfo->bmiHeader.biClrImportant   = 0; 
	} 
}  
//*********************************************************** 
 
//*********************************************************** 
void  CImage::InitGrayImageInfo() 
{ 
	if( m_lpDibInfo != NULL ) 
	{   
		m_lpDibInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER); 
		m_lpDibInfo->bmiHeader.biWidth         = m_ImageWidth; 
		m_lpDibInfo->bmiHeader.biHeight        = m_ImageHeight; 
		m_lpDibInfo->bmiHeader.biPlanes        = 1; 
		m_lpDibInfo->bmiHeader.biBitCount      = 8; 
		m_lpDibInfo->bmiHeader.biCompression   = BI_RGB; 
		m_lpDibInfo->bmiHeader.biSizeImage     = m_ImageSize; 
		m_lpDibInfo->bmiHeader.biXPelsPerMeter = 0; 
		m_lpDibInfo->bmiHeader.biYPelsPerMeter = 0; 
		m_lpDibInfo->bmiHeader.biClrUsed       = m_wColorMapNum; 
		m_lpDibInfo->bmiHeader.biClrImportant  = 0; 
	 
		if( m_wImageDepth == 8)// create the color table 
		{ 
			for(int i= 0;i bmiColors[i].rgbBlue     = (P_BYTE)i; 
				m_lpDibInfo->bmiColors[i].rgbGreen    = (P_BYTE)i; 
				m_lpDibInfo->bmiColors[i].rgbRed      = (P_BYTE)i; 
				m_lpDibInfo->bmiColors[i].rgbReserved = 0; 
			}  
			BakupColorIndex(); 
		}         
	} 
} 
//*********************************************************** 
  
//*********************************************************** 
BOOL  CImage::BakupColorIndex() 
{ 
	if( m_wImageDepth <= 8 ) 
	{ 
		for(int i= 0; i< m_wColorMapNum; i++) 
		{ 
			ColorIndex[i].rgbtBlue  = m_lpDibInfo->bmiColors[i].rgbBlue; 
			ColorIndex[i].rgbtGreen = m_lpDibInfo->bmiColors[i].rgbGreen; 
			ColorIndex[i].rgbtRed   = m_lpDibInfo->bmiColors[i].rgbRed;	 
		} 
		return true;			 
	} 
	return false; 
} 
void CImage::GenerateRowAddress() 
{ 
	if( RowAddress != NULL )  
	{ 
		delete []RowAddress; 
		RowAddress = NULL; 
	} 
	RowAddress = new P_BYTE*[m_ImageHeight]; 
 
	m_IsImageDownUp = m_lpDibInfo->bmiHeader.biHeight > 0; 
 
	if( m_IsImageDownUp ) 
	{ 
		RowAddress[m_nDibHeight-1] = m_lpDibArray; 
		for(int i= m_nDibHeight- 2; i>=0 ; i--) 
		{ 
			RowAddress[i] = RowAddress[i+1] + m_nDibWidth; 
		} 
	} 
	else 
	{ 
		RowAddress[0] = m_lpDibArray; 
		for(int i= 1; i< m_nDibHeight; i++) 
		{ 
			RowAddress[i] = RowAddress[i-1] + m_nDibWidth; 
		} 
	} 
} 
//*********************************************************** 
 
//*********************************************************** 
void CImage::AllocateMemory(BOOL IsExistRGBMask) 
{ 
	DeleteMe(); 
	m_lpDibArray = new P_BYTE[m_ImageSize]; 
	memset(m_lpDibArray, 0, m_ImageSize); 
	if(m_lpDibArray == NULL)  AfxThrowMemoryException(); 
	 
	//为m_hDibInfo图像信息头分配内存 
	DWORD DibInfoSize; 
	if(!IsExistRGBMask) 
	{		 
		DibInfoSize = m_wColorMapNum*sizeof(RGBQUAD) + sizeof(BITMAPINFOHEADER); 
	} 
	else  
	{ 
		DibInfoSize = 3* sizeof(DWORD) + sizeof(BITMAPINFOHEADER); 
	} 
	 
	m_pUseful = new P_BYTE[DibInfoSize]; 
	if ( m_pUseful == NULL) 
	{ 
		ReleaseDibArray(); 
		AfxThrowMemoryException(); 
	} 
	m_lpDibInfo = (LPBITMAPINFO)m_pUseful;	 
} 
//*********************************************************** 
 
//*********************************************************** 
void   CImage::ReleaseCopyHandle() 
{ 
	if( m_hDIB != NULL ) 
    { 
		GlobalUnlock( m_hDIB ); 
        GlobalFree( m_hDIB ); 
        m_hDIB = NULL; 
    } 
} 
//*********************************************************** 
 
//*********************************************************** 
HANDLE CImage::GetCopyHandle(CPoint LTp, CPoint RBp) 
{ 
#ifdef _DEBUG 
	if(!CheckRect(LTp,RBp)) 
	{ 
		AfxMessageBox("下标越界!!!"); 
		AfxAbort(); 
	} 
#endif 
	P_LONG  width   = (RBp.x - LTp.x+1); 
    P_LONG  height  = (RBp.y - LTp.y+1); 
    
	width = (width* m_wImageDepth/ 8 + 3) & ~3; 
	 
	P_LONG  dwBitsSize = width * height; 
	P_LONG  DibInfoSize; 
 
	DibInfoSize = sizeof(BITMAPINFOHEADER) + m_wColorMapNum*sizeof(RGBQUAD); 
    dwBitsSize += (DibInfoSize + sizeof(BITMAPFILEHEADER)); 
	m_hDIB      = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); 
     
	LPSTR  lpDIBHdr          = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB); 
    LPSTR  lpDIBBits         = lpDIBHdr + DibInfoSize; 
    LPBITMAPINFO CopyDibInfo = (LPBITMAPINFO)lpDIBHdr; 
    CopyDibInfo->bmiHeader   = m_lpDibInfo->bmiHeader; 
     
	CopyDibInfo->bmiHeader.biWidth       = (RBp.x - LTp.x + 1); 
    CopyDibInfo->bmiHeader.biHeight      = height; 
	CopyDibInfo->bmiHeader.biSizeImage   = width * height; 
	if( m_wImageDepth <= 8) 
	{ 
		for(int i=0 ;i< m_wColorMapNum; i++) 
		{ 
			CopyDibInfo->bmiColors[i] = m_lpDibInfo->bmiColors[i]; 
		}  
	}  
	int   OffsetX  = LTp.x* m_wImageDepth/ 8; 
	LPSTR lpTarget = lpDIBBits + (height-1) * width; 
	for( P_LONG j= 0; j< height; j++, lpTarget -= width) 
	{		 
		memcpy( lpTarget,  RowAddress[LTp.y+ j] + OffsetX,  width); 
	} 
	return m_hDIB;     
} 
//*********************************************************** 
 
//*********************************************************** 
void  CImage::Inverse() 
{	 
	eImageType dImageType = GetImageType(); 
	if(dImageType == IndexColorImage) 
	{ 
		for(int gray=0;gray < m_wColorMapNum;gray++) 
		{ 
			m_lpDibInfo->bmiColors[gray].rgbBlue  = ~m_lpDibInfo->bmiColors[gray].rgbBlue ; 
			m_lpDibInfo->bmiColors[gray].rgbGreen = ~m_lpDibInfo->bmiColors[gray].rgbGreen; 
			m_lpDibInfo->bmiColors[gray].rgbRed   = ~m_lpDibInfo->bmiColors[gray].rgbRed  ; 
		}                            
	} 
	else 
	{ 
		DWORD *lpTemp = (DWORD *)m_lpDibArray; 
		P_LONG tempL  = m_ImageSize / 4; 
		for(P_LONG i= 0; i< tempL; i++) 
			*lpTemp = ~*lpTemp++; 
	} 
} 
//*********************************************************** 
 
//*********************************************************** 
void  CImage::VerticalFlip() 
{ 
	P_BYTE *temp = new P_BYTE[m_nDibWidth]; // Inverse the IMG format image 
    int  dim = m_ImageHeight / 2; 
	for(int i = 0;i < dim ;i++)  
	{ 
		memcpy( temp,          RowAddress[i],                m_nDibWidth); 
        memcpy( RowAddress[i], RowAddress[m_nDibHeight-1-i], m_nDibWidth); 
        memcpy( RowAddress[m_nDibHeight-1-i] ,      temp,    m_nDibWidth); 
    } 
	if(temp != NULL) delete []temp; 
} 
//*********************************************************** 
 
//*********************************************************** 
void  CImage::HorizontalFlip() 
{ 
	if( m_wImageDepth < 8) return; 
	int  dim = m_ImageWidth / 2; 
	int  Last = (m_ImageWidth - 1)* m_wImageDepth/ 8; 
	switch( m_wImageDepth ) 
	{ 
		case  8: 
		{ 
			P_BYTE *fp, *bp, swap; 
	        for(int j= 0; j< m_ImageHeight; j++) 
			{	 
				fp = RowAddress[j]; 
				bp = RowAddress[j] + Last; 
		        for(int i = 0;i < dim ;i++)  
				{ 
					swap  = *fp; 
					*fp++ = *bp; 
					*bp-- =  swap; 
				} 
			} 
			break; 
		} 
		case  16: 
		{ 
			WORD *fp, *bp, swap; 
	        for(int j=0; jbmiHeader.biWidth	   = m_ImageWidth; 
	m_lpDibInfo->bmiHeader.biHeight	   = m_IsImageDownUp ? m_ImageHeight : -m_ImageHeight; 
	m_lpDibInfo->bmiHeader.biSizeImage = m_ImageSize; 
 
    m_lpDibArray = new P_BYTE[m_ImageSize]; 
	if(m_lpDibArray == NULL) AfxThrowMemoryException(); 
	BYTE **lpBRowAddress = new BYTE*[m_OldImageHeight]; 
	long i, j; 
	if( m_IsImageDownUp ) 
	{ 
		lpBRowAddress[m_OldImageHeight- 1] = m_lpDibArrayBuff; 
		for(i= m_OldImageHeight- 2; i>=0 ; i--) 
		{ 
			lpBRowAddress[i] = lpBRowAddress[i+1] + m_OldnDibWidth; 
		} 
	} 
	else 
	{ 
		lpBRowAddress[0] = m_lpDibArrayBuff; 
		for(i= 1; i< m_OldImageHeight; i++) 
		{ 
			lpBRowAddress[i] = lpBRowAddress[i-1] + m_OldnDibWidth; 
		} 
	} 
    GenerateRowAddress(); 
    
	DWORD start = GetTickCount(); 
	if( Clockwise ) 
	{ 
		switch(m_wImageDepth) 
		{ 
			case  8: 
			{ 
				for(j= 0; j< m_OldImageHeight; j++) 
				{ 
					for(i= 0; i< m_OldImageWidth; i++) 
						RowAddress[i][m_OldImageHeight- j- 1] = lpBRowAddress[j][i]; 
				} 
				break; 
			} 
			case  16: 
			{ 
				WORD *BRowAddress, *fp; 
				for(P_LONG j= 0; j< m_OldImageHeight; j++) 
				{ 
					BRowAddress = (WORD*)(lpBRowAddress[j]); 
					for(P_LONG i= 0; i< m_OldImageWidth; i++) 
					{ 
						fp = (WORD*)RowAddress[i]; 
						fp[m_OldImageHeight- j- 1] = BRowAddress[i]; 
					} 
				} 
				break; 
			} 
			case  24: 
			{   
				RGBTRIPLE *BRowAddress, *fp; 
				for(P_LONG j= 0; j< m_OldImageHeight; j++) 
				{ 
					BRowAddress = (RGBTRIPLE*)(lpBRowAddress[j]); 
					for(P_LONG i= 0; i< m_OldImageWidth; i++) 
					{ 
						fp = (RGBTRIPLE*)RowAddress[i]; 
						fp[m_OldImageHeight- j- 1] = BRowAddress[i]; 
					} 
				} 
				break; 
			} 
			case  32: 
			{ 
				DWORD *BRowAddress, *fp; 
				for(P_LONG j= 0; j< m_OldImageHeight; j++) 
				{ 
					BRowAddress = (DWORD*)(lpBRowAddress[j]); 
					for(P_LONG i= 0; i< m_OldImageWidth; i++) 
					{ 
						fp = (DWORD*)RowAddress[i]; 
						fp[m_OldImageHeight- j- 1] = BRowAddress[i]; 
					} 
				} 
				break; 
			} 
		} 
	} 
	else 
	{ 
		switch(m_wImageDepth) 
		{ 
			case  8: 
			{ 
				for(j= 0; j< m_OldImageHeight; j++) 
				{ 
					for(i= 0; i< m_OldImageWidth; i++) 
						RowAddress[m_ImageHeight- i- 1][j]    = lpBRowAddress[j][i]; 
				} 
				break; 
			} 
			case  16: 
			{ 
				WORD *BRowAddress, *fp; 
				for(P_LONG j= 0; j< m_OldImageHeight; j++) 
				{ 
					BRowAddress = (WORD*)(lpBRowAddress[j]); 
					for(P_LONG i= 0; i< m_OldImageWidth; i++) 
					{ 
						fp = (WORD*)RowAddress[m_ImageHeight- i- 1]; 
						fp[j] = BRowAddress[i]; 
					} 
				} 
				break; 
			} 
			case  24: 
			{   
				RGBTRIPLE *BRowAddress, *fp; 
				for(P_LONG j= 0; j< m_OldImageHeight; j++) 
				{ 
					BRowAddress = (RGBTRIPLE*)(lpBRowAddress[j]); 
					for(P_LONG i= 0; i< m_OldImageWidth; i++) 
					{ 
						fp = (RGBTRIPLE*)RowAddress[m_ImageHeight- i- 1]; 
						fp[j] = BRowAddress[i]; 
					} 
				} 
				break; 
			} 
			case  32: 
			{ 
				DWORD *BRowAddress, *fp; 
				for(P_LONG j= 0; j< m_OldImageHeight; j++) 
				{ 
					BRowAddress = (DWORD*)(lpBRowAddress[j]); 
					for(P_LONG i= 0; i< m_OldImageWidth; i++) 
					{ 
						fp = (DWORD*)RowAddress[m_ImageHeight- i- 1]; 
						fp[j] = BRowAddress[i]; 
					} 
				} 
				break; 
			} 
		} 
	} 
	DWORD use = GetTickCount() - start; 
	TRACE("use = %d\n ", use); 
    if(m_lpDibArrayBuff != NULL) ReleaseBuffer(); 
	if(lpBRowAddress != NULL) delete []lpBRowAddress; 
} 
 
//--------------------------------------------------------------------- 
// Clipboard support 
// Function:   CopyHandle (from SDK DibView sample clipbrd.c) 
// 
// Purpose:    Makes a copy of the given global memory block.  Returns 
//             a handle to the new memory block (NULL on error). 
// 
//             Routine stolen verbatim out of ShowDIB. 
// 
// Parms:      h == Handle to global memory to duplicate. 
// 
// Returns:    Handle to new global memory block. 
// 
//--------------------------------------------------------------------- 
HANDLE  CopyHandle (HANDLE h) 
{ 
	P_BYTE  *lpCopy; 
	P_BYTE  *lp; 
	HANDLE     hCopy; 
	DWORD      dwLen; 
 
	if (h == NULL) 	return NULL; 
	dwLen = ::GlobalSize((HGLOBAL) h); 
 
	if ((hCopy = (HANDLE) ::GlobalAlloc (GHND, dwLen)) != NULL) 
	{ 
		lpCopy = (P_BYTE  *) ::GlobalLock((HGLOBAL) hCopy); 
		lp     = (P_BYTE  *) ::GlobalLock((HGLOBAL) h); 
 
		while (dwLen--) 
			*lpCopy++ = *lp++; 
 
		::GlobalUnlock((HGLOBAL) hCopy); 
		::GlobalUnlock((HGLOBAL) h); 
	} 
	return hCopy; 
}