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

📄 camera_control.cpp

📁 用FPGA来实现摄像头的捕捉和采集
💻 CPP
字号:
/*---------------------------------------------------------------
  
	CST 238 GUI Project.
	Windows interface to digital camera senior project.
		
    Filename:  	camera_control.cpp
	Compiler:	MSVC 6.0
	Author:		Ryan Henderson hendersr@oit.edu

  Overview
	This program transfers images from the camera and displays them 
	in a window.  The user can adjust color balance with some 
	sliders, stop and start image transfer and save the current
	image to a bitmap.  The taskbar shows progress of downloading
	the next picture from the camera.

  Files description
	camera_control.cpp 
	Top level file that handles windows	API messages for the menus, 
	dialogs, status bars and etc. It starts a thread to access the 
	camera, transfer raw image, and translate them to a bitmap.  
	Messages from the thread are processed to update the window.
	
	hardware_interface.cpp
	Connects directly with the hardware through the 
	XSTOOL / DriverLINX parallel port driver.  Commands and addresses
	are sent to	the camera to start, stop a transfer.  Data is read
	from the camera and written to a raw buffer.

	image_manip.cpp
	Reads raw image buffer and translates it to a bitmap.  Uses the
	class defined in bitmap.cpp for formatting the bitmap.  Adjusts
	colors in the bitmap according to values set by the adjust
	color sliders.  image_manip has it's own raw buffer that it fills
	from the hardware_interface raw buffer.  
	hi fills its buffer -> im copies that buffer -> hi fills it's 
	buffer again.  Wouldn't want to fill, read from same buffer or 
	image will not contain consistant data.

	Bitmap.cpp
	Defines a bitmap with bitmap file-header and bitmap info-header 
	structs and a big Picture Data buffer.

	Script1.rc, resource.h
	Resource studio created files for menu, dialog boxes

	Other files
	XESS Corporation xstools 4.0 www.xess.com  
	Thank you Dave Van den Bout for answering my questions.

	DriverLINX Port I/O Driver Interface
	<cp> Copyright 1996 Scientific Software Tools, Inc.<nl>
 
	Unified IO - C++ interface for industrial IO cards
	Copyright (C) 2000, UAB "BBD SOFT" ( http://www.bbdsoft.com/ ) 


  	
-------------------------------------------------------------------*/

#include <process.h>
#include <windows.h>
#include <stdlib.h>
#include <assert.h>
#include <strstrea.h>
#include <fstream.h>
#include <string>
#include <commctrl.h>
#include <Commdlg.h>
#include <afxres.h>

using std::string;

#include "hardware_interface.h"                      
#include "image_manip.h"
#include "mystructs.h"
#include "resource.h"

#define WM_FRAME_FINISHED WM_USER

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, 
						  LPARAM lParam);
BOOL CALLBACK CamCtrProc (HWND hDlg, UINT message, WPARAM wParam,
						  LPARAM lParam);
BOOL CALLBACK AboutProc (HWND hDlg, UINT message, WPARAM wParam,
						  LPARAM lParam);

HWND hDlgModeless;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpszCmdParam, int nCmdShow)
{
     static char szAppName[] = "Camera Controller";
     HWND        hwnd;
     MSG         msg;	
     WNDCLASSEX  wndclass; 
	 HMENU		 hMenu;
  
	  wndclass.cbSize		 = sizeof(wndclass);
	  wndclass.style         = CS_HREDRAW | CS_VREDRAW;
	  wndclass.lpfnWndProc   = WndProc;
	  wndclass.cbClsExtra    = 0;
	  wndclass.cbWndExtra    = 0;
	  wndclass.hInstance     = hInstance;
	  wndclass.hIcon         = 
		  LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1));
	  wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
	  wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);
	  wndclass.lpszMenuName  = NULL;
	  wndclass.lpszClassName = szAppName;
	  wndclass.hIconSm		 = NULL;

	  RegisterClassEx (&wndclass);
	
	hMenu = LoadMenu (hInstance, MAKEINTRESOURCE( IDR_MENU1 ) );

    hwnd = CreateWindow (szAppName,         // window class name
		    "Image Window",
		    					     		 // window caption
                    WS_OVERLAPPEDWINDOW,     // window style
                    CW_USEDEFAULT,           // initial x position
                    CW_USEDEFAULT,           // initial y position
                    CW_USEDEFAULT,           // initial x size
                    CW_USEDEFAULT,           // initial y size
                    NULL,                    // parent window handle
                    hMenu,                    // window menu handle
                    hInstance,               // program instance handle
		    		NULL);		     		 // creation parameters

     ShowWindow (hwnd, nCmdShow);
     UpdateWindow (hwnd);

     while (GetMessage (&msg, NULL, 0, 0))
	 {
			TranslateMessage (&msg);
			DispatchMessage (&msg);
	 }
     return msg.wParam;
}

