/*
	
	  Camera image capture & manipulation 
	
	  author : Mateusz Malczak [ mateuszATmalczakDOTinfo ]
			   http://malczak.info		
	
	  downloaded from http://devblog.malczak.info
		(vistit this page for more info)
	 
*/
#include <windows.h>
#include <winuser.h>
#include <wingdi.h>
#include <vfw.h>
#include <stdlib.h>
#include <math.h>

typedef struct
{ 
	unsigned char b,g,r;
} rgb24;


LRESULT PASCAL precapture(HWND hWnd, LPVIDEOHDR lpVHdr) ;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	HWND capwin, hwnd;
	MSG msg;
	WNDCLASSEX ws;
	ws.cbSize = sizeof(WNDCLASSEX);
	ws.style = CS_HREDRAW | CS_VREDRAW;
	ws.lpszMenuName = "";
	ws.lpszClassName = "CamCapClass";
	ws.lpfnWndProc = WindowProc;
	ws.hInstance = hInstance;
	ws.hIcon = LoadIcon( NULL, IDI_APPLICATION );
	ws.hIconSm = LoadIcon( NULL, IDI_APPLICATION );;
	ws.hCursor = LoadCursor( NULL, IDC_ARROW );
	ws.hbrBackground = (HBRUSH)GetStockObject( LTGRAY_BRUSH );
	ws.cbWndExtra = 0;
	ws.cbClsExtra = 0;

	RegisterClassEx(&ws);

	hwnd = CreateWindowEx(0,"CamCapClass","CamCapture",
					      WS_VISIBLE,10,10,1,1,
						  NULL,NULL,hInstance,NULL );


	capwin = capCreateCaptureWindow("capwin",WS_CHILD|WS_VISIBLE,0,0,1,1,hwnd,0);
	 
	 if ( capDriverConnect(capwin,0) )
	 {
		LPBITMAPINFO bmpnfo;
		DWORD bmpnfosize = capGetVideoFormatSize(capwin);
		bmpnfo = (LPBITMAPINFO)GlobalAlloc(GHND, bmpnfosize);
		capGetVideoFormat(capwin, bmpnfo, bmpnfosize);	
		SetWindowPos(hwnd,HWND_TOP,0,0,bmpnfo->bmiHeader.biWidth,bmpnfo->bmiHeader.biHeight,
					SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOREPOSITION|SWP_NOOWNERZORDER|SWP_NOCOPYBITS|SWP_FRAMECHANGED);
		SetWindowPos(capwin,HWND_TOP,0,0,bmpnfo->bmiHeader.biWidth,bmpnfo->bmiHeader.biHeight,
					SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOREPOSITION|SWP_NOOWNERZORDER|SWP_NOCOPYBITS|SWP_FRAMECHANGED);
		GlobalFree(bmpnfo);	
		capPreviewRate(capwin,10);	
		capPreview(capwin,TRUE);
		capSetCallbackOnFrame(capwin,precapture);
	 };
	
		while( GetMessage(&msg,NULL,0,0) )
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		};

	return msg.wParam;
}

LRESULT PASCAL precapture(HWND hWnd, LPVIDEOHDR lpVHdr) 
{
	int i,x,y,j;
	rgb24 *colp, *cols;	//(ive assumed 24bits per pixel)

	i = 0;
	y = 0;
	j = 0;

	int scale = 2;

	for ( y=0, x=0; 
		  i<(int)lpVHdr->dwBytesUsed; 
		  i+=3*scale )
		{	
			colp = (rgb24*)((unsigned char*)lpVHdr->lpData+i);
			cols = (rgb24*)((unsigned char*)lpVHdr->lpData+(y*960)+x);
			cols[0] = colp[0];
			cols[1] = colp[1];
			cols[2] = colp[2];
			x+=3;
				if ( x>=(3*320/scale) )
				{
					memcpy( (unsigned char*)lpVHdr->lpData+((y+120)*960),
							(unsigned char*)lpVHdr->lpData+(y*960),
							3*320/scale ); //TOP LEFT
					memcpy( (unsigned char*)lpVHdr->lpData+((y+120)*960)+x,
							(unsigned char*)lpVHdr->lpData+(y*960),
							3*320/scale ); //TOP RIGHT
					memcpy( (unsigned char*)lpVHdr->lpData+((120-y)*960)+x,
							(unsigned char*)lpVHdr->lpData+(y*960),
							3*320/scale ); //BOTTOM RIGHT
					y += 1;
					x = 0;
					i = 960*scale*y;
				};
		};

	return (LRESULT)FALSE;
};

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	 switch( uMsg )
	 {
		case WM_DESTROY:
			PostQuitMessage(0);
			return 0;
	 };
	return DefWindowProc(hwnd,uMsg,wParam,lParam);
};
