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

📄 gltriwarp.c

📁 matlab aamtool box
💻 C
字号:
/**************************************************************************************** * * Author:		Barry Theobald, Iain Matthews * Data:			30/12/2002 * Function:	Use windows API calls to set up an offscreen bitmap for image warping. * * Revision:	$Id: gltriwarp.c,v 1.0 2003-12-08 11:32:56+00 barry-john_theobald Exp barry-john_theobald $ * Revision:	$Id: gltriwarp.c,v 1.0 2005-09-26 15:34:00+00 andrew ian hanna Exp andrew ian hanna $ * Revision:	$Id: gltriwarp.c,v 1.0 2006-02-07 16:08:00+00 andrew (god) courtenay Exp andrew (god) courtenay $****************************************************************************************/#include <windows.h>#include <stdio.h>#include <math.h>#include "GL/gl.h"#include "mex.h"// *************************************************************************************// Store windows and offscreen bitmap informationtypedef struct _WGLINFO {	HDC hDC;	HGLRC hGLRC;	HPALETTE hPalette;	HBITMAP hBitmap;	HBITMAP	hOldBitmap;	HINSTANCE hCInst;	WNDCLASS wndClass;	HWND hWnd;} WGLINFO; GLuint texName;// Define globals **********************************************************************#define BMP_WIDTH	1024#define BMP_HEIGHT	1024static WGLINFO wglInfo;static int initialised = 0;char *className = "gltriwarp";char *windowName = "gltriwarp";// Function declarations ****************************************************************LRESULT APIENTRY WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);void setupDIB(void);void Initalways();void setupPixelFormat(void);void Initialise(int nrhs, const mxArray *prhs[]);void KillGLWindow(void);void InitGL(void);void InitTexture(void);GLvoid getMappedImage(int opwidth, int opheight);GLubyte *GetInputImage(const mxArray *img, int *width, int *height);void ParseVert(float *vert, int nvert, int *opwidth, int *opheight);float *ScaleTexVert(float *vert, int Nvert, int width, int height);// **************************************************************************************void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){	int k;	int width, height, opwidth, opheight, Nvert;	int dims[3];	float *ivert, *overt, *tvert;	GLubyte *pix;	mxArray *oimg;	if(nrhs < 3)		mexErrMsgTxt("Must give the input image and the vertices!");	// Setup the bitmap on first call *****************************************************    if(!initialised)		Initialise(nrhs, prhs);    Initalways();        	// Get the texture image **************************************************************	pix = GetInputImage(prhs[0], &width, &height);	// Check the image size < bitmap	if(width > BMP_WIDTH || height > BMP_HEIGHT)		mexErrMsgTxt("\nImage is larger than the rendering window\n");  // Copy image into texture memory	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pix);	// Get input vertices *****************************************************************	if(!mxIsNumeric(prhs[1]) || mxIsEmpty(prhs[1]))		mexErrMsgTxt("Input vertices must not be empty\n");	else		ivert = (float*)mxGetData(prhs[1]);	// The number of vertices	Nvert = mxGetNumberOfElements(prhs[1]) / 2;	// Get output vertices *****************************************************************	if(!mxIsNumeric(prhs[2]) || mxIsEmpty(prhs[2]))		mexErrMsgTxt("Output vertices must not be empty\n");	else		overt = (float*)mxGetData(prhs[2]);	// The number of vertices	if((mxGetNumberOfElements(prhs[2]) / 2) != Nvert)		mexErrMsgTxt("Number of input and output vertices must match");	// Get the range of output verticies and set the output image size ********************	ParseVert(overt, Nvert, &opwidth, &opheight);	// Scale texture coordinates into the range 0->1 	tvert = ScaleTexVert(ivert, Nvert, BMP_WIDTH, BMP_HEIGHT);	// Now draw the texture ***************************************************************	glEnable(GL_TEXTURE_2D);	glClear(GL_COLOR_BUFFER_BIT);	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);        glBindTexture(GL_TEXTURE_2D, texName);	glBegin(GL_TRIANGLES);	for(k=0; k < Nvert * 2; k+=2) {		glTexCoord2fv(tvert + k);		glVertex2fv(overt + k);	}	glEnd();	glFinish();	glDisable(GL_TEXTURE_2D);	// Texture coordinates are no longer needed	mxFree(tvert);	// Setup the return image and return **************************************************	dims[0] = opwidth;	dims[1] = opheight;	dims[2] = 3;	if ((oimg = mxCreateNumericArray(3, dims, mxUINT8_CLASS, mxREAL)) == NULL)		mexErrMsgTxt("Unable to allocate output matrix\n");	// Read pixels from framebuffer to output matrix	glReadPixels(0, 0, opwidth, opheight, GL_RGB, GL_UNSIGNED_BYTE, (GLubyte*)mxGetData(oimg));	glFinish();	// Output matrix	plhs[0] = oimg;    wglDeleteContext(wglInfo.hGLRC);   // DestroyWindow(wglInfo.hWnd);    }//****************************************************************************************//****************************************************************************************//********************************* Windows Stuff   **************************************//****************************************************************************************//****************************************************************************************void Initalways(){	// Create the OpenGL context and make it current	if (!(wglInfo.hGLRC = wglCreateContext(wglInfo.hDC)))				// Are We Able To Get A Rendering Context?	{		KillGLWindow();								// Reset The Display		MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);		//return FALSE;								// Return FALSE	}	if(!wglMakeCurrent(wglInfo.hDC, wglInfo.hGLRC))					// Try To Activate The Rendering Context	{		KillGLWindow();								// Reset The Display		MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);	//	return FALSE;								// Return FALSE	}		// Initialise OpenGL state variables and OpenGL texture mapping	InitGL();	InitTexture();}// Initialise a window (but do not display), and use properties to setup an DIBvoid Initialise(int nrhs, const mxArray *prhs[]){	// Define and register a window class	wglInfo.wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	wglInfo.wndClass.lpfnWndProc = WndProc;	wglInfo.wndClass.cbClsExtra = 0;	wglInfo.wndClass.cbWndExtra = 0;	wglInfo.wndClass.hInstance = wglInfo.hCInst;	wglInfo.wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);	wglInfo.wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);	wglInfo.wndClass.hbrBackground = GetStockObject(WHITE_BRUSH);	wglInfo.wndClass.lpszMenuName = NULL;	wglInfo.wndClass.lpszClassName = className;			if (!RegisterClass(&wglInfo.wndClass))									// Attempt To Register The Window Class	{		MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);		//return FALSE;											// Return FALSE	}	//	//	NOTE: --	//	Create a window of the previously defined class, but do not display!	//	The window properties are used to setup the bitmap	//	if (!(	wglInfo.hWnd = CreateWindow(		className,							// Window class's name 		windowName,							// Title bar text 		WS_OVERLAPPEDWINDOW |		// The window's style 		WS_CLIPCHILDREN |		WS_CLIPSIBLINGS,		0, 0,										// Position 		BMP_WIDTH, BMP_HEIGHT,	// Size 		NULL,										// Parent window's handle 		NULL,										// Menu handle 		wglInfo.hCInst,					// Instance handle 		NULL)))									// No additional data 	{		KillGLWindow();								// Reset The Display		MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);		//return FALSE;								// Return FALSE	}if (!(wglInfo.hDC = GetDC(wglInfo.hWnd)))							// Did We Get A Device Context?	{		KillGLWindow();								// Reset The Display		MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);		//return FALSE;								// Return FALSE	}if (!(wglInfo.hDC = CreateCompatibleDC(wglInfo.hDC)))							// Did We Get A Device Context?	{		KillGLWindow();								// Reset The Display		MessageBox(NULL,"Can't Create Compatible DC.","ERROR",MB_OK|MB_ICONEXCLAMATION);		//return FALSE;								// Return FALSE	}		// Set up the bitmap	setupDIB();	// Define the desired pixel format	setupPixelFormat();	// Lock the mex file for return calls	mexMakeMemoryPersistent(&wglInfo);	initialised = 1;	mexLock();}// This never actually gets used as MEX will clear everything when Matlab quitsLRESULT APIENTRY WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){	switch (message) {		case WM_DESTROY:			PostQuitMessage(0);			return 0;		default:			break;	}	// Deal with any unprocessed messages	return DefWindowProc(hWnd, message, wParam, lParam);}//****************************************************************************************// Set up a device independent bitmap in memory for offscreen renderingvoid setupDIB(void){	BITMAPINFO *bmInfo;	BITMAPINFOHEADER *bmHeader;	UINT usage;	VOID *base;	int bmiSize;	int bitsPerPixel;	bmiSize = sizeof(*bmInfo);	bitsPerPixel = GetDeviceCaps(wglInfo.hDC, BITSPIXEL);	bmInfo = (BITMAPINFO *) calloc(1, bmiSize);	bmHeader = &bmInfo->bmiHeader;	bmHeader->biSize = sizeof(*bmHeader);	bmHeader->biWidth = BMP_WIDTH;	bmHeader->biHeight = BMP_HEIGHT;	bmHeader->biPlanes = 1;	bmHeader->biBitCount = bitsPerPixel;	bmHeader->biXPelsPerMeter = 0;	bmHeader->biYPelsPerMeter = 0;	bmHeader->biClrUsed = 0;	bmHeader->biClrImportant = 0;	bmHeader->biCompression = BI_RGB;	bmHeader->biSizeImage = 0;	usage = DIB_RGB_COLORS;	wglInfo.hBitmap = CreateDIBSection(wglInfo.hDC, bmInfo, usage, &base, NULL, 0);	if(wglInfo.hBitmap == NULL)		mexErrMsgTxt("Failed to create DIBSection.");	wglInfo.hOldBitmap = SelectObject(wglInfo.hDC, wglInfo.hBitmap);	free(bmInfo);	}//****************************************************************************************// Set the desire pixel format and ensure we can select itvoid setupPixelFormat(void){	PIXELFORMATDESCRIPTOR pfd = {		sizeof(PIXELFORMATDESCRIPTOR),	// size of this pfd		1,															// version num 		PFD_SUPPORT_OPENGL,							// support OpenGL 		0,															// pixel type 		0,															// 8-bit color depth 		0, 0, 0, 0, 0, 0,								// color bits (ignored) 		0,															// no alpha buffer 		0,															// alpha bits (ignored) 		0,															// no accumulation buffer 		0, 0, 0, 0,											// accum bits (ignored) 		16,															// depth buffer 		0,															// no stencil buffer 		0,															// no auxiliary buffers 		PFD_MAIN_PLANE,									// main layer 		0,															// reserved 		0, 0, 0,												// no layer, visible, damage masks 	};    	int SelectedPixelFormat;	BOOL retVal;	pfd.cColorBits = GetDeviceCaps(wglInfo.hDC, BITSPIXEL);	pfd.iPixelType = PFD_TYPE_RGBA;	pfd.dwFlags |= PFD_DRAW_TO_BITMAP;			if (!(SelectedPixelFormat = ChoosePixelFormat(wglInfo.hDC, &pfd)))	// Did Windows Find A Matching Pixel Format?	{		KillGLWindow();								// Reset The Display		MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);		//return FALSE;								// Return FALSE	}		retVal = SetPixelFormat(wglInfo.hDC, SelectedPixelFormat, &pfd);	if(!retVal)		// Are We Able To Set The Pixel Format?	{		KillGLWindow();								// Reset The Display		MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);		//return FALSE;								// Return FALSE	}	}void KillGLWindow(void){}//****************************************************************************************//****************************************************************************************//********************************   OpenGL Stuff   **************************************//****************************************************************************************//****************************************************************************************void InitGL(void){	glClearColor(0.0, 0.0, 0.0, 0.0);	glShadeModel(GL_FLAT);	glViewport(0, 0, BMP_WIDTH, BMP_HEIGHT);	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	glOrtho(0.0, BMP_WIDTH, 0.0, BMP_HEIGHT, -1.0, 1.0);	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();glPixelStorei(GL_UNPACK_ALIGNMENT, 1);	glPixelStorei(GL_PACK_ALIGNMENT, 1);}void InitTexture(void){	glGenTextures(1, &texName);	glBindTexture(GL_TEXTURE_2D, texName);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);	glTexImage2D(GL_TEXTURE_2D, 0, 3, BMP_WIDTH, BMP_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);}//****************************************************************************************//****************************************************************************************//********************************  Iain's Stuff   ***************************************//****************************************************************************************//****************************************************************************************GLubyte *GetInputImage(const mxArray *img, int *width, int *height){	int	ndim, nx, ny;	const int *dim; if(!mxIsNumeric(img) || mxIsEmpty(img) || !mxIsUint8(img))		mexErrMsgTxt("Input image must be uint8 2D or 3D numeric matrix");			ndim = mxGetNumberOfDimensions(img);	if(ndim != 3)		mexErrMsgTxt("Input image must be (nx * ny * 3) 24-bit RGB");	dim = mxGetDimensions(img);	*width = nx = dim[0];	*height = ny = dim[1];	if(dim[2] > 3)		mexWarnMsgTxt("Only using first 3 values of 3rd dimension");	else if(dim[2] < 3)		mexErrMsgTxt("Third dimension must have size = 3");	return((GLubyte*)mxGetData(img));}float *ScaleTexVert(float *vert, int Nvert, int width, int height){	int k;	float *tvert, xval, yval;	if((tvert = (float*)mxCalloc(2 * Nvert, sizeof(float))) == NULL)		mexErrMsgTxt("Unable to allocate texture vertices\n");	for(k = 0; k < Nvert; k++) {		xval = vert[k*2];		yval = vert[(k*2)+1];		tvert[k*2] = xval / (float)width;		tvert[(k*2)+1] = yval / (float)height;	}	return(tvert);}void ParseVert(float *vert, int nvert, int *opwidth, int *opheight){	float maxx = -10000.0, maxy = -10000.0;	float x, y;	int k;		for(k = 0; k < nvert; k++) {		x = vert[k*2];		y = vert[(k*2)+1];				if (maxx < x)			maxx = x;		if (maxy < y)			maxy = y;	}		// Return the number of pixels in the output image	*opwidth = (int)floor(maxx + 0.5);	*opheight = (int)floor(maxy + 0.5);}

⌨️ 快捷键说明

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