/*******************************************************************

	Thread to pull the image from the camera and translate it to 
	a bmp.  Because this takes about 10 - 20s, this will keep the 
	app from freezing during this process.

	Problem:  the thread doesn't end... It's still using hi and im
	when their destructors are being called.   Need a way to
	end the thread gracefully.

*******************************************************************/

void GetImageThreadProc (PVOID pVoid)
{
	PPARAMS pparams;
	pparams = (PPARAMS)pVoid;

	while(true)
	{
		pparams->hi->DownloadImage(pparams->hwnd);
		pparams->hi->GetRawBuffCpy(pparams->im->GetlpRawImage());
		pparams->im->RawtoBMP(); //Optional width and height later
	//	pparams->im->WriteBMPFile("bmpout.bmp");
		SendMessage(pparams->hwnd, WM_FRAME_FINISHED, 0, 0);

	}
}


/*******************************************************************

	WndProc  Handles Messages

*******************************************************************/
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
						  LPARAM lParam)
{
	HDC						hdc;
	PAINTSTRUCT				ps;
	TCHAR					szBuffer[32];
	static hardware_interface *hi;
	static image_manip		*im;
	static Bitmap*			pbmTemp;
	static BITMAPINFO		bmpinfo;
	static int				cxClient, cyClient;
	static PARAMS			threadParams;
	static	HINSTANCE		hInst;
	INITCOMMONCONTROLSEX	cc;
	static HWND				hStatusBar, hwndParent;
	PDRAWITEMSTRUCT			pdi;
	RECT					rcProgressBar;
	static	float			fPercentComplete;
	static	CAMCTR_DATA		ccd;
	static	UINT iSelection = ID_CONTROL_GO;
	static 	HMENU		 hMenu;
	OPENFILENAME ofn;
	static TCHAR strFileName[255];
	
	
	switch (message)
	{

	case WM_COMMAND:
		
		switch (LOWORD (wParam))
		{
			
		case ID_FILE_EXIT:
			SendMessage(hwnd, WM_CLOSE, 0, 0);
			return 0;
		
		//Pop getsavefilename dialog, then write file
		case ID_FILE_SAVE_AS:
			
			strFileName[0] = '\0';
			ofn.lStructSize = sizeof(OPENFILENAME);
			ofn.hwndOwner = hwnd;
			ofn.lpstrFile = strFileName;
			ofn.lpstrFileTitle = NULL;
			ofn.Flags = OFN_OVERWRITEPROMPT;
			ofn.hInstance = NULL;
			ofn.lpstrFilter = "Bitmap Files (*.BMP)\0*.bmp\0\0";
			ofn.lpstrCustomFilter = NULL;
			ofn.nMaxCustFilter = 0;
			ofn.nFilterIndex = 0;
			ofn.lpstrInitialDir= NULL;
			ofn.lpstrDefExt = "bmp";
			ofn.lpfnHook = NULL;
			ofn.lpTemplateName = NULL;
			ofn.nMaxFile = 255;
			ofn.lpstrTitle = NULL;
			ofn.nFileOffset = 0;
			ofn.nFileExtension = 0;
			ofn.lCustData = 0L;
			ofn.nMaxFileTitle = NULL;

			GetSaveFileName(&ofn);
			im->WriteBMPFile(ofn.lpstrFile);

			return 0;

		//Pop Adjust color dialog.  Set hourglass cause this could
		//take a while
		case ID_ADJUST_COLORBALANCE:
			DialogBoxParam(hInst, MAKEINTRESOURCE( IDD_DIALOG1 ), hwnd, 
				CamCtrProc, (LPARAM)&ccd );
			im->SetColorAdj(ccd.rgbqAdj);

			SetCursor(LoadCursor(NULL, IDC_WAIT));
			im->RawtoBMP();
			SetCursor(LoadCursor(NULL, IDC_ARROW));
			
			InvalidateRect(hwnd, NULL, FALSE);
			return 0;
		
		case ID_CONTROL_GO:
			CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);
			iSelection = LOWORD(wParam);
			CheckMenuItem(hMenu, iSelection, MF_CHECKED);

			SetEvent(hi->GethEventGoStop());
			return 0;

		//Cause hi to wait on event ... suspending itself
		case ID_CONTROL_STOP:
			CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);
			iSelection = LOWORD(wParam);
			CheckMenuItem(hMenu, iSelection, MF_CHECKED);

			ResetEvent(hi->GethEventGoStop());
			return 0;

		case ID_ABOUT_ABOUTCAMERACONTROL:
			DialogBox(hInst, MAKEINTRESOURCE( IDD_ABOUT ), hwnd, 
				AboutProc );
				return 0;
		}
		
		break;


	//Send by hi
	case WM_DOWNLOAD_STATUS:
		fPercentComplete = *(float*)wParam;
		InvalidateRect(hStatusBar, NULL, TRUE);
		return 0;

	//Owner draw status bar needs an update
	case WM_DRAWITEM:
		pdi = PDRAWITEMSTRUCT(lParam);
		rcProgressBar = pdi->rcItem;
		rcProgressBar.right =  (float)cyClient * fPercentComplete;
		rcProgressBar.top+=2;
		rcProgressBar.bottom-=2;

		//Just drawing it myself ... he he
		FillRect(pdi->hDC, &rcProgressBar, 
			(HBRUSH)GetStockObject (BLACK_BRUSH));
		
		return 0;
	
	//Make status bar update in size too
	case WM_SIZE:
		cxClient = LOWORD(lParam);
		cyClient = HIWORD(lParam);
		SendMessage(hStatusBar, WM_SIZE, 0, lParam);
		return 0;

	//Setup, init, create etc.
	case WM_CREATE:
		    
		hInst = ((LPCREATESTRUCT) lParam)->hInstance;
		cc.dwSize = sizeof(cc);
		cc.dwICC = ICC_BAR_CLASSES;
		InitCommonControlsEx(&cc);

		//Create memory for im and hi
		im = new image_manip;
		hi = new hardware_interface;

		//Initial Color adjust values
		ccd.rgbqAdj.rgbRed = 127;
		ccd.rgbqAdj.rgbGreen = 127;
		ccd.rgbqAdj.rgbBlue = 127;
		im->SetColorAdj(ccd.rgbqAdj);

		//Setup status bar
		hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, 
			"", hwnd, ID_STATUS_BAR);

		SendMessage(hStatusBar, SB_SETTEXT, SBT_OWNERDRAW , (LPARAM)"");

		//Grab a handle to the menu
		hMenu = GetMenu(hwnd);

		// Check if port opened ok
		if (hi->OpenedOK() == false)
		{
			wsprintf(szBuffer, "Couldn't Open Port");
			MessageBox (hwnd, szBuffer, "Error!", 
				MB_OK | MB_ICONINFORMATION);
			SendMessage(hwnd, WM_CLOSE, NULL, NULL);
		}
		
		//Startup thread to read from pport
		threadParams.hwnd = hwnd;
		threadParams.hi = hi;
		threadParams.im = im;
		_beginthread(GetImageThreadProc, 0, &threadParams);
		return 0;

	//Force a repaint when frame finished
	case WM_FRAME_FINISHED:			
		InvalidateRect(hwnd, NULL, TRUE);
		return 0;
	
	
	//Draw the bitmap onto the display.  I tried to stretch the bmp to 
	//fit the client, but it looks really ugly
	case WM_PAINT:
		
		pbmTemp = im->GetBitmap();
		bmpinfo.bmiHeader = *pbmTemp->pbih;
		hdc = BeginPaint(hwnd, &ps);
		
		SetDIBitsToDevice(
			hdc,
			0,
			0,
			pbmTemp->pbih->biWidth,
			pbmTemp->pbih->biHeight,
			0,
			0,
			0,
			pbmTemp->pbih->biHeight,
			pbmTemp->lpPixels,
			&bmpinfo,
			DIB_RGB_COLORS);
	
		EndPaint (hwnd, &ps);
		return 0;
	
	//Nice Doggy...  Make sure things shut down ok
	case WM_DESTROY:
		hi->EndThread();
		WaitForSingleObject(hi->GethEventThreadDead(), 5*1000);
		
		//Once everybody is done with it, delete it
		if(hi != 0) delete hi;
		if(im != 0) delete im;

		PostQuitMessage (0);
		return 0;
	}
	
	return DefWindowProc (hwnd, message, wParam, lParam);
}


