www.pudn.com > geometrical transform.rar > geotrans.c


////////////////////////////////////////////////////////////// 
//Name:geotrans.c 
//Purpose: To perform geometric transform 
//Author: phoenix, CS, TshingHua, Beijing, P.R.C. 
//Email: bjlufengjun@www.163.net or lufengjun@hotmail.com 
//Date:April 3, 1998 
 
//header file 
#include "bmp.h" 
#include "memory.h" 
#include "math.h" 
 
//macro definition 
#define WIDTHBYTES(i)    ((i+31)/32*4) 
#define PI 3.1415926535 
#define RADIAN(angle) ((angle)*PI/180.0) //convert angle to radian 
 
//function declaration 
int PASCAL WinMain (HANDLE, HANDLE, LPSTR, int); 
LRESULT CALLBACK MainWndProc(HWND , UINT,WPARAM, LPARAM); 
BOOL LoadBmpFile (HWND hWnd,char *BmpFileName); 
BOOL CALLBACK InputBox( HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam ); 
BOOL Translation(HWND hWnd); 
BOOL Rotation(HWND hWnd); 
BOOL Mirror(HWND hWnd,BOOL XDirection); 
BOOL Transpose(HWND hWnd); 
BOOL Zoom(HWND hWnd); 
 
//global variable declaration 
BITMAPFILEHEADER   bf; 
BITMAPINFOHEADER   bi; 
HPALETTE           hPalette=NULL; 
HBITMAP            hBitmap=NULL; 
HGLOBAL            hImgData=NULL; 
DWORD              NumColors; 
DWORD              LineBytes; 
HWND               hWnd; 
HINSTANCE          ghInst; 
int                xOffset=0,yOffset=0; 
float			   RotateAngle=0.0f; 
float              ZoomRatio=0.25f; 
DWORD              ImgWidth=0 , ImgHeight=0; 
/////////////////////////////////////////////////////////// 
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, 
		    LPSTR lpszCmdLine, int nCmdShow) 
{ 
	MSG       msg; 
	WNDCLASS  wndclass; 
 
	ghInst=hInstance; 
	if ( ! hPrevInstance ){ 
		wndclass.style = CS_HREDRAW | CS_VREDRAW; 
		wndclass.lpfnWndProc = MainWndProc; 
		wndclass.cbClsExtra = 0; 
		wndclass.cbWndExtra = 0; 
		wndclass.hInstance = hInstance; 
		wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); 
		wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); 
		wndclass.hbrBackground = GetStockObject (WHITE_BRUSH); 
		wndclass.lpszMenuName =  "BMPMENU"; 
		wndclass.lpszClassName = "phoenix ip system"; 
    } 
 
    if ( ! RegisterClass (&wndclass) ) 
	    return FALSE; 
  
	hWnd = CreateWindow ("phoenix ip system","geometric transform", 
						 WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, 
						 CW_USEDEFAULT,	CW_USEDEFAULT, NULL,NULL, 
						 hInstance,	NULL); 
	if (!hWnd) 
		return FALSE; 
	ShowWindow (hWnd, SW_SHOWMAXIMIZED); 
	UpdateWindow (hWnd); 
	 
	while ( GetMessage (&msg, NULL, 0, 0) ){ 
		TranslateMessage (&msg); 
		DispatchMessage (&msg); 
    } 
	return msg.wParam; 
} 
 
//////////////////////////////////////////////////////////////// 
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message,WPARAM wParam, LPARAM lParam) 
{ 
    static  HDC    hDC,hMemDC; 
    PAINTSTRUCT    ps; 
 
    switch (message){ 
    case WM_PAINT: 
	{          
		hDC = BeginPaint(hWnd, &ps); 
		if (hBitmap) 
		{  
			hMemDC = CreateCompatibleDC(hDC); 
			if (hPalette) 
			{            
				SelectPalette (hDC, hPalette, FALSE);  
				SelectPalette (hMemDC, hPalette, FALSE); 
				RealizePalette (hDC); 
			}    
			SelectObject(hMemDC, hBitmap);  
			BitBlt(hDC, 0, 0, ImgWidth,ImgHeight, hMemDC, 0, 0, SRCCOPY); 
			DeleteDC(hMemDC); 
		} 
		EndPaint(hWnd, &ps); 
		break; 
	} 
	case WM_DESTROY: //注意释放内存和位图,调色板句柄 
        if(hBitmap!=NULL) 
	        DeleteObject(hBitmap); 
	     
		if(hPalette!=NULL)                      
	        DeleteObject(hPalette); 
		 
		if(hImgData!=NULL){ 
			GlobalUnlock(hImgData); 
			GlobalFree(hImgData); 
		}	         
	    PostQuitMessage (0); 
	    return 0; 
	case WM_COMMAND: 
	    switch (wParam){ 
	    case IDM_LOADBMP:  
			//注意重新分配内存和调色板,位图句柄时,先释放原来的 
	        if(hBitmap!=NULL){      
				DeleteObject(hBitmap); 
	            hBitmap=NULL; 
	        } 
	        if(hPalette!=NULL){                      
				DeleteObject(hPalette); 
	            hPalette=NULL; 
	        } 
			if(hImgData!=NULL){ 
				GlobalUnlock(hImgData); 
				GlobalFree(hImgData);   
				hImgData=NULL; 
			}	         
			if(LoadBmpFile(hWnd,"c:\\test.bmp")) //成功,则重画窗口 
                InvalidateRect(hWnd,NULL,TRUE); 
	        break; 
		case IDM_TRANSLATION:  
			if(hImgData!=NULL){ 
				if(Translation(hWnd)) 
					InvalidateRect(hWnd,NULL,TRUE); 
			} 
			else 
				MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
			break; 
		case IDM_ROTATION:  
			if(hImgData!=NULL){ 
				if(Rotation(hWnd)) 
					InvalidateRect(hWnd,NULL,TRUE); 
			} 
			else 
				MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
			break; 
		case IDM_MIRRORX:  
			if(hImgData!=NULL){ 
				if(Mirror(hWnd,TRUE)) 
					InvalidateRect(hWnd,NULL,TRUE); 
			} 
			else 
				MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
			break; 
		case IDM_MIRRORY:  
			if(hImgData!=NULL){ 
				if(Mirror(hWnd,FALSE)) 
					InvalidateRect(hWnd,NULL,TRUE); 
			} 
			else 
				MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
			break; 
		case IDM_TRANSPOSE:  
			if(hImgData!=NULL){ 
				if(Transpose(hWnd)) 
					InvalidateRect(hWnd,NULL,TRUE); 
			} 
			else 
				MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
			break; 
		case IDM_ZOOM:  
			if(hImgData!=NULL){ 
				if(Zoom(hWnd)) 
					InvalidateRect(hWnd,NULL,TRUE); 
			} 
			else 
				MessageBox(hWnd,"File not loaded yet!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
			break; 
		case IDM_EXIT: 
	        SendMessage(hWnd,WM_DESTROY,0,0L); 
	        break; 
	    } 
	break;                 
    } 
    return DefWindowProc (hWnd, message, wParam, lParam); 
} 
 
//////////////////////////////////////////////////////////////// 
BOOL LoadBmpFile (HWND hWnd,char *BmpFileName) 
{    
    HFILE              hf; 
    LPBITMAPINFOHEADER lpImgData; 
    LOGPALETTE         *pPal; 
    LPRGBQUAD          lpRGB; 
    HPALETTE           hPrevPalette;  
    HDC                hDc; 
	HLOCAL             hPal; 
	DWORD 		       ImgSize; 
	DWORD              i; 
 
    if((hf=_lopen(BmpFileName,OF_READ))==HFILE_ERROR){ 
        MessageBox(hWnd,"File c:\\test.bmp not found!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
        return FALSE; 
	} 
	_lread(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));  
	_lread(hf,(LPSTR)&bi,sizeof(BITMAPINFOHEADER)); 
	ImgWidth=bi.biWidth; 
	ImgHeight=bi.biHeight; 
	LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount); 
	ImgSize=(DWORD)LineBytes*bi.biHeight; 
    if(bi.biClrUsed!=0) 
		NumColors=(DWORD)bi.biClrUsed; 
	else 
        switch(bi.biBitCount){ 
	       	case 1: 
        	    NumColors=2; 
        	    break; 
        	case 4: 
        	    NumColors=16; 
        	    break; 
        	case 8: 
        	    NumColors=256; 
        	    break; 
        	case 24: 
        	    NumColors=0; 
        	    break; 
              default: 
                  MessageBox(hWnd,"Invalid color numbers!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
                  _lclose(hf); 
                  return FALSE;  
        } 
	if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER) 
							+sizeof(BITMAPINFOHEADER))) 
	{ 
    	MessageBox(hWnd,"Invalid color numbers!","Error Message" ,MB_OK| 
	               MB_ICONEXCLAMATION); 
		_lclose(hf); 
		return FALSE;  
	} 
        bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize; 
	if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+ 
						     NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL) 
	{ 
    	MessageBox(hWnd,"Error alloc memory!","ErrorMessage",MB_OK| 
                   MB_ICONEXCLAMATION); 
	    _lclose(hf); 
		return FALSE; 
	} 
   
	lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);  
    _llseek(hf,sizeof(BITMAPFILEHEADER),SEEK_SET); 
	_hread(hf,(char *)lpImgData,(long)sizeof(BITMAPINFOHEADER) 
           +(long)NumColors*sizeof(RGBQUAD)+ImgSize); 
	_lclose(hf); 
    if(NumColors!=0) 
	{                     
	    hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) + NumColors* sizeof(PALETTEENTRY)); 
	    pPal =(LOGPALETTE *)LocalLock(hPal); 
	    pPal->palNumEntries =(WORD) NumColors; 
		pPal->palVersion    = 0x300; 
	    lpRGB = (LPRGBQUAD)((LPSTR)lpImgData + (DWORD)sizeof(BITMAPINFOHEADER)); 
		for (i = 0; i < NumColors; i++) { 
     		pPal->palPalEntry[i].peRed=lpRGB->rgbRed; 
			pPal->palPalEntry[i].peGreen=lpRGB->rgbGreen; 
			pPal->palPalEntry[i].peBlue=lpRGB->rgbBlue; 
			pPal->palPalEntry[i].peFlags=(BYTE)0; 
			lpRGB++; 
		} 
		hPalette=CreatePalette(pPal); 
		LocalUnlock(hPal); 
		LocalFree(hPal); 
	} 
	hDc=GetDC(hWnd); 
	if(hPalette){ 
        hPrevPalette=SelectPalette(hDc,hPalette,FALSE); 
		RealizePalette(hDc); 
	} 
	hBitmap=CreateDIBitmap(hDc,	(LPBITMAPINFOHEADER)lpImgData, (LONG)CBM_INIT, 
				(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD), 
   				(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS); 
	if(hPalette && hPrevPalette){ 
		SelectPalette(hDc,hPrevPalette,FALSE); 
		RealizePalette(hDc); 
	} 
  
	ReleaseDC(hWnd,hDc); 
	GlobalUnlock(hImgData); 
	return TRUE;  
} 
//////////////////////////////////////////////////////////////// 
BOOL CALLBACK InputBox( HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam ) 
{ 	 
	char str[80]; 
 
   	switch  ( message ){ 
    case WM_INITDIALOG:		    
     	SetDlgItemText(hDlg,ID_XOFFSET,"0"); 
     	SetDlgItemText(hDlg,ID_YOFFSET,"0"); 
     	SetDlgItemText(hDlg,ID_ANGLE,"0"); 
     	SetDlgItemText(hDlg,ID_ZOOMRATIO,"0.25"); 
    	return TRUE; 
   	case WM_COMMAND:		    
    	if ( wParam == IDOK || wParam == IDCANCEL ) 
       	{ 
        	GetDlgItemText(hDlg,ID_XOFFSET,str,80); 
			xOffset=atoi(str); 
        	GetDlgItemText(hDlg,ID_YOFFSET,str,80); 
			yOffset=atoi(str); 
        	GetDlgItemText(hDlg,ID_ANGLE,str,80); 
			RotateAngle=(float)atof(str); 
        	GetDlgItemText(hDlg,ID_ZOOMRATIO,str,80); 
			ZoomRatio=(float)atof(str); 
            EndDialog ( hDlg, TRUE ); 
            return  TRUE; 
       	} 
        break; 
   		} 
	return FALSE;			      
} 
//////////////////////////////////////////////////////////////// 
BOOL Translation(HWND hWnd) 
{ 
	DLGPROC            dlgInputBox = NULL; 
	DWORD              OffBits,BufSize; 
    LPBITMAPINFOHEADER lpImgData; 
	LPSTR              lpPtr; 
	HLOCAL             hTempImgData; 
	LPBITMAPINFOHEADER lpTempImgData; 
	LPSTR              lpTempPtr; 
	int				   SrcX0,SrcY0,SrcX1,SrcY1,DstX0,DstY0,DstX1,DstY1; 
	int                RectWidth,RectHeight; 
	BOOL               xVisible,yVisible; 
	HDC                hDc; 
	HFILE              hf; 
	int                i; 
 
	dlgInputBox = (DLGPROC) MakeProcInstance ( (FARPROC)InputBox, ghInst ); 
	DialogBox (ghInst, "INPUTBOX", hWnd, dlgInputBox); 
	FreeProcInstance ( (FARPROC) dlgInputBox ); 
 
	OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER); 
	BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER); 
 
	if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL) 
    { 
    	MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
        return FALSE; 
    } 
 
    lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);     
	lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData); 
 
	lpPtr=(char *)lpImgData; 
	lpTempPtr=(char *)lpTempImgData; 
 
	memset(lpTempPtr,(BYTE)255,BufSize); 
	memcpy(lpTempPtr,lpPtr,OffBits); 
 
	xVisible=TRUE; 
	if( xOffset<= -bi.biWidth ) 
		xVisible=FALSE; 
	else if( xOffset<=0){ 
		DstX0=0; 
		DstX1=bi.biWidth+xOffset; 
	} 
	else if ( xOffset=0) && (x0=0) && (y0=0) && (x0=0) && (y0