/*******************************************************************

	Helper function for CamCtrProc function
	Sets the static text numbers below the sliders

*******************************************************************/
void UpdateBuddies(HWND *hCtrl, CAMCTR_DATA *pccd)
{
		TCHAR	szBuffer[32];
		
		wsprintf(szBuffer, "%d", pccd->rgbqAdj.rgbRed);
		SetWindowText(hCtrl[0], szBuffer);

		wsprintf(szBuffer, "%d", pccd->rgbqAdj.rgbGreen);
		SetWindowText(hCtrl[1], szBuffer);

		wsprintf(szBuffer, "%d", pccd->rgbqAdj.rgbBlue);
		SetWindowText(hCtrl[2], szBuffer);
}


/*******************************************************************

	Dialog box proc for adjust colors.  Sets up range for sliders
	on init.  Also sets the position of the sliders to where they
	were left last.  The sliders are upside down.  If I created
	them manually, I might be able to set the LEFTISDOWN param, but
	it does not seem to be supported.

*******************************************************************/
BOOL CALLBACK CamCtrProc (HWND hDlg, UINT message, WPARAM wParam,
						  LPARAM lParam)
{
	static	HWND hwndParent, hCtrl[6];
	static	CAMCTR_DATA	ccd, *pccd;	

	switch (message)
	{

	case WM_INITDIALOG:
		pccd = (CAMCTR_DATA*) lParam;
		ccd = *pccd;
		
		hCtrl[0] = GetDlgItem(hDlg, IDC_SLIDERRED);
		hCtrl[1] = GetDlgItem(hDlg, IDC_SLIDERGREEN);
		hCtrl[2] = GetDlgItem(hDlg, IDC_SLIDERBLUE);
		hCtrl[3] = GetDlgItem(hDlg, IDC_STATIC_REDVAL);
		hCtrl[4] = GetDlgItem(hDlg, IDC_STATIC_GREENVAL);
		hCtrl[5] = GetDlgItem(hDlg, IDC_STATIC_BLUEVAL);

		UpdateBuddies(&hCtrl[3], pccd);

		//Red
		SendMessage(hCtrl[0], TBM_SETRANGE, 
			(WPARAM) TRUE,                   // redraw flag 
			(LPARAM) MAKELONG(0, 255));  // min. & max. positions 

		SendMessage(hCtrl[0], TBM_SETPOS,
			(WPARAM) TRUE,                   // redraw flag 
			(LPARAM) ccd.rgbqAdj.rgbRed);  // min. & max. positions 

		//Green
		SendMessage(hCtrl[1], TBM_SETRANGE, 
			(WPARAM) TRUE,                   // redraw flag 
			(LPARAM) MAKELONG(0, 255));  // min. & max. positions 

		SendMessage(hCtrl[1], TBM_SETPOS,
			(WPARAM) TRUE,                   // redraw flag 
			(LPARAM) ccd.rgbqAdj.rgbGreen);  // min. & max. positions 

		//Blue
		SendMessage(hCtrl[2], TBM_SETRANGE, 
			(WPARAM) TRUE,                   // redraw flag 
			(LPARAM) MAKELONG(0, 255));  // min. & max. positions 

		SendMessage(hCtrl[2], TBM_SETPOS,
			(WPARAM) TRUE,                   // redraw flag 
			(LPARAM) ccd.rgbqAdj.rgbBlue);  // min. & max. positions 

		return true;
	
	case WM_VSCROLL:
		//The scroll bars are upside down ... 
		ccd.rgbqAdj.rgbRed = SendMessage(hCtrl[0], TBM_GETPOS, 0, 0) ;
		ccd.rgbqAdj.rgbGreen = SendMessage(hCtrl[1], TBM_GETPOS, 0, 0);
		ccd.rgbqAdj.rgbBlue = SendMessage(hCtrl[2], TBM_GETPOS, 0, 0) ;
		UpdateBuddies(&hCtrl[3], &ccd);

		return 0;

	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		
		case IDCANCEL:
			EndDialog(hDlg, FALSE);
			return true;
		
		case IDOK:
			*pccd = ccd; 
			EndDialog(hDlg, FALSE);
			return true;
		
		
		}
	}

	return false;
}

/*******************************************************************

	About Box.  Doesn't do much of anything... here for future 
	feature support!

*******************************************************************/
BOOL CALLBACK AboutProc (HWND hDlg, UINT message, WPARAM wParam,
						  LPARAM lParam)
{

	switch (message)
	{
	case WM_INITDIALOG:
		
		return true;
	
	case WM_COMMAND:
		if(LOWORD(wParam) == IDOK)
		{
			EndDialog(hDlg, FALSE);
			return true;
		}
	}

	return false;
}

⌨️ 快捷键说明

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