This is the latest WPILib src, VisionSample2013, cRIO image, ... pulled down from firstforge.wpi.edu.

There might be risks in using the top of tree rather than an official release, but the commit messages do mention fixes for some deadlocks and race conditions.

git-svn-id: https://robotics.mvla.net/svn/frc971/2013/trunk/src@4066 f308d9b7-e957-4cde-b6ac-9a88185e7312
diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCamera.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCamera.cpp
new file mode 100644
index 0000000..14aa4b3
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCamera.cpp
@@ -0,0 +1,501 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "Vision/AxisCamera.h"

+

+#include <string.h>

+#include "NetworkCommunication/UsageReporting.h"

+#include "Synchronized.h"

+#include "Vision/PCVideoServer.h"

+#include "WPIErrors.h"

+

+/** Private NI function to decode JPEG */

+IMAQ_FUNC int Priv_ReadJPEGString_C(Image* _image, const unsigned char* _string, UINT32 _stringLength);

+

+// Max packet without jumbo frames is 1500... add 36 because??

+#define kMaxPacketSize 1536

+#define kImageBufferAllocationIncrement 1000

+

+AxisCamera *AxisCamera::_instance = NULL;

+

+/**

+ * AxisCamera constructor

+ */

+AxisCamera::AxisCamera(const char *ipAddress)

+	: AxisCameraParams(ipAddress)

+	, m_cameraSocket(ERROR)

+	, m_protectedImageBuffer(NULL)

+	, m_protectedImageBufferLength(0)

+	, m_protectedImageSize(0)

+	, m_protectedImageSem(NULL)

+	, m_freshImage(false)

+	, m_imageStreamTask("cameraTask", (FUNCPTR)s_ImageStreamTaskFunction)

+	, m_videoServer(NULL)

+{

+	m_protectedImageSem = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);

+

+#if JAVA_CAMERA_LIB != 1

+	nUsageReporting::report(nUsageReporting::kResourceType_AxisCamera, ipAddress == NULL ? 1 : 2);

+#endif

+

+	if (!StatusIsFatal())

+		m_imageStreamTask.Start((int)this); 

+}

+

+/**

+ * Destructor

+ */

+AxisCamera::~AxisCamera()

+{

+	delete m_videoServer;

+	m_videoServer = NULL;

+

+	m_imageStreamTask.Stop();

+	close(m_cameraSocket);

+

+	SemSet_t::iterator it = m_newImageSemSet.begin();

+	SemSet_t::iterator end = m_newImageSemSet.end();

+	for (;it != end; it++)

+	{

+		semDelete(*it);

+	}

+	m_newImageSemSet.clear();

+

+	semDelete(m_protectedImageSem);

+}

+

+/**

+ * Get a pointer to the AxisCamera object, if the object does not exist, create it

+ * To use the camera on port 2 of a cRIO-FRC, pass "192.168.0.90" to the first GetInstance call.

+ * @return reference to AxisCamera object

+ */

+AxisCamera &AxisCamera::GetInstance(const char *cameraIP)

+{

+	if (NULL == _instance)

+	{

+		_instance = new AxisCamera(cameraIP);

+

+		_instance->m_videoServer = new PCVideoServer();

+	}

+

+	return *_instance;

+}

+

+/**

+ * Called by Java to delete the camera... how thoughtful

+ */

+void AxisCamera::DeleteInstance()

+{

+	delete _instance;

+	_instance = NULL;

+}

+

+/**

+ * Return true if the latest image from the camera has not been retrieved by calling GetImage() yet.

+ * @return true if the image has not been retrieved yet.

+ */

+bool AxisCamera::IsFreshImage()

+{

+	return m_freshImage;

+}

+

+/**

+ * Get the semaphore to be used to synchronize image access with camera acquisition

+ *

+ * Call semTake on the returned semaphore to block until a new image is acquired.

+ *

+ * The semaphore is owned by the AxisCamera class and will be deleted when the class is destroyed.

+ * @return A semaphore to notify when new image is received

+ */

+SEM_ID AxisCamera::GetNewImageSem()

+{

+	SEM_ID sem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);

+	m_newImageSemSet.insert(sem);

+	return sem;

+}

+

+/**

+ * Get an image from the camera and store it in the provided image.

+ * @param image The imaq image to store the result in. This must be an HSL or RGB image

+ * This function is called by Java.

+ * @return 1 upon success, zero on a failure

+ */

+int AxisCamera::GetImage(Image* imaqImage)

+{

+	if (m_protectedImageBuffer == NULL)

+		return 0;

+	Synchronized sync(m_protectedImageSem);

+	Priv_ReadJPEGString_C(imaqImage,

+		(unsigned char*)m_protectedImageBuffer, m_protectedImageSize);

+	m_freshImage = false;

+	return 1;

+}

+

+#if JAVA_CAMERA_LIB != 1

+/**

+ * Get an image from the camera and store it in the provided image.

+ * @param image The image to store the result in. This must be an HSL or RGB image

+ * @return 1 upon success, zero on a failure

+ */

+int AxisCamera::GetImage(ColorImage* image)

+{

+	return GetImage(image->GetImaqImage());

+}

+

+/**

+ * Instantiate a new image object and fill it with the latest image from the camera.

+ *

+ * The returned pointer is owned by the caller and is their responsibility to delete.

+ * @return a pointer to an HSLImage object

+ */

+HSLImage* AxisCamera::GetImage()

+{

+	HSLImage *image = new HSLImage();

+	GetImage(image);

+	return image;

+}

+#endif

+

+/**

+ * Copy an image into an existing buffer.

+ * This copies an image into an existing buffer rather than creating a new image

+ * in memory. That way a new image is only allocated when the image being copied is

+ * larger than the destination.

+ * This method is called by the PCVideoServer class.

+ * @param imageData The destination image.

+ * @param numBytes The size of the destination image.

+ * @return 0 if failed (no source image or no memory), 1 if success.

+ */

+int AxisCamera::CopyJPEG(char **destImage, int &destImageSize, int &destImageBufferSize)

+{

+	Synchronized sync(m_protectedImageSem);

+	if (destImage == NULL)

+		wpi_setWPIErrorWithContext(NullParameter, "destImage must not be NULL");

+

+	if (m_protectedImageBuffer == NULL || m_protectedImageSize <= 0)

+		return 0; // if no source image

+

+	if (destImageBufferSize < m_protectedImageSize) // if current destination buffer too small

+	{

+		if (*destImage != NULL) delete [] *destImage;

+		destImageBufferSize = m_protectedImageSize + kImageBufferAllocationIncrement;

+		*destImage = new char[destImageBufferSize];

+		if (*destImage == NULL) return 0;

+	}

+	// copy this image into destination buffer

+	if (*destImage == NULL)

+	{

+		wpi_setWPIErrorWithContext(NullParameter, "*destImage must not be NULL");

+	}

+	// TODO: Is this copy realy necessary... perhaps we can simply transmit while holding the protected buffer

+	memcpy(*destImage, m_protectedImageBuffer, m_protectedImageSize);

+	destImageSize = m_protectedImageSize;

+	return 1;

+}

+

+/**

+ * Static interface that will cause an instantiation if necessary.

+ * This static stub is directly spawned as a task to read images from the camera.

+ */

+int AxisCamera::s_ImageStreamTaskFunction(AxisCamera *thisPtr)

+{

+	return thisPtr->ImageStreamTaskFunction();

+}

+

+/**

+ * Task spawned by AxisCamera constructor to receive images from cam

+ * If setNewImageSem has been called, this function does a semGive on each new image

+ * Images can be accessed by calling getImage()

+ */

+int AxisCamera::ImageStreamTaskFunction()

+{

+	// Loop on trying to setup the camera connection. This happens in a background

+	// thread so it shouldn't effect the operation of user programs.

+	while (1)

+	{

+		const char *requestString = "GET /mjpg/video.mjpg HTTP/1.1\n\

+User-Agent: HTTPStreamClient\n\

+Connection: Keep-Alive\n\

+Cache-Control: no-cache\n\

+Authorization: Basic RlJDOkZSQw==\n\n";

+		semTake(m_socketPossessionSem, WAIT_FOREVER);

+		m_cameraSocket = CreateCameraSocket(requestString);

+		if (m_cameraSocket == ERROR)

+		{

+			// Don't hammer the camera if it isn't ready.

+			semGive(m_socketPossessionSem);

+			taskDelay(1000);

+		}

+		else

+		{

+			ReadImagesFromCamera();

+		}

+	}

+}

+

+/**

+ * This function actually reads the images from the camera.

+ */

+int AxisCamera::ReadImagesFromCamera()

+{

+	char *imgBuffer = NULL;

+	int imgBufferLength = 0;

+	//Infinite loop, task deletion handled by taskDeleteHook

+	// Socket cleanup handled by destructor

+

+	// TODO: these recv calls must be non-blocking. Otherwise if the camera

+	// fails during a read, the code hangs and never retries when the camera comes

+	// back up.

+

+	int counter = 2;

+	while (1)

+	{

+		char initialReadBuffer[kMaxPacketSize] = "";

+		char intermediateBuffer[1];

+		char *trailingPtr = initialReadBuffer;

+		int trailingCounter = 0;

+		while (counter)

+		{

+			// TODO: fix me... this cannot be the most efficient way to approach this, reading one byte at a time.

+			if(recv(m_cameraSocket, intermediateBuffer, 1, 0) == ERROR)

+			{

+				wpi_setErrnoErrorWithContext("Failed to read image header");

+				close (m_cameraSocket);

+				return ERROR;

+			}

+			strncat(initialReadBuffer, intermediateBuffer, 1);

+			// trailingCounter ensures that we start looking for the 4 byte string after

+			// there is at least 4 bytes total. Kind of obscure.

+			// look for 2 blank lines (\r\n)

+			if (NULL != strstr(trailingPtr, "\r\n\r\n"))

+			{

+				--counter;

+			}

+			if (++trailingCounter >= 4)

+			{

+				trailingPtr++;

+			}

+		}

+		counter = 1;

+		char *contentLength = strstr(initialReadBuffer, "Content-Length: ");

+		if (contentLength == NULL)

+		{

+			wpi_setWPIErrorWithContext(IncompatibleMode, "No content-length token found in packet");

+			close(m_cameraSocket);

+			return ERROR;

+		}

+		contentLength = contentLength + 16; // skip past "content length"

+		int readLength = atol(contentLength); // get the image byte count

+

+		// Make sure buffer is large enough

+		if (imgBufferLength < readLength)

+		{

+			if (imgBuffer) delete[] imgBuffer;

+			imgBufferLength = readLength + kImageBufferAllocationIncrement;

+			imgBuffer = new char[imgBufferLength];

+			if (imgBuffer == NULL)

+			{

+				imgBufferLength = 0;

+				continue;

+			}

+		}

+

+		// Read the image data for "Content-Length" bytes

+		int bytesRead = 0;

+		int remaining = readLength;

+		while(bytesRead < readLength)

+		{

+			int bytesThisRecv = recv(m_cameraSocket, &imgBuffer[bytesRead], remaining, 0);

+			bytesRead += bytesThisRecv;

+			remaining -= bytesThisRecv;

+		}

+		// Update image

+		UpdatePublicImageFromCamera(imgBuffer, readLength);

+		if (semTake(m_paramChangedSem, NO_WAIT) == OK)

+		{

+			// params need to be updated: close the video stream; release the camera.

+			close(m_cameraSocket);

+			semGive(m_socketPossessionSem);

+			return 0;

+		}

+	}

+}

+

+/**

+ * Copy the image from private buffer to shared buffer.

+ * @param imgBuffer The buffer containing the image

+ * @param bufLength The length of the image

+ */

+void AxisCamera::UpdatePublicImageFromCamera(char *imgBuffer, int imgSize)

+{

+	{

+		Synchronized sync(m_protectedImageSem);

+

+		// Adjust the buffer size if current destination buffer is too small.

+		if (m_protectedImageBufferLength < imgSize)

+		{

+			if (m_protectedImageBuffer != NULL) delete [] m_protectedImageBuffer;

+			m_protectedImageBufferLength = imgSize + kImageBufferAllocationIncrement;

+			m_protectedImageBuffer = new char[m_protectedImageBufferLength];

+			if (m_protectedImageBuffer == NULL)

+			{

+				m_protectedImageBufferLength = 0;

+				return;

+			}

+		}

+

+		memcpy(m_protectedImageBuffer, imgBuffer, imgSize);

+		m_protectedImageSize = imgSize;

+	}

+

+	m_freshImage = true;

+	// Notify everyone who is interested.

+	SemSet_t::iterator it = m_newImageSemSet.begin();

+	SemSet_t::iterator end = m_newImageSemSet.end();

+	for (;it != end; it++)

+	{

+		semGive(*it);

+	}

+}

+

+/**

+ * Implement the pure virtual interface so that when parameter changes require a restart, the image task can be bounced.

+ */

+void AxisCamera::RestartCameraTask()

+{

+	m_imageStreamTask.Stop();

+	m_imageStreamTask.Start((int)this);

+}

+

+#if JAVA_CAMERA_LIB == 1

+

+// C bindings used by Java

+// These need to stay as is or Java has to change

+

+void AxisCameraStart(const char *IPAddress)

+{

+#ifdef SVN_REV

+	if (strlen(SVN_REV))

+	{

+		printf("JavaCameraLib was compiled from SVN revision %s\n", SVN_REV);

+	}

+	else

+	{

+		printf("JavaCameraLib was compiled from a location that is not source controlled.\n");

+	}

+#else

+	printf("JavaCameraLib was compiled without -D'SVN_REV=nnnn'\n");

+#endif

+	AxisCamera::GetInstance(IPAddress);

+}

+

+int AxisCameraGetImage (Image* image)

+{

+	return AxisCamera::GetInstance().GetImage(image);

+}

+

+void AxisCameraWriteBrightness(int brightness)

+{

+	AxisCamera::GetInstance().WriteBrightness(brightness);

+}

+

+int AxisCameraGetBrightness()

+{

+	return AxisCamera::GetInstance().GetBrightness();

+}

+

+void AxisCameraWriteWhiteBalance(AxisCameraParams::WhiteBalance_t whiteBalance)

+{

+	AxisCamera::GetInstance().WriteWhiteBalance(whiteBalance);

+}

+

+AxisCameraParams::WhiteBalance_t AxisCameraGetWhiteBalance()

+{

+	return AxisCamera::GetInstance().GetWhiteBalance();

+}

+

+void AxisCameraWriteColorLevel(int colorLevel)

+{

+	AxisCamera::GetInstance().WriteColorLevel(colorLevel);

+}

+

+int AxisCameraGetColorLevel()

+{

+	return AxisCamera::GetInstance().GetColorLevel();

+}

+

+void AxisCameraWriteExposureControl(AxisCameraParams::Exposure_t exposure)

+{

+	AxisCamera::GetInstance().WriteExposureControl(exposure);

+}

+

+AxisCameraParams::Exposure_t AxisCameraGetExposureControl()

+{

+	return AxisCamera::GetInstance().GetExposureControl();

+}

+

+void AxisCameraWriteExposurePriority(int exposure)

+{

+	AxisCamera::GetInstance().WriteExposurePriority(exposure);

+}

+

+int AxisCameraGetExposurePriority()

+{

+	return AxisCamera::GetInstance().GetExposurePriority();

+}

+

+void AxisCameraWriteMaxFPS(int maxFPS)

+{

+	AxisCamera::GetInstance().WriteMaxFPS(maxFPS);

+}

+

+int AxisCameraGetMaxFPS()

+{

+	return AxisCamera::GetInstance().GetMaxFPS();

+}

+

+void AxisCameraWriteResolution(AxisCameraParams::Resolution_t resolution)

+{

+	AxisCamera::GetInstance().WriteResolution(resolution);

+}

+

+AxisCameraParams::Resolution_t AxisCameraGetResolution()

+{

+	return AxisCamera::GetInstance().GetResolution();

+}

+

+void AxisCameraWriteCompression(int compression)

+{

+	AxisCamera::GetInstance().WriteCompression(compression);

+}

+

+int AxisCameraGetCompression()

+{

+	return AxisCamera::GetInstance().GetCompression();

+}

+

+void AxisCameraWriteRotation(AxisCameraParams::Rotation_t rotation)

+{

+	AxisCamera::GetInstance().WriteRotation(rotation);

+}

+

+AxisCameraParams::Rotation_t AxisCameraGetRotation()

+{

+	return AxisCamera::GetInstance().GetRotation();

+}

+

+void AxisCameraDeleteInstance()

+{

+	AxisCamera::DeleteInstance();

+}

+

+int AxisCameraFreshImage()

+{

+	return AxisCamera::GetInstance().IsFreshImage();

+}

+

+#endif // JAVA_CAMERA_LIB == 1

+

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCamera.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCamera.h
new file mode 100644
index 0000000..ba889b7
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCamera.h
@@ -0,0 +1,114 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __AXIS_CAMERA_H__

+#define __AXIS_CAMERA_H__

+

+#include <taskLib.h>

+#include <vxWorks.h> 

+#include <sockLib.h> 

+#include <inetLib.h>

+

+#include "Vision/AxisCameraParams.h"

+#if JAVA_CAMERA_LIB != 1

+#include "Vision/ColorImage.h"

+#include "Vision/HSLImage.h"

+#endif

+#include "nivision.h"

+#include <set>

+#include "Task.h"

+

+class PCVideoServer;

+

+/**

+ * AxisCamera class.

+ * This class handles everything about the Axis 206 FRC Camera.

+ * It starts up 2 tasks each using a different connection to the camera:

+ * - image reading task that reads images repeatedly from the camera

+ * - parameter handler task in the base class that monitors for changes to

+ *     parameters and updates the camera

+ */

+class AxisCamera : public AxisCameraParams

+{

+private:

+	explicit AxisCamera(const char *cameraIP);

+public:

+	virtual ~AxisCamera();

+	static AxisCamera& GetInstance(const char *cameraIP = NULL);

+	static void DeleteInstance();

+

+	bool IsFreshImage();

+	SEM_ID GetNewImageSem();

+

+	int GetImage(Image *imaqImage);

+#if JAVA_CAMERA_LIB != 1

+	int GetImage(ColorImage *image);

+	HSLImage *GetImage();

+#endif

+

+	int CopyJPEG(char **destImage, int &destImageSize, int &destImageBufferSize);

+

+private:

+	static int s_ImageStreamTaskFunction(AxisCamera *thisPtr);

+	int ImageStreamTaskFunction();

+

+	int ReadImagesFromCamera();

+	void UpdatePublicImageFromCamera(char *imgBuffer, int imgSize);

+

+	virtual void RestartCameraTask();

+

+	static AxisCamera *_instance;

+	int m_cameraSocket;

+	typedef std::set<SEM_ID> SemSet_t;

+	SemSet_t m_newImageSemSet;

+

+	char* m_protectedImageBuffer;

+	int m_protectedImageBufferLength;

+	int m_protectedImageSize;

+	SEM_ID m_protectedImageSem;

+	bool m_freshImage;

+

+	Task m_imageStreamTask;

+

+	PCVideoServer *m_videoServer;

+};

+

+#if JAVA_CAMERA_LIB == 1

+#ifdef __cplusplus

+extern "C" {

+#endif

+	void AxisCameraStart(const char *IPAddress);

+	int AxisCameraGetImage(Image *image);

+	void AxisCameraDeleteInstance();

+	int AxisCameraFreshImage();

+

+	// Mid-stream gets & writes

+	void AxisCameraWriteBrightness(int brightness);

+	int AxisCameraGetBrightness();

+	void AxisCameraWriteWhiteBalance(AxisCameraParams::WhiteBalance_t whiteBalance);

+	AxisCameraParams::WhiteBalance_t AxisCameraGetWhiteBalance();

+	void AxisCameraWriteColorLevel(int colorLevel);

+	int AxisCameraGetColorLevel();

+	void AxisCameraWriteExposureControl(AxisCameraParams::Exposure_t exposure);

+	AxisCameraParams::Exposure_t AxisCameraGetExposureControl();

+	void AxisCameraWriteExposurePriority(int exposurePriority);

+	int AxisCameraGetExposurePriority();

+	void AxisCameraWriteMaxFPS(int maxFPS);

+	int AxisCameraGetMaxFPS();

+

+	// New-Stream gets & writes

+	void AxisCameraWriteResolution(AxisCameraParams::Resolution_t resolution);

+	AxisCameraParams::Resolution_t AxisCameraGetResolution();

+	void AxisCameraWriteCompression(int compression);

+	int AxisCameraGetCompression();

+	void AxisCameraWriteRotation(AxisCameraParams::Rotation_t rotation);

+	AxisCameraParams::Rotation_t AxisCameraGetRotation();

+#ifdef __cplusplus

+}

+#endif

+#endif // JAVA_CAMERA_LIB == 1

+

+#endif

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCameraParams.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCameraParams.cpp
new file mode 100644
index 0000000..9d429e4
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCameraParams.cpp
@@ -0,0 +1,469 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "Vision/AxisCameraParams.h"

+

+#include "Vision/AxisCamera.h"

+#include <inetLib.h>

+#include "pcre.h"

+#include <sockLib.h>

+#include <string.h>

+#include "Synchronized.h"

+#include "Timer.h"

+#include "Utility.h"

+#include "WPIErrors.h"

+

+#if JAVA_CAMERA_LIB != 1

+#include "DriverStation.h"

+#endif

+

+static const char *const kRotationChoices[] = {"0", "180"};

+static const char *const kResolutionChoices[] = {"640x480", "640x360", "320x240", "160x120"};

+static const char *const kExposureControlChoices[] = { "automatic", "hold", "flickerfree50", "flickerfree60" };

+static const char *const kWhiteBalanceChoices[] = { "auto", "holdwb", "fixed_outdoor1",

+		"fixed_outdoor2", "fixed_indoor", "fixed_fluor1", "fixed_fluor2" };

+

+/**

+ * AxisCamera constructor

+ */

+AxisCameraParams::AxisCameraParams(const char* ipAddress)

+	: m_paramTask("paramTask", (FUNCPTR) s_ParamTaskFunction)

+	, m_paramChangedSem (NULL)

+	, m_socketPossessionSem (NULL)

+	, m_brightnessParam (NULL)

+	, m_compressionParam (NULL)

+	, m_exposurePriorityParam (NULL)

+	, m_colorLevelParam (NULL)

+	, m_maxFPSParam (NULL)

+	, m_rotationParam (NULL)

+	, m_resolutionParam (NULL)

+	, m_exposureControlParam (NULL)

+	, m_whiteBalanceParam (NULL)

+{

+	if (ipAddress == NULL || strlen(ipAddress) == 0)

+	{

+#if JAVA_CAMERA_LIB == 1

+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "IP Address must be specified");

+		return;

+#else

+		DriverStation *ds = DriverStation::GetInstance();

+		ds->WaitForData();

+		UINT16 teamNumber = ds->GetTeamNumber();

+		char cameraIP[16];

+		snprintf(cameraIP, 16, "10.%d.%d.11", teamNumber / 100, teamNumber % 100);

+		m_ipAddress = inet_addr(cameraIP);

+#endif

+	}

+	else

+	{

+		m_ipAddress = inet_addr((char*)ipAddress);

+	}

+

+	if (m_ipAddress == (u_long)ERROR)

+	{

+		wpi_setErrnoError();

+		return;

+	}

+

+	m_brightnessParam = new IntCameraParameter("ImageSource.I0.Sensor.Brightness=%i",

+			"root.ImageSource.I0.Sensor.Brightness=(.*)", false);

+	m_parameters.push_back(m_brightnessParam);

+	m_colorLevelParam = new IntCameraParameter("ImageSource.I0.Sensor.ColorLevel=%i",

+			"root.ImageSource.I0.Sensor.ColorLevel=(.*)", false);

+	m_parameters.push_back(m_colorLevelParam);

+	m_exposurePriorityParam = new IntCameraParameter("ImageSource.I0.Sensor.exposurePriority=%i",

+			"root.ImageSource.I0.Sensor.ExposurePriority=(.*)", false);

+	m_parameters.push_back(m_exposurePriorityParam);

+	m_compressionParam = new IntCameraParameter("Image.I0.Appearance.Compression=%i",

+			"root.Image.I0.Appearance.Compression=(.*)", true);

+	m_parameters.push_back(m_compressionParam);

+	m_maxFPSParam = new IntCameraParameter("Image.I0.Stream.FPS=%i",

+			"root.Image.I0.Stream.FPS=(.*)", false);

+	m_parameters.push_back(m_maxFPSParam);

+	m_rotationParam = new EnumCameraParameter("Image.I0.Appearance.Rotation=%s",

+			"root.Image.I0.Appearance.Rotation=(.*)", true, kRotationChoices, sizeof(kRotationChoices)/sizeof(kRotationChoices[0]));

+	m_parameters.push_back(m_rotationParam);

+	m_resolutionParam = new EnumCameraParameter("Image.I0.Appearance.Resolution=%s",

+			"root.Image.I0.Appearance.Resolution=(.*)", true, kResolutionChoices, sizeof(kResolutionChoices)/sizeof(kResolutionChoices[0]));

+	m_parameters.push_back(m_resolutionParam);

+	m_exposureControlParam = new EnumCameraParameter("ImageSource.I0.Sensor.Exposure=%s",

+			"root.ImageSource.I0.Sensor.Exposure=(.*)", false, kExposureControlChoices, sizeof(kExposureControlChoices)/sizeof(kExposureControlChoices[0]));

+	m_parameters.push_back(m_exposureControlParam);

+	m_whiteBalanceParam = new EnumCameraParameter("ImageSource.IO.Sensor.WhiteBalance=%s",

+			"root.ImageSource.I0.Sensor.WhiteBalance=(.*)", false, kWhiteBalanceChoices, sizeof(kWhiteBalanceChoices)/sizeof(kWhiteBalanceChoices[0]));

+	m_parameters.push_back(m_whiteBalanceParam);

+

+	m_paramChangedSem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);

+	m_socketPossessionSem = semBCreate (SEM_Q_PRIORITY, SEM_FULL);

+

+	m_paramTask.Start((int)this);

+}

+

+/**

+ * Destructor

+ */

+AxisCameraParams::~AxisCameraParams()

+{

+	m_paramTask.Stop();

+

+	semDelete(m_socketPossessionSem);

+	semDelete(m_paramChangedSem);

+

+	delete m_whiteBalanceParam;

+	delete m_exposureControlParam;

+	delete m_resolutionParam;

+	delete m_rotationParam;

+	delete m_maxFPSParam;

+	delete m_compressionParam;

+	delete m_exposurePriorityParam;

+	delete m_colorLevelParam;

+	delete m_brightnessParam;

+}

+

+/**

+ * Static function to start the parameter updating task

+ */

+int AxisCameraParams::s_ParamTaskFunction(AxisCameraParams* thisPtr)

+{

+	return thisPtr->ParamTaskFunction();

+}

+

+/**

+ * Main loop of the parameter task.

+ * This loop runs continuously checking parameters from the camera for

+ * posted changes and updating them if necessary.

+ */

+// TODO: need to synchronize the actual setting of parameters (the assignment statement)

+int AxisCameraParams::ParamTaskFunction()

+{

+	static bool firstTime = true;

+

+	while (true)

+	{

+		semTake(m_socketPossessionSem, WAIT_FOREVER);

+		if (firstTime)

+		{

+			while (ReadCamParams() == 0);

+			firstTime = false;

+		}

+		bool restartRequired = false;

+

+		ParameterVector_t::iterator it = m_parameters.begin();

+		ParameterVector_t::iterator end = m_parameters.end();

+		for(; it != end; it++)

+		{

+			bool changed = false;

+			char param[150];

+			restartRequired |= (*it)->CheckChanged(changed, param);

+			if (changed)

+			{

+				UpdateCamParam(param);

+			}

+		}

+		if (restartRequired)

+		{

+			RestartCameraTask();

+		}

+		semGive(m_socketPossessionSem);

+	}

+	return 0;

+}

+

+/**

+ * Write the brightness value to the camera.

+ * @param brightness valid values 0 .. 100

+ */

+void AxisCameraParams::WriteBrightness(int brightness)

+{

+	m_brightnessParam->SetValue(brightness);

+	semGive(m_paramChangedSem);

+}

+

+/**

+ * Get the brightness value.

+ * @return Brightness value from the camera.

+ */

+int AxisCameraParams::GetBrightness()

+{

+	return m_brightnessParam->GetValue();

+}

+

+/**

+ * Set the white balance value.

+ * @param whiteBalance Valid values from the WhiteBalance_t enum.

+ */

+void AxisCameraParams::WriteWhiteBalance(WhiteBalance_t whiteBalance)

+{

+	m_whiteBalanceParam->SetValue(whiteBalance);

+	semGive(m_paramChangedSem);

+}

+

+/**

+ * Retrieve the current white balance parameter.

+ * @return The white balance value.

+ */

+AxisCameraParams::WhiteBalance_t AxisCameraParams::GetWhiteBalance()

+{

+	return (WhiteBalance_t) m_whiteBalanceParam->GetValue();

+}

+

+/**

+ * Write the color level to the camera.

+ * @param colorLevel valid values are 0 .. 100

+ */

+void AxisCameraParams::WriteColorLevel(int colorLevel)

+{

+	m_colorLevelParam->SetValue(colorLevel);

+	semGive(m_paramChangedSem);

+}

+

+/**

+ * Retrieve the color level from the camera.

+ * @Returns the camera color level.

+ */

+int AxisCameraParams::GetColorLevel()

+{

+	return m_colorLevelParam->GetValue();

+}

+

+/**

+ * Write the exposure control value to the camera.

+ * @param exposureControl A mode to write in the Exposure_t enum.

+ */

+void AxisCameraParams::WriteExposureControl(Exposure_t exposureControl)

+{

+	m_exposureControlParam->SetValue(exposureControl);

+	semGive(m_paramChangedSem);

+}

+

+/**

+ * Get the exposure value from the camera.

+ * @returns the exposure value from the camera.

+ */

+AxisCameraParams::Exposure_t AxisCameraParams::GetExposureControl()

+{

+	return (Exposure_t) m_exposureControlParam->GetValue();

+}

+

+/**

+ * Write resolution value to camera.

+ * @param resolution The camera resolution value to write to the camera.  Use the Resolution_t enum.

+ */

+void AxisCameraParams::WriteResolution(Resolution_t resolution)

+{

+	m_resolutionParam->SetValue(resolution);

+	semGive(m_paramChangedSem);

+}

+

+/**

+ * Get the resolution value from the camera.

+ * @returns resultion value for the camera.

+ */

+AxisCameraParams::Resolution_t AxisCameraParams::GetResolution()

+{

+	return (Resolution_t) m_resolutionParam->GetValue();

+}

+

+/**

+ * Write the exposre priority value to the camera.

+ * @param exposurePriority Valid values are 0, 50, 100.

+ * 0 = Prioritize image quality

+ * 50 = None

+ * 100 = Prioritize frame rate

+ */

+void AxisCameraParams::WriteExposurePriority(int exposurePriority)

+{

+	m_exposurePriorityParam->SetValue(exposurePriority);

+	semGive(m_paramChangedSem);

+}

+

+int AxisCameraParams::GetExposurePriority()

+{

+	return m_exposurePriorityParam->GetValue();

+}

+

+/**

+ * Write the rotation value to the camera.

+ * If you mount your camera upside down, use this to adjust the image for you.

+ * @param rotation The image from the Rotation_t enum in AxisCameraParams (kRotation_0 or kRotation_180)

+ */

+void AxisCameraParams::WriteRotation(Rotation_t rotation)

+{

+	m_rotationParam->SetValue(rotation);

+	semGive(m_paramChangedSem);

+}

+

+/**

+ * Get the rotation value from the camera.

+ * @return The rotation value from the camera (Rotation_t).

+ */

+AxisCameraParams::Rotation_t AxisCameraParams::GetRotation()

+{

+	return (Rotation_t) m_rotationParam->GetValue();

+}

+

+/**

+ * Write the compression value to the camera.

+ * @param compression Values between 0 and 100.

+ */

+

+void AxisCameraParams::WriteCompression(int compression)

+{

+	m_compressionParam->SetValue(compression);

+	semGive(m_paramChangedSem);

+}

+

+/**

+ * Get the compression value from the camera.

+ * @return The cached compression value from the camera.

+ */

+int AxisCameraParams::GetCompression()

+{

+	return m_compressionParam->GetValue();

+}

+

+/**

+ * Write the maximum frames per second that the camera should send

+ * Write 0 to send as many as possible.

+ * @param maxFPS The number of frames the camera should send in a second, exposure permitting.

+ */

+void AxisCameraParams::WriteMaxFPS(int maxFPS)

+{

+	m_maxFPSParam->SetValue(maxFPS);

+	semGive(m_paramChangedSem);

+}

+

+/**

+ * Get the max number of frames per second that the camera will send

+ * @return Maximum frames per second.

+ */

+int AxisCameraParams::GetMaxFPS()

+{

+	return m_maxFPSParam->GetValue();

+}

+

+/**

+ * Update a camera parameter.

+ * Write a camera parameter to the camera when it has bene changed.

+ * @param param the string to insert into the http request.

+ * @returns 0 if it failed, otherwise nonzero.

+ */

+int AxisCameraParams::UpdateCamParam(const char* param)

+{

+	char *requestString =

+		"GET /axis-cgi/admin/param.cgi?action=update&%s HTTP/1.1\n\

+User-Agent: HTTPStreamClient\n\

+Connection: Keep-Alive\n\

+Cache-Control: no-cache\n\

+Authorization: Basic RlJDOkZSQw==\n\n";

+	char completedRequest[1024];

+	sprintf(completedRequest, requestString, param);

+	// Send request

+	int camSocket = CreateCameraSocket(completedRequest);

+	if (camSocket == ERROR)

+	{

+		printf("UpdateCamParam failed: %s\n", param);

+		return 0;

+	}

+	close(camSocket);

+	return 1;

+}

+

+/**

+ * Read the full param list from camera, use regular expressions to find the bits we care about

+ * assign values to member variables.

+ */

+int AxisCameraParams::ReadCamParams()

+{

+	char * requestString =

+		"GET /axis-cgi/admin/param.cgi?action=list HTTP/1.1\n\

+User-Agent: HTTPStreamClient\n\

+Connection: Keep-Alive\n\

+Cache-Control: no-cache\n\

+Authorization: Basic RlJDOkZSQw==\n\n";

+

+	int camSocket = CreateCameraSocket(requestString);

+	if (camSocket == ERROR)

+	{

+		return 0;

+	}

+	// Allocate on the heap since it is very large and only needed once

+	char *readBuffer = new char[27000];

+	int totalRead = 0;

+	while (1)

+	{

+		wpi_assert(totalRead < 26000);

+		int bytesRead = recv(camSocket, &readBuffer[totalRead], 1000, 0);

+		if (bytesRead == ERROR)

+		{

+			wpi_setErrnoErrorWithContext("Failed to read image header");

+			close(camSocket);

+			return 0;

+		}

+		else if (bytesRead <= 0)

+		{

+			break;

+		}

+		totalRead += bytesRead;

+	}

+	readBuffer[totalRead] = '\0';

+

+	ParameterVector_t::iterator it = m_parameters.begin();

+	ParameterVector_t::iterator end = m_parameters.end();

+	for(; it != end; it++)

+	{

+		(*it)->GetParamFromString(readBuffer, totalRead);

+	}

+	close(camSocket);

+	delete [] readBuffer;

+	return 1;

+}

+

+/*

+ * Create a socket connected to camera

+ * Used to create a connection to the camera by both AxisCameraParams and AxisCamera.

+ * @param requestString The initial request string to send upon successful connection.

+ * @return ERROR if failed, socket handle if successful.

+ */

+int AxisCameraParams::CreateCameraSocket(const char *requestString)

+{

+	int sockAddrSize;

+	struct sockaddr_in serverAddr;

+	int camSocket;

+	/* create socket */

+	if ((camSocket = socket(AF_INET, SOCK_STREAM, 0)) == ERROR)

+	{

+		wpi_setErrnoErrorWithContext("Failed to create the camera socket");

+		return ERROR;

+	}

+

+	sockAddrSize = sizeof(struct sockaddr_in);

+	bzero((char *) &serverAddr, sockAddrSize);

+	serverAddr.sin_family = AF_INET;

+	serverAddr.sin_len = (u_char) sockAddrSize;

+	serverAddr.sin_port = htons(80);

+

+	serverAddr.sin_addr.s_addr = m_ipAddress;

+

+	/* connect to server */

+	struct timeval connectTimeout;

+	connectTimeout.tv_sec = 5;

+	connectTimeout.tv_usec = 0;

+	if (connectWithTimeout(camSocket, (struct sockaddr *) &serverAddr, sockAddrSize, &connectTimeout) == ERROR)

+	{

+		wpi_setErrnoErrorWithContext("Failed to connect to the camera");

+		close(camSocket);

+		return ERROR;

+	}

+	int sent = send(camSocket, requestString, strlen(requestString), 0);

+	if (sent == ERROR)

+	{

+		wpi_setErrnoErrorWithContext("Failed to send a request to the camera");

+		close(camSocket);

+		return ERROR;

+	}

+	return camSocket;

+}

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCameraParams.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCameraParams.h
new file mode 100644
index 0000000..e5816ee
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/AxisCameraParams.h
@@ -0,0 +1,90 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __AXIS_CAMERA_PARAMS_H__

+#define __AXIS_CAMERA_PARAMS_H__

+

+#include "EnumCameraParameter.h"

+#include "ErrorBase.h"

+#include "IntCameraParameter.h"

+#include "Task.h"

+#include <vector>

+

+/**

+ * AxisCameraParams class.

+ * This class handles parameter configuration the Axis 206 Ethernet Camera.

+ * It starts up a tasks with an independent connection to the camera that monitors

+ * for changes to parameters and updates the camera.

+ * It is only separate from AxisCamera to isolate the parameter code from the image streaming code.

+ */

+class AxisCameraParams : public ErrorBase

+{

+public:

+	typedef enum Exposure_t {kExposure_Automatic, kExposure_Hold, kExposure_FlickerFree50Hz, kExposure_FlickerFree60Hz};

+	typedef enum WhiteBalance_t {kWhiteBalance_Automatic, kWhiteBalance_Hold, kWhiteBalance_FixedOutdoor1, kWhiteBalance_FixedOutdoor2, kWhiteBalance_FixedIndoor, kWhiteBalance_FixedFlourescent1, kWhiteBalance_FixedFlourescent2};

+	typedef enum Resolution_t {kResolution_640x480, kResolution_640x360, kResolution_320x240, kResolution_160x120};

+	typedef enum Rotation_t {kRotation_0, kRotation_180};

+

+protected:

+	AxisCameraParams(const char* ipAddress);

+	virtual ~AxisCameraParams();

+

+public:

+	// Mid-stream gets & writes

+	void WriteBrightness(int);

+	int GetBrightness();

+	void WriteWhiteBalance(WhiteBalance_t whiteBalance);

+	WhiteBalance_t GetWhiteBalance();

+	void WriteColorLevel(int);

+	int GetColorLevel();

+	void WriteExposureControl(Exposure_t);

+	Exposure_t GetExposureControl();

+	void WriteExposurePriority(int);

+	int GetExposurePriority();

+	void WriteMaxFPS(int);

+	int GetMaxFPS();

+

+	// New-Stream gets & writes (i.e. require restart)

+	void WriteResolution(Resolution_t);

+	Resolution_t GetResolution();

+	void WriteCompression(int);

+	int GetCompression();

+	void WriteRotation(Rotation_t);

+	Rotation_t GetRotation();

+

+protected:

+	virtual void RestartCameraTask() = 0;

+	int CreateCameraSocket(const char *requestString);

+

+	static int s_ParamTaskFunction(AxisCameraParams* thisPtr);

+	int ParamTaskFunction();

+

+	int UpdateCamParam(const char *param);

+	int ReadCamParams();

+

+	Task m_paramTask;

+	UINT32 m_ipAddress; // IPv4

+	SEM_ID m_paramChangedSem;

+	SEM_ID m_socketPossessionSem;

+

+	//Camera Properties

+	IntCameraParameter *m_brightnessParam;

+	IntCameraParameter *m_compressionParam;

+	IntCameraParameter *m_exposurePriorityParam;

+	IntCameraParameter *m_colorLevelParam;

+	IntCameraParameter *m_maxFPSParam;

+	EnumCameraParameter *m_rotationParam;

+	EnumCameraParameter *m_resolutionParam;

+	EnumCameraParameter *m_exposureControlParam;

+	EnumCameraParameter *m_whiteBalanceParam;

+

+	// A vector to access all properties simply.

+	typedef std::vector<IntCameraParameter*> ParameterVector_t;

+	ParameterVector_t m_parameters;

+};

+

+

+#endif

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/BinaryImage.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/BinaryImage.cpp
new file mode 100644
index 0000000..83d37c6
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/BinaryImage.cpp
@@ -0,0 +1,222 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "BinaryImage.h"

+#include "WPIErrors.h"

+

+/** Private NI function needed to write to the VxWorks target */

+IMAQ_FUNC int Priv_SetWriteFileAllowed(UINT32 enable); 

+

+BinaryImage::BinaryImage() : MonoImage()

+{

+}

+

+BinaryImage::~BinaryImage()

+{

+}

+

+/**

+ * Get then number of particles for the image.

+ * @returns the number of particles found for the image.

+ */

+int BinaryImage::GetNumberParticles()

+{

+	int numParticles = 0;

+	int success = imaqCountParticles(m_imaqImage, 1, &numParticles);

+	wpi_setImaqErrorWithContext(success, "Error counting particles");

+	return numParticles;

+}

+

+/**

+ * Get a single particle analysis report.

+ * Get one (of possibly many) particle analysis reports for an image.

+ * @param particleNumber Which particle analysis report to return.

+ * @returns the selected particle analysis report

+ */

+ParticleAnalysisReport BinaryImage::GetParticleAnalysisReport(int particleNumber)

+{

+	ParticleAnalysisReport par;

+	GetParticleAnalysisReport(particleNumber, &par);

+	return par;

+}

+

+/**

+ * Get a single particle analysis report.

+ * Get one (of possibly many) particle analysis reports for an image.

+ * This version could be more efficient when copying many reports.

+ * @param particleNumber Which particle analysis report to return.

+ * @param par the selected particle analysis report

+ */

+void BinaryImage::GetParticleAnalysisReport(int particleNumber, ParticleAnalysisReport *par)

+{

+	int success;

+	int numParticles = 0;

+

+	success = imaqGetImageSize(m_imaqImage, &par->imageWidth, &par->imageHeight);

+	wpi_setImaqErrorWithContext(success, "Error getting image size");

+	if (StatusIsFatal())

+		return;

+

+	success = imaqCountParticles(m_imaqImage, 1, &numParticles);

+	wpi_setImaqErrorWithContext(success, "Error counting particles");

+	if (StatusIsFatal())

+		return;

+

+	if (particleNumber >= numParticles)

+	{

+		wpi_setWPIErrorWithContext(ParameterOutOfRange, "particleNumber");

+		return;

+	}

+

+	par->particleIndex = particleNumber;

+	// Don't bother measuring the rest of the particle if one fails

+	bool good = ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_X, &par->center_mass_x);

+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_Y, &par->center_mass_y);

+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA, &par->particleArea);

+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_TOP, &par->boundingRect.top);

+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_LEFT, &par->boundingRect.left);

+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_HEIGHT, &par->boundingRect.height);

+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_WIDTH, &par->boundingRect.width);

+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_IMAGE_AREA, &par->particleToImagePercent);

+	good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA, &par->particleQuality);

+

+	if (good)

+	{

+		/* normalized position (-1 to 1) */

+		par->center_mass_x_normalized = NormalizeFromRange(par->center_mass_x, par->imageWidth);

+		par->center_mass_y_normalized = NormalizeFromRange(par->center_mass_y, par->imageHeight);

+	}

+}

+

+

+/**

+ * Get an ordered vector of particles for the image.

+ * Create a vector of particle analysis reports sorted by size for an image.

+ * The vector contains the actual report structures.

+ * @returns a pointer to the vector of particle analysis reports. The caller must delete the

+ * vector when finished using it.

+ */

+vector<ParticleAnalysisReport>* BinaryImage::GetOrderedParticleAnalysisReports()

+{

+	vector<ParticleAnalysisReport>* particles = new vector<ParticleAnalysisReport>;

+	int particleCount = GetNumberParticles();

+	for(int particleIndex = 0; particleIndex < particleCount; particleIndex++)

+	{

+		particles->push_back(GetParticleAnalysisReport(particleIndex));

+	}

+	// TODO: This is pretty inefficient since each compare in the sort copies

+	//   both reports being compared... do it manually instead... while we're

+	//   at it, we should provide a version that allows a preallocated buffer of

+	//   ParticleAnalysisReport structures

+	sort(particles->begin(), particles->end(), CompareParticleSizes);

+	return particles;

+}

+

+/**

+ * Write a binary image to flash.

+ * Writes the binary image to flash on the cRIO for later inspection.

+ * @param fileName the name of the image file written to the flash.

+ */

+void BinaryImage::Write(const char *fileName)

+{

+	RGBValue colorTable[256];

+	Priv_SetWriteFileAllowed(1);

+	memset(colorTable, 0, sizeof(colorTable));

+	colorTable[0].R = 0;

+	colorTable[1].R = 255;

+	colorTable[0].G = colorTable[1].G = 0;

+	colorTable[0].B = colorTable[1].B = 0;

+	colorTable[0].alpha = colorTable[1].alpha = 0;

+	imaqWriteFile(m_imaqImage, fileName, colorTable);

+}

+

+/**

+ * Measure a single parameter for an image.

+ * Get the measurement for a single parameter about an image by calling the imaqMeasureParticle

+ * function for the selected parameter.

+ * @param particleNumber which particle in the set of particles

+ * @param whatToMeasure the imaq MeasurementType (what to measure)

+ * @param result the value of the measurement

+ * @returns false on failure, true on success

+ */

+bool BinaryImage::ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, int *result)

+{

+	double resultDouble;

+	bool success = ParticleMeasurement(particleNumber, whatToMeasure, &resultDouble);

+	*result = (int)resultDouble;

+	return success;

+}

+

+/**

+ * Measure a single parameter for an image.

+ * Get the measurement for a single parameter about an image by calling the imaqMeasureParticle

+ * function for the selected parameter.

+ * @param particleNumber which particle in the set of particles

+ * @param whatToMeasure the imaq MeasurementType (what to measure)

+ * @param result the value of the measurement

+ * @returns true on failure, false on success

+ */

+bool BinaryImage::ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, double *result)

+{

+	int success;

+	success = imaqMeasureParticle(m_imaqImage, particleNumber, 0, whatToMeasure, result);

+	wpi_setImaqErrorWithContext(success, "Error measuring particle");

+	return !StatusIsFatal();

+}

+

+//Normalizes to [-1,1]

+double BinaryImage::NormalizeFromRange(double position, int range)

+{

+	return (position * 2.0 / (double)range) - 1.0;

+}

+

+/**

+ * The compare helper function for sort.

+ * This function compares two particle analysis reports as a helper for the sort function.

+ * @param particle1 The first particle to compare

+ * @param particle2 the second particle to compare

+ * @returns true if particle1 is greater than particle2

+ */

+bool BinaryImage::CompareParticleSizes(ParticleAnalysisReport particle1, ParticleAnalysisReport particle2)

+{

+	//we want descending sort order

+	return particle1.particleToImagePercent > particle2.particleToImagePercent;

+}

+

+BinaryImage *BinaryImage::RemoveSmallObjects(bool connectivity8, int erosions)

+{

+	BinaryImage *result = new BinaryImage();

+	int success = imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8, erosions, IMAQ_KEEP_LARGE, NULL);

+	wpi_setImaqErrorWithContext(success, "Error in RemoveSmallObjects");

+	return result;

+}

+

+BinaryImage *BinaryImage::RemoveLargeObjects(bool connectivity8, int erosions)

+{

+	BinaryImage *result = new BinaryImage();

+	int success = imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8, erosions, IMAQ_KEEP_SMALL, NULL);

+	wpi_setImaqErrorWithContext(success, "Error in RemoveLargeObjects");

+	return result;

+}

+

+BinaryImage *BinaryImage::ConvexHull(bool connectivity8)

+{

+	BinaryImage *result = new BinaryImage();

+	int success = imaqConvexHull(result->GetImaqImage(), m_imaqImage, connectivity8);

+	wpi_setImaqErrorWithContext(success, "Error in convex hull operation");

+	return result;

+}

+

+BinaryImage *BinaryImage::ParticleFilter(ParticleFilterCriteria2 *criteria, int criteriaCount)

+{

+	BinaryImage *result = new BinaryImage();

+	int numParticles;

+	ParticleFilterOptions2 filterOptions = {0, 0, 0, 1};

+	int success = imaqParticleFilter4(result->GetImaqImage(), m_imaqImage, criteria, criteriaCount, &filterOptions, NULL, &numParticles);

+	wpi_setImaqErrorWithContext(success, "Error in particle filter operation");

+	return result;

+}

+

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/BinaryImage.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/BinaryImage.h
new file mode 100644
index 0000000..b71f86a
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/BinaryImage.h
@@ -0,0 +1,42 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __BINARY_IMAGE_H__

+#define __BINARY_IMAGE_H__

+

+#include "MonoImage.h"

+/**

+ * Included for ParticleAnalysisReport definition

+ * TODO: Eliminate this dependency! 

+ */

+#include "Vision2009/VisionAPI.h"

+

+#include <vector>

+#include <algorithm>

+using namespace std;

+

+class BinaryImage : public MonoImage

+{

+public:

+	BinaryImage();

+	virtual ~BinaryImage();

+	int GetNumberParticles();

+	ParticleAnalysisReport GetParticleAnalysisReport(int particleNumber);

+	void GetParticleAnalysisReport(int particleNumber, ParticleAnalysisReport *par);

+	vector<ParticleAnalysisReport>* GetOrderedParticleAnalysisReports();

+	BinaryImage *RemoveSmallObjects(bool connectivity8, int erosions);

+	BinaryImage *RemoveLargeObjects(bool connectivity8, int erosions);

+	BinaryImage *ConvexHull(bool connectivity8);

+	BinaryImage *ParticleFilter(ParticleFilterCriteria2 *criteria, int criteriaCount);

+	virtual void Write(const char *fileName);

+private:

+	bool ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, int *result);

+	bool ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, double *result);

+	static double NormalizeFromRange(double position, int range);

+	static bool CompareParticleSizes(ParticleAnalysisReport particle1, ParticleAnalysisReport particle2);

+};

+

+#endif

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ColorImage.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ColorImage.cpp
new file mode 100644
index 0000000..8324bb5
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ColorImage.cpp
@@ -0,0 +1,465 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "ColorImage.h"

+

+#include "WPIErrors.h"

+

+ColorImage::ColorImage(ImageType type) : ImageBase(type)

+{

+}

+

+ColorImage::~ColorImage()

+{

+}

+

+/**

+ * Perform a threshold operation on a ColorImage.

+ * Perform a threshold operation on a ColorImage using the ColorMode supplied

+ * as a parameter.

+ * @param colorMode The type of colorspace this operation should be performed in

+ * @returns a pointer to a binary image

+ */

+BinaryImage *ColorImage::ComputeThreshold(ColorMode colorMode,

+		int low1, int high1,

+		int low2, int high2,

+		int low3, int high3)

+{

+	BinaryImage *result = new BinaryImage();

+	Range range1 = {low1, high1},

+		range2 = {low2, high2},

+		range3 = {low3, high3};

+	

+	int success = imaqColorThreshold(result->GetImaqImage(), m_imaqImage, 1, colorMode, &range1, &range2, &range3);

+	wpi_setImaqErrorWithContext(success, "ImaqThreshold error");

+	return result;

+}

+

+/**

+ * Perform a threshold in RGB space.

+ * @param redLow Red low value

+ * @param redHigh Red high value

+ * @param greenLow Green low value

+ * @param greenHigh Green high value

+ * @param blueLow Blue low value

+ * @param blueHigh Blue high value

+ * @returns A pointer to a BinaryImage that represents the result of the threshold operation.

+ */

+BinaryImage *ColorImage::ThresholdRGB(int redLow, int redHigh, int greenLow, int greenHigh, int blueLow, int blueHigh)

+{

+	return ComputeThreshold(IMAQ_RGB, redLow, redHigh, greenLow, greenHigh, blueLow, blueHigh);

+}

+

+/**

+ * Perform a threshold in RGB space.

+ * @param threshold a reference to the Threshold object to use.

+ * @returns A pointer to a BinaryImage that represents the result of the threshold operation.

+ */

+BinaryImage *ColorImage::ThresholdRGB(Threshold &t)

+{

+	return ComputeThreshold(IMAQ_RGB, t.plane1Low, t.plane1High,

+								t.plane2Low, t.plane2High,

+								t.plane3Low, t.plane3High);

+}

+

+/**

+ * Perform a threshold in HSL space.

+ * @param hueLow Low value for hue

+ * @param hueHigh High value for hue

+ * @param saturationLow Low value for saturation

+ * @param saturationHigh High value for saturation

+ * @param luminenceLow Low value for luminence

+ * @param luminenceHigh High value for luminence

+ * @returns a pointer to a BinaryImage that represents the result of the threshold operation.

+ */

+BinaryImage *ColorImage::ThresholdHSL(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int luminenceLow, int luminenceHigh)

+{

+	return ComputeThreshold(IMAQ_HSL, hueLow, hueHigh, saturationLow, saturationHigh, luminenceLow, luminenceHigh);

+}

+

+/**

+ * Perform a threshold in HSL space.

+ * @param threshold a reference to the Threshold object to use.

+ * @returns A pointer to a BinaryImage that represents the result of the threshold operation.

+ */

+BinaryImage *ColorImage::ThresholdHSL(Threshold &t)

+{

+	return ComputeThreshold(IMAQ_HSL, t.plane1Low, t.plane1High,

+								t.plane2Low, t.plane2High,

+								t.plane3Low, t.plane3High);

+}

+

+/**

+ * Perform a threshold in HSV space.

+ * @param hueLow Low value for hue

+ * @param hueHigh High value for hue

+ * @param saturationLow Low value for saturation

+ * @param saturationHigh High value for saturation

+ * @param valueLow Low value

+ * @param valueHigh High value

+ * @returns a pointer to a BinaryImage that represents the result of the threshold operation.

+ */

+BinaryImage *ColorImage::ThresholdHSV(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int valueLow, int valueHigh)

+{

+	return ComputeThreshold(IMAQ_HSV, hueLow, hueHigh, saturationLow, saturationHigh, valueLow, valueHigh);

+}

+

+/**

+ * Perform a threshold in HSV space.

+ * @param threshold a reference to the Threshold object to use.

+ * @returns A pointer to a BinaryImage that represents the result of the threshold operation.

+ */

+BinaryImage *ColorImage::ThresholdHSV(Threshold &t)

+{

+	return ComputeThreshold(IMAQ_HSV, t.plane1Low, t.plane1High,

+								t.plane2Low, t.plane2High,

+								t.plane3Low, t.plane3High);

+}

+

+/**

+ * Perform a threshold in HSI space.

+ * @param hueLow Low value for hue

+ * @param hueHigh High value for hue

+ * @param saturationLow Low value for saturation

+ * @param saturationHigh High value for saturation

+ * @param valueLow Low intensity

+ * @param valueHigh High intensity

+ * @returns a pointer to a BinaryImage that represents the result of the threshold operation.

+ */

+BinaryImage *ColorImage::ThresholdHSI(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int intensityLow, int intensityHigh)

+{

+	return ComputeThreshold(IMAQ_HSI, hueLow, hueHigh, saturationLow, saturationHigh, intensityLow, intensityHigh);

+}

+

+/**

+ * Perform a threshold in HSI space.

+ * @param threshold a reference to the Threshold object to use.

+ * @returns A pointer to a BinaryImage that represents the result of the threshold operation.

+ */

+BinaryImage *ColorImage::ThresholdHSI(Threshold &t)

+{

+	return ComputeThreshold(IMAQ_HSI, t.plane1Low, t.plane1High,

+								t.plane2Low, t.plane2High,

+								t.plane3Low, t.plane3High);

+}

+

+/**

+ * Extract a color plane from the image

+ * @param mode The ColorMode to use for the plane extraction

+ * @param planeNumber Which plane is to be extracted

+ * @returns A pointer to a MonoImage that represents the extracted plane.

+ */

+MonoImage *ColorImage::ExtractColorPlane(ColorMode mode, int planeNumber)

+{

+	MonoImage *result = new MonoImage();

+	if (m_imaqImage == NULL)

+		wpi_setWPIError(NullParameter);

+	int success = imaqExtractColorPlanes(m_imaqImage, 

+										 mode, 

+										 (planeNumber == 1) ? result->GetImaqImage() : NULL, 

+										 (planeNumber == 2) ? result->GetImaqImage() : NULL, 

+										 (planeNumber == 3) ? result->GetImaqImage() : NULL);

+	wpi_setImaqErrorWithContext(success, "Imaq ExtractColorPlanes failed");

+	return result;

+}

+

+/*

+ * Extract the first color plane for an image.

+ * @param mode The color mode in which to operate

+ * @returns a pointer to a MonoImage that is the extracted plane.

+ */

+MonoImage *ColorImage::ExtractFirstColorPlane(ColorMode mode)

+{

+	return ExtractColorPlane(mode, 1);

+}

+

+/*

+ * Extract the second color plane for an image.

+ * @param mode The color mode in which to operate

+ * @returns a pointer to a MonoImage that is the extracted plane.

+ */

+MonoImage *ColorImage::ExtractSecondColorPlane(ColorMode mode)

+{

+	return ExtractColorPlane(mode, 2);

+}

+

+/*

+ * Extract the third color plane for an image.

+ * @param mode The color mode in which to operate

+ * @returns a pointer to a MonoImage that is the extracted plane.

+ */

+MonoImage *ColorImage::ExtractThirdColorPlane(ColorMode mode)

+{

+	return ExtractColorPlane(mode, 3);

+}

+

+/*

+ * Extract the red plane from an RGB image.

+ * @returns a pointer to a MonoImage that is the extraced plane.

+ */

+MonoImage *ColorImage::GetRedPlane()

+{

+	return ExtractFirstColorPlane(IMAQ_RGB);

+}

+

+/*

+ * Extract the green plane from an RGB image.

+ * @returns a pointer to a MonoImage that is the extraced plane.

+ */

+MonoImage *ColorImage::GetGreenPlane()

+{

+    return ExtractSecondColorPlane(IMAQ_RGB);

+}

+

+/*

+ * Extract the blue plane from an RGB image.

+ * @returns a pointer to a MonoImage that is the extraced plane.

+ */

+MonoImage *ColorImage::GetBluePlane()

+{

+    return ExtractThirdColorPlane(IMAQ_RGB);

+}

+

+/*

+ * Extract the Hue plane from an HSL image.

+ * @returns a pointer to a MonoImage that is the extraced plane.

+ */

+MonoImage *ColorImage::GetHSLHuePlane()

+{

+	return ExtractFirstColorPlane(IMAQ_HSL);

+}

+

+/*

+ * Extract the Hue plane from an HSV image.

+ * @returns a pointer to a MonoImage that is the extraced plane.

+ */

+MonoImage *ColorImage::GetHSVHuePlane()

+{

+	return ExtractFirstColorPlane(IMAQ_HSV);

+}

+

+/*

+ * Extract the Hue plane from an HSI image.

+ * @returns a pointer to a MonoImage that is the extraced plane.

+ */

+MonoImage *ColorImage::GetHSIHuePlane()

+{

+	return ExtractFirstColorPlane(IMAQ_HSI);

+}

+

+/*

+ * Extract the Luminance plane from an HSL image.

+ * @returns a pointer to a MonoImage that is the extraced plane.

+ */

+MonoImage *ColorImage::GetLuminancePlane()

+{

+	return ExtractThirdColorPlane(IMAQ_HSL);

+}

+

+/*

+ * Extract the Value plane from an HSV image.

+ * @returns a pointer to a MonoImage that is the extraced plane.

+ */

+MonoImage *ColorImage::GetValuePlane()

+{

+	return ExtractThirdColorPlane(IMAQ_HSV);

+}

+

+/*

+ * Extract the Intensity plane from an HSI image.

+ * @returns a pointer to a MonoImage that is the extraced plane.

+ */

+MonoImage *ColorImage::GetIntensityPlane()

+{

+	return ExtractThirdColorPlane(IMAQ_HSI);

+}

+

+/**

+ * Replace a plane in the ColorImage with a MonoImage

+ * Replaces a single plane in the image with a MonoImage

+ * @param mode The ColorMode in which to operate

+ * @param plane The pointer to the replacement plane as a MonoImage

+ * @param planeNumber The plane number (1, 2, 3) to replace

+ */

+void ColorImage::ReplacePlane(ColorMode mode, MonoImage *plane, int planeNumber) {

+	int success = imaqReplaceColorPlanes(m_imaqImage, 

+										 (const Image*) m_imaqImage, 

+									     mode, 

+									     (planeNumber == 1) ? plane->GetImaqImage() : NULL, 

+									     (planeNumber == 2) ? plane->GetImaqImage() : NULL, 

+									     (planeNumber == 3) ? plane->GetImaqImage() : NULL);

+	wpi_setImaqErrorWithContext(success, "Imaq ReplaceColorPlanes failed");

+}

+

+/**

+ * Replace the first color plane with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceFirstColorPlane(ColorMode mode, MonoImage *plane)

+{

+	ReplacePlane(mode, plane, 1);

+}

+

+/**

+ * Replace the second color plane with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceSecondColorPlane(ColorMode mode, MonoImage *plane)

+{

+	ReplacePlane(mode, plane, 2);

+}

+

+/**

+ * Replace the third color plane with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceThirdColorPlane(ColorMode mode, MonoImage *plane)

+{ 

+	ReplacePlane(mode, plane, 3);

+}

+

+/**

+ * Replace the red color plane with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceRedPlane(MonoImage *plane)

+{

+	ReplaceFirstColorPlane(IMAQ_RGB, plane);

+}

+

+/**

+ * Replace the green color plane with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceGreenPlane(MonoImage *plane)

+{

+	ReplaceSecondColorPlane(IMAQ_RGB, plane);

+}

+

+/**

+ * Replace the blue color plane with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceBluePlane(MonoImage *plane)

+{

+	ReplaceThirdColorPlane(IMAQ_RGB, plane);

+}

+

+

+/**

+ * Replace the Hue color plane in a HSL image with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceHSLHuePlane(MonoImage *plane)

+{

+	return ReplaceFirstColorPlane(IMAQ_HSL, plane);

+}

+

+/**

+ * Replace the Hue color plane in a HSV image with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceHSVHuePlane(MonoImage *plane)

+{

+	return ReplaceFirstColorPlane(IMAQ_HSV, plane);

+}

+

+/**

+ * Replace the first Hue plane in a HSI image with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceHSIHuePlane(MonoImage *plane)

+{

+	return ReplaceFirstColorPlane(IMAQ_HSI, plane);

+}

+

+/**

+ * Replace the Saturation color plane in an HSL image with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceHSLSaturationPlane(MonoImage *plane)

+{

+	return ReplaceSecondColorPlane(IMAQ_HSL, plane);

+}

+

+/**

+ * Replace the Saturation color plane in a HSV image with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceHSVSaturationPlane(MonoImage *plane)

+{

+	return ReplaceSecondColorPlane(IMAQ_HSV, plane);

+}

+

+/**

+ * Replace the Saturation color plane in a HSI image with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceHSISaturationPlane(MonoImage *plane)

+{

+	return ReplaceSecondColorPlane(IMAQ_HSI, plane);

+}

+

+/**

+ * Replace the Luminance color plane in an HSL image with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceLuminancePlane(MonoImage *plane)

+{

+	return ReplaceThirdColorPlane(IMAQ_HSL, plane);

+}

+

+/**

+ * Replace the Value color plane in an HSV with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceValuePlane(MonoImage *plane)

+{

+	return ReplaceThirdColorPlane(IMAQ_HSV, plane);

+}

+

+/**

+ * Replace the Intensity color plane in a HSI image with a MonoImage.

+ * @param mode The color mode in which to operate.

+ * @param plane A pointer to a MonoImage that will replace the specified color plane.

+ */

+void ColorImage::ReplaceIntensityPlane(MonoImage *plane)

+{

+	return ReplaceThirdColorPlane(IMAQ_HSI, plane);

+}

+

+//TODO: frcColorEqualize(Image* dest, const Image* source, int colorEqualization) needs to be modified

+//The colorEqualization parameter is discarded and is set to TRUE in the call to imaqColorEqualize.

+void ColorImage::Equalize(bool allPlanes)

+{

+	// Note that this call uses NI-defined TRUE and FALSE

+	int success = imaqColorEqualize(m_imaqImage, (const Image*) m_imaqImage, (allPlanes) ? TRUE : FALSE);

+	wpi_setImaqErrorWithContext(success, "Imaq ColorEqualize error");

+}

+

+void ColorImage::ColorEqualize()

+{

+	Equalize(true);

+}

+

+void ColorImage::LuminanceEqualize()

+{

+	Equalize(false);

+}

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ColorImage.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ColorImage.h
new file mode 100644
index 0000000..4ebf77e
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ColorImage.h
@@ -0,0 +1,68 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __COLOR_IMAGE_H__

+#define __COLOR_IMAGE_H__

+

+#include "ImageBase.h"

+#include "BinaryImage.h"

+#include "Threshold.h"

+

+class ColorImage : public ImageBase

+{

+public:

+	ColorImage(ImageType type);

+	virtual ~ColorImage();

+	BinaryImage *ThresholdRGB(int redLow, int redHigh, int greenLow, int greenHigh, int blueLow, int blueHigh);

+	BinaryImage *ThresholdHSL(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int luminenceLow, int luminenceHigh);

+	BinaryImage *ThresholdHSV(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int valueHigh, int valueLow);

+	BinaryImage *ThresholdHSI(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int intensityLow, int intensityHigh);

+	BinaryImage *ThresholdRGB(Threshold &threshold);

+	BinaryImage *ThresholdHSL(Threshold &threshold);

+	BinaryImage *ThresholdHSV(Threshold &threshold);

+	BinaryImage *ThresholdHSI(Threshold &threshold);

+	MonoImage *GetRedPlane();

+	MonoImage *GetGreenPlane();

+	MonoImage *GetBluePlane();

+	MonoImage *GetHSLHuePlane();

+	MonoImage *GetHSVHuePlane();

+	MonoImage *GetHSIHuePlane();

+	MonoImage *GetHSLSaturationPlane();

+	MonoImage *GetHSVSaturationPlane();

+	MonoImage *GetHSISaturationPlane();

+	MonoImage *GetLuminancePlane();

+	MonoImage *GetValuePlane();

+	MonoImage *GetIntensityPlane();

+	void ReplaceRedPlane(MonoImage *plane);

+	void ReplaceGreenPlane(MonoImage *plane);

+	void ReplaceBluePlane(MonoImage *plane);

+	void ReplaceHSLHuePlane(MonoImage *plane);

+	void ReplaceHSVHuePlane(MonoImage *plane);

+	void ReplaceHSIHuePlane(MonoImage *plane);

+	void ReplaceHSLSaturationPlane(MonoImage *plane);

+	void ReplaceHSVSaturationPlane(MonoImage *plane);

+	void ReplaceHSISaturationPlane(MonoImage *plane);

+	void ReplaceLuminancePlane(MonoImage *plane);

+	void ReplaceValuePlane(MonoImage *plane);

+	void ReplaceIntensityPlane(MonoImage *plane);

+	void ColorEqualize();

+	void LuminanceEqualize();

+	

+private:

+	BinaryImage *ComputeThreshold(ColorMode colorMode, int low1, int high1, int low2, int high2, int low3, int high3);

+	void Equalize(bool allPlanes);

+	MonoImage * ExtractColorPlane(ColorMode mode, int planeNumber);

+	MonoImage * ExtractFirstColorPlane(ColorMode mode);

+	MonoImage * ExtractSecondColorPlane(ColorMode mode);

+	MonoImage * ExtractThirdColorPlane(ColorMode mode);

+	void ReplacePlane(ColorMode mode, MonoImage *plane, int planeNumber);

+	void ReplaceFirstColorPlane(ColorMode mode, MonoImage *plane);

+	void ReplaceSecondColorPlane(ColorMode mode, MonoImage *plane);

+	void ReplaceThirdColorPlane(ColorMode mode, MonoImage *plane);

+};

+

+#endif

+

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/EnumCameraParameter.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/EnumCameraParameter.cpp
new file mode 100644
index 0000000..cdf5fbb
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/EnumCameraParameter.cpp
@@ -0,0 +1,67 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "EnumCameraParameter.h"

+#include <stdio.h>

+#include <string.h>

+

+/**

+ * Constructor for an enumeration camera parameter.

+ * Enumeration camera parameters have lists of value choices and strings that go

+ * with them. There are also C++ enumerations to go along with them.

+ * @param setString The string for an HTTP request to set the value.

+ * @param getString The string for an HTTP request to get the value.

+ * @param choices An array of strings of the parameter choices set in the http strings.

+ * @param numChoices The number of choices in the enumeration set.

+ */

+EnumCameraParameter::EnumCameraParameter(const char *setString, const char *getString, bool requiresRestart,

+													const char *const*choices, int numChoices)

+	: IntCameraParameter(setString, getString, requiresRestart)

+{

+	m_enumValues = choices;

+	m_numChoices = numChoices;

+}

+

+/*

+ * Check if an enumeration camera parameter has changed.

+ * Check if the parameter has changed and update the camera if it has. This is called

+ * from a loop in the parameter checker task.

+ * @returns true if the camera needs to restart

+ */

+bool EnumCameraParameter::CheckChanged(bool &changed, char *param)

+{

+	changed = m_changed;

+	if (m_changed)

+	{

+		m_changed = false;

+		sprintf(param, m_setString, m_enumValues[m_value]);

+		return m_requiresRestart;

+	}

+	return false;

+}

+

+/**

+ * Extract the parameter value from a string.

+ * Extract the parameter value from the camera status message.

+ * @param string The string returned from the camera.

+ * @param length The length of the string from the camera.

+ */

+void EnumCameraParameter::GetParamFromString(const char *string, int stringLength)

+{

+	char resultString[50];

+	if (SearchForParam(m_getString, string, stringLength, resultString) < 0) return;

+	for (int i = 0; i < m_numChoices; i++)

+	{

+		if (strcmp(resultString, m_enumValues[i]) == 0)

+		{

+			if (!m_changed)	  // don't change parameter that's been set in code

+			{

+				m_value = i;

+			}

+		}

+	}

+}

+

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/EnumCameraParameter.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/EnumCameraParameter.h
new file mode 100644
index 0000000..a29c3fd
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/EnumCameraParameter.h
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __ENUM_CAMERA_PARAMETER_H__

+#define __ENUM_CAMERA_PARAMETER_H__

+

+#include "IntCameraParameter.h"

+

+/**

+ * Enumerated camera parameter.

+ * This class represents a camera parameter that takes an enumerated type for a value.

+ */

+class EnumCameraParameter: public IntCameraParameter

+{

+private:

+	const char *const*m_enumValues;

+	int m_numChoices;

+

+public:

+	EnumCameraParameter(const char *setString, const char *getString, bool requiresRestart, const char *const*choices, int numChoices);

+	virtual bool CheckChanged(bool &changed, char *param);

+	virtual void GetParamFromString(const char *string, int stringLength);

+};

+

+#endif

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/HSLImage.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/HSLImage.cpp
new file mode 100644
index 0000000..770bcf0
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/HSLImage.cpp
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "HSLImage.h"

+

+/**

+ * Create a new image that uses the Hue, Saturation, and Luminance planes.

+ */

+HSLImage::HSLImage() : ColorImage(IMAQ_IMAGE_HSL)

+{

+}

+

+/**

+ * Create a new image by loading a file.

+ * @param fileName The path of the file to load.

+ */

+HSLImage::HSLImage(const char *fileName) : ColorImage(IMAQ_IMAGE_HSL)

+{

+	int success = imaqReadFile(m_imaqImage, fileName, NULL, NULL);

+	wpi_setImaqErrorWithContext(success, "Imaq ReadFile error");

+}

+

+HSLImage::~HSLImage()

+{

+}

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/HSLImage.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/HSLImage.h
new file mode 100644
index 0000000..bd50610
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/HSLImage.h
@@ -0,0 +1,24 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __HSL_IMAGE_H__

+#define __HSL_IMAGE_H__

+

+#include "ColorImage.h"

+

+/**

+ * A color image represented in HSL color space at 3 bytes per pixel.

+ */

+class HSLImage : public ColorImage

+{

+public:

+    HSLImage();

+    HSLImage(const char *fileName);

+    virtual ~HSLImage();

+};

+

+#endif

+

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ImageBase.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ImageBase.cpp
new file mode 100644
index 0000000..68a2721
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ImageBase.cpp
@@ -0,0 +1,77 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "ImageBase.h"

+#include "nivision.h"

+

+/** Private NI function needed to write to the VxWorks target */

+IMAQ_FUNC int Priv_SetWriteFileAllowed(UINT32 enable); 

+

+/**

+ * Create a new instance of an ImageBase.

+ * Imagebase is the base of all the other image classes. The constructor

+ * creates any type of image and stores the pointer to it in the class.

+ * @param type The type of image to create

+ */

+ImageBase::ImageBase(ImageType type)

+{

+	m_imaqImage = imaqCreateImage(type, DEFAULT_BORDER_SIZE);

+}

+

+/**

+ * Frees memory associated with an ImageBase.

+ * Destructor frees the imaq image allocated with the class.

+ */

+ImageBase::~ImageBase()

+{

+	if(m_imaqImage)

+		imaqDispose(m_imaqImage);

+}

+

+/**

+ * Writes an image to a file with the given filename.

+ * Write the image to a file in the flash on the cRIO.

+ * @param fileName The name of the file to write

+ */

+void ImageBase::Write(const char *fileName)

+{

+	Priv_SetWriteFileAllowed(1);

+	int success = imaqWriteFile(m_imaqImage, fileName, NULL);

+	wpi_setImaqErrorWithContext(success, "Imaq Image writeFile error");

+}

+

+/**

+ * Gets the height of an image.

+ * @return The height of the image in pixels.

+ */

+int ImageBase::GetHeight()

+{

+	int height;

+	imaqGetImageSize(m_imaqImage, NULL, &height);

+	return height;

+}

+

+/**

+ * Gets the width of an image.

+ * @return The width of the image in pixels.

+ */

+int ImageBase::GetWidth()

+{

+	int width;

+	imaqGetImageSize(m_imaqImage, &width, NULL);

+	return width;

+}

+

+/**

+ * Access the internal IMAQ Image data structure.

+ * 

+ * @return A pointer to the internal IMAQ Image data structure.

+ */

+Image *ImageBase::GetImaqImage()

+{

+	return m_imaqImage;

+}

+

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ImageBase.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ImageBase.h
new file mode 100644
index 0000000..98bea67
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/ImageBase.h
@@ -0,0 +1,29 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __IMAGE_BASE_H__

+#define __IMAGE_BASE_H__

+

+#include <stdio.h>

+#include "nivision.h"

+#include "ErrorBase.h"

+

+#define DEFAULT_BORDER_SIZE 3

+

+class ImageBase : public ErrorBase

+{

+public:

+	ImageBase(ImageType type);

+	virtual ~ImageBase();

+	virtual void Write(const char *fileName);

+	int GetHeight();

+	int GetWidth();

+	Image *GetImaqImage();

+protected:

+	Image *m_imaqImage;

+};

+

+#endif

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/IntCameraParameter.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/IntCameraParameter.cpp
new file mode 100644
index 0000000..d79ef9c
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/IntCameraParameter.cpp
@@ -0,0 +1,111 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "IntCameraParameter.h"

+#include "pcre.h"

+#include <stdio.h>

+#include <string.h>

+

+/**

+ * Constructor for an integer camera parameter.

+ * @param setString The string to set a value in the HTTP request

+ * @param getString The string to retrieve a value in the HTTP request

+ */

+IntCameraParameter::IntCameraParameter(const char *setString, const char *getString, bool requiresRestart)

+{

+	m_changed = false;

+	m_value = 0;

+	m_setString = setString;

+	m_getString = getString;

+	m_requiresRestart = requiresRestart;

+}

+

+/**

+ * Get a value for a camera parameter.

+ * @returns The camera parameter cached valued.

+ */

+int IntCameraParameter::GetValue()

+{

+	return m_value;

+}

+

+/**

+ * Set a value for a camera parameter.

+ * Mark the value for change. The value will be updated in the parameter

+ * change loop.

+ */

+void IntCameraParameter::SetValue(int value)

+{

+	m_value = value;

+	m_changed = true;

+}

+

+/**

+ * Check if a parameter has changed and update.

+ * Check if a parameter has changed and send the update string if it

+ * has changed. This is called from the loop in the parameter task loop.

+ * @returns true if the camera needs to restart

+ */

+bool IntCameraParameter::CheckChanged(bool &changed, char *param)

+{

+	changed = m_changed;

+	if (m_changed)

+	{

+		sprintf(param, m_setString, m_value);

+		m_changed = false;

+		return m_requiresRestart;

+	}

+	return false;

+}

+

+/**

+ * Get a parameter value from the string.

+ * Get a parameter value from the camera status string. If it has been changed

+ * been changed by the program, then don't update it. Program values have

+ * precedence over those written in the camera.

+ */

+void IntCameraParameter::GetParamFromString(const char *string, int stringLength)

+{

+	char resultString[150];

+	if (SearchForParam(m_getString, string, stringLength, resultString) >= 0)

+	{	

+		if (!m_changed) m_value = atoi(resultString);

+	}

+}

+

+/**

+ * @param pattern: the regular expression

+ * @param searchString the text to search

+ * @param searchStringLen the length of searchString

+ * @param result buffer to put resulting text into, must be pre-allocated

+ */

+int IntCameraParameter::SearchForParam(const char *pattern, const char *searchString, int searchStringLen, char *result)

+{

+	int vectorLen = 10;

+	int resultVector[vectorLen];

+	const char *error;

+	int erroffset;

+	pcre *compiledPattern = pcre_compile(

+			pattern, //"root.Image.I0.Appearance.Resolution=(.*)", 

+			PCRE_CASELESS, 

+			&error, // for error message 

+			&erroffset, // for error offset 

+			NULL); // use default character tables 

+	int rc;

+	rc = pcre_exec(compiledPattern, 

+					NULL, 

+					searchString, 

+					searchStringLen, 

+					0, 

+					0, 

+					resultVector,		//locations of submatches 

+					vectorLen);			//size of ovector

+	int length = resultVector[3] - resultVector[2];

+	memcpy(result, &searchString[resultVector[2]], length);

+	result[length] = '\0';

+	return rc;

+}

+

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/IntCameraParameter.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/IntCameraParameter.h
new file mode 100644
index 0000000..bb2ddc4
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/IntCameraParameter.h
@@ -0,0 +1,35 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __INT_CAMERA_PARAMETER_H__

+#define __INT_CAMERA_PARAMETER_H__

+

+#include <vxWorks.h>

+

+/**

+ * Integer camera parameter.

+ * This class represents a camera parameter that takes an integer value.

+ */

+class IntCameraParameter

+{

+protected:

+	const char *m_setString;

+	const char *m_getString;

+	bool m_changed;

+	bool m_requiresRestart;

+	int m_value;			// parameter value

+

+	int SearchForParam(const char *pattern, const char *searchString, int searchStringLen, char *result);

+

+public:

+	IntCameraParameter(const char *setString, const char *getString, bool requiresRestart);

+	int GetValue();

+	void SetValue(int value);

+	virtual bool CheckChanged(bool &changed, char *param);

+	virtual void GetParamFromString(const char *string, int stringLength);

+};

+

+#endif

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/MonoImage.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/MonoImage.cpp
new file mode 100644
index 0000000..7daaed1
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/MonoImage.cpp
@@ -0,0 +1,53 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "MonoImage.h"

+#include "nivision.h"

+

+MonoImage::MonoImage() : ImageBase(IMAQ_IMAGE_U8)

+{

+}

+

+MonoImage::~MonoImage()

+{

+}

+

+/**

+ * Look for ellipses in an image.

+ * Given some input parameters, look for any number of ellipses in an image.

+ * @param ellipseDescriptor Ellipse descriptor

+ * @param curveOptions Curve options

+ * @param shapeDetectionOptions Shape detection options

+ * @param roi Region of Interest

+ * @returns a vector of EllipseMatch structures (0 length vector on no match)

+ */

+vector<EllipseMatch> * MonoImage::DetectEllipses(

+		EllipseDescriptor *ellipseDescriptor, CurveOptions *curveOptions,

+		ShapeDetectionOptions *shapeDetectionOptions, ROI *roi)

+{

+	int numberOfMatches;

+	EllipseMatch *e = imaqDetectEllipses(m_imaqImage, ellipseDescriptor,

+										curveOptions, shapeDetectionOptions, roi, &numberOfMatches);

+	vector<EllipseMatch> *ellipses = new vector<EllipseMatch>;

+	if (e == NULL)

+	{

+		return ellipses;

+	}

+	for (int i = 0; i < numberOfMatches; i++)

+	{

+		ellipses->push_back(e[i]);

+	}

+	imaqDispose(e);

+	return ellipses;

+}

+

+vector<EllipseMatch> * MonoImage::DetectEllipses(

+		EllipseDescriptor *ellipseDescriptor)

+{

+	vector<EllipseMatch> *ellipses = DetectEllipses(ellipseDescriptor, NULL,

+			NULL, NULL);

+	return ellipses;

+}

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/MonoImage.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/MonoImage.h
new file mode 100644
index 0000000..571dd6c
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/MonoImage.h
@@ -0,0 +1,29 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __MONO_IMAGE_H__

+#define __MONO_IMAGE_H__

+

+#include "ImageBase.h"

+

+#include <vector>

+

+using namespace std;

+

+class MonoImage : public ImageBase

+{

+public:

+	MonoImage();

+	virtual ~MonoImage();

+

+	vector<EllipseMatch> * DetectEllipses(EllipseDescriptor *ellipseDescriptor,

+					CurveOptions *curveOptions,

+					ShapeDetectionOptions *shapeDetectionOptions,

+					ROI *roi);

+	vector<EllipseMatch> * DetectEllipses(EllipseDescriptor *ellipseDescriptor);

+};

+

+#endif

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/PCVideoServer.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/PCVideoServer.cpp
new file mode 100644
index 0000000..222128d
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/PCVideoServer.cpp
@@ -0,0 +1,281 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include <vxWorks.h>

+

+#include "PCVideoServer.h"

+

+#include <errnoLib.h>

+#include <hostLib.h>

+#include <inetLib.h>

+#include <sockLib.h>

+

+#include "NetworkCommunication/UsageReporting.h"

+#include "Task.h"

+#include "Timer.h"

+#include "Vision/AxisCamera.h"

+#include "WPIErrors.h"

+

+/**

+ * @brief Implements an object that automatically does a close on a

+ * camera socket on destruction.

+ */

+class ScopedSocket {

+public:

+	ScopedSocket(int camSock)

+		: m_camSock(camSock)

+	{

+	}

+

+	~ScopedSocket() {

+		if (m_camSock != ERROR) {

+			close(m_camSock);

+		}

+	}

+	// Cast to int allows you to pass this to any function that

+	// takes the socket as an int.

+	operator int() const {

+		return m_camSock;

+	}

+

+private:

+	int m_camSock;

+};

+

+//============================================================================

+// PCVideoServer

+//============================================================================

+

+/**

+ * @brief Constructor.

+ */

+PCVideoServer::PCVideoServer()

+	: m_serverTask("PCVideoServer", (FUNCPTR)s_ServerTask)

+	, m_newImageSem (NULL)

+	, m_stopServer (false)

+{

+	AxisCamera &cam = AxisCamera::GetInstance();

+	m_newImageSem = cam.GetNewImageSem();

+	if (!cam.StatusIsFatal())

+	{

+		StartServerTask();

+	}

+	else

+	{

+		CloneError(&cam);

+	}

+}

+

+/**

+ * @brief Destructor.

+ * Stop serving images and destroy this class.

+ */

+PCVideoServer::~PCVideoServer()

+{

+	// Stop the images to PC server.

+	Stop();

+	// Clear the error so that you can use this object to make a connection to

+	// the VIDEO_TO_PC_PORT to stop the ImageToPCServer if it is waiting to

+	// accept connections from a PC.

+	ClearError();

+	// Open a socket.

+	int camSock = socket(AF_INET, SOCK_STREAM, 0);

+	if (camSock == ERROR)

+	{

+		wpi_setErrnoError();

+		return;

+	}

+	ScopedSocket scopedCamSock(camSock);

+	// If successful

+	if (!StatusIsFatal())

+	{

+		//  Create a connection to the localhost.

+		struct sockaddr_in selfAddr;

+		int sockAddrSize = sizeof(selfAddr);

+		bzero ((char *) &selfAddr, sockAddrSize);

+		selfAddr.sin_family = AF_INET;

+		selfAddr.sin_len = (u_char) sockAddrSize;

+		selfAddr.sin_port = htons (VIDEO_TO_PC_PORT);

+

+		if (( (int)(selfAddr.sin_addr.s_addr = inet_addr (const_cast<char*>("localhost")) ) != ERROR) ||

+			( (int)(selfAddr.sin_addr.s_addr = hostGetByName (const_cast<char*>("localhost")) ) != ERROR))

+		{

+			struct timeval connectTimeout;

+			connectTimeout.tv_sec = 1;

+			connectTimeout.tv_usec = 0;

+			connectWithTimeout(camSock, (struct sockaddr *) &selfAddr, sockAddrSize, &connectTimeout);

+		}

+	}

+}

+

+/**

+ * Start the task that is responsible for sending images to the PC.

+ */

+int PCVideoServer::StartServerTask()

+{

+	if (StatusIsFatal())

+	{

+		return -1;

+	}

+	int id = 0;

+	m_stopServer = false;

+	// Check for prior copy of running task

+	int oldId = taskNameToId((char*)m_serverTask.GetName());

+	if(oldId != ERROR)

+	{

+		// TODO: Report error. You are in a bad state.

+		taskDelete(oldId);

+	}

+

+	// spawn video server task

+	// this is done to ensure that the task is spawned with the

+	// floating point context save parameter.

+	bool started = m_serverTask.Start((int)this);

+

+	id = m_serverTask.GetID();

+

+	if (!started)

+	{

+		wpi_setWPIError(TaskError);

+		return id;

+	}

+	taskDelay(1);

+	return id;

+}

+

+/**

+ * @brief Start sending images to the PC.

+ */

+void PCVideoServer::Start()

+{

+	StartServerTask();

+}

+

+/**

+ * @brief Stop sending images to the PC.

+ */

+void PCVideoServer::Stop()

+{

+	m_stopServer = true;

+}

+

+/**

+ * Static stub for kicking off the server task

+ */

+int PCVideoServer::s_ServerTask(PCVideoServer *thisPtr)

+{

+	return thisPtr->ServerTask();

+}

+

+/**

+ * @brief Initialize the socket and serve images to the PC.

+ * This is the task that serves images to the PC in a loop. This runs

+ * as a separate task.

+ */

+int PCVideoServer::ServerTask()

+{

+	/* Setup to PC sockets */

+	struct sockaddr_in serverAddr;

+	int sockAddrSize = sizeof(serverAddr);

+	int pcSock = ERROR;

+	bzero ((char *) &serverAddr, sockAddrSize);

+	serverAddr.sin_len = (u_char) sockAddrSize;

+	serverAddr.sin_family = AF_INET;

+	serverAddr.sin_port = htons (VIDEO_TO_PC_PORT);

+	serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);

+

+	int success;

+	while (true)

+	{

+		taskSafe();

+		// Create the socket.

+		if ((pcSock = socket (AF_INET, SOCK_STREAM, 0)) == ERROR)

+		{

+			wpi_setErrnoErrorWithContext("Failed to create the PCVideoServer socket");

+			continue;

+		}

+		// Set the TCP socket so that it can be reused if it is in the wait state.

+		int reuseAddr = 1;

+		setsockopt(pcSock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&reuseAddr), sizeof(reuseAddr));

+		// Bind socket to local address.

+		if (bind (pcSock, (struct sockaddr *) &serverAddr, sockAddrSize) == ERROR)

+		{

+			wpi_setErrnoErrorWithContext("Failed to bind the PCVideoServer port");

+			close (pcSock);

+			continue;

+		}

+		// Create queue for client connection requests.

+		if (listen (pcSock, 1) == ERROR)

+		{

+			wpi_setErrnoErrorWithContext("Failed to listen on the PCVideoServer port");

+			close (pcSock);

+			continue;

+		}

+

+		struct sockaddr_in clientAddr;

+		int clientAddrSize;

+		int newPCSock = accept (pcSock, reinterpret_cast<sockaddr*>(&clientAddr), &clientAddrSize);

+		if (newPCSock  == ERROR)

+		{

+			close(pcSock);

+			continue;

+		}

+		//TODO: check camera error

+

+		// Report usage when there is actually a connection.

+		nUsageReporting::report(nUsageReporting::kResourceType_PCVideoServer, 0);

+

+		int numBytes = 0;

+		int imageDataSize = 0;

+		char* imageData = NULL;

+

+		while(!m_stopServer)

+		{

+			success = semTake(m_newImageSem, 1000);

+			if (success == ERROR)

+			{

+				// If the semTake timed out, there are no new images from the camera.

+				continue;

+			}

+			success = AxisCamera::GetInstance().CopyJPEG(&imageData, numBytes, imageDataSize);

+			if (!success)

+			{

+				// No point in running too fast -

+				Wait(1.0);

+				// If camera is not initialzed you will get failure and

+				// the timestamp is invalid. Reset this value and try again.

+				continue;

+			}

+

+			// Write header to PC

+			static const char header[4]={1,0,0,0};

+			int headerSend = write(newPCSock, const_cast<char*>(header), 4);

+

+			// Write image length to PC

+			int lengthSend = write(newPCSock, reinterpret_cast<char*>(&numBytes), 4);

+

+			// Write image to PC

+			int sent = write (newPCSock, imageData, numBytes);

+

+			// The PC probably closed connection. Get out of here

+			// and try listening again.

+			if (headerSend == ERROR || lengthSend == ERROR || sent == ERROR)

+			{

+				break;

+			}

+		}

+		// Clean up

+		delete [] imageData;

+		close (newPCSock);

+		newPCSock = ERROR;

+		close (pcSock);

+		pcSock = ERROR;

+		taskUnsafe();

+		Wait(0.1);

+	}

+	return (OK);

+}

+

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/PCVideoServer.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/PCVideoServer.h
new file mode 100644
index 0000000..bb0a6f3
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/PCVideoServer.h
@@ -0,0 +1,39 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __PC_VIDEO_SERVER_H__

+#define __PC_VIDEO_SERVER_H__

+

+#include "Task.h"

+#include <semLib.h>

+

+/** port for sending video to laptop */

+#define VIDEO_TO_PC_PORT 1180

+

+/**

+ * Class the serves images to the PC.

+ */

+class PCVideoServer : public ErrorBase {

+

+public:

+	PCVideoServer();

+	~PCVideoServer();

+	unsigned int Release();

+	void Start();

+	void Stop();

+

+private:

+	static int s_ServerTask(PCVideoServer *thisPtr);

+	int ServerTask();

+	int StartServerTask();

+

+	Task m_serverTask;

+	SEM_ID m_newImageSem;

+	bool m_stopServer;

+};

+

+#endif

+

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/RGBImage.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/RGBImage.cpp
new file mode 100644
index 0000000..0cca95d
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/RGBImage.cpp
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "RGBImage.h"

+

+/**

+ * Create a new image that uses Red, Green, and Blue planes.

+ */

+RGBImage::RGBImage() : ColorImage(IMAQ_IMAGE_RGB)

+{

+}

+

+/**

+ * Create a new image by loading a file.

+ * @param fileName The path of the file to load.

+ */

+RGBImage::RGBImage(const char *fileName) : ColorImage(IMAQ_IMAGE_RGB)

+{

+	int success = imaqReadFile(m_imaqImage, fileName, NULL, NULL);

+	wpi_setImaqErrorWithContext(success, "Imaq ReadFile error");

+}

+

+RGBImage::~RGBImage()

+{

+}

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/RGBImage.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/RGBImage.h
new file mode 100644
index 0000000..a577e22
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/RGBImage.h
@@ -0,0 +1,23 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __RGB_IMAGE_H__

+#define __RGB_IMAGE_H__

+

+#include "ColorImage.h"

+

+/**

+ * A color image represented in RGB color space at 3 bytes per pixel.

+ */

+class RGBImage : public ColorImage

+{

+public:

+    RGBImage();

+    RGBImage(const char *fileName);

+    virtual ~RGBImage();

+};

+

+#endif

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/Threshold.cpp b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/Threshold.cpp
new file mode 100644
index 0000000..7dcd82f
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/Threshold.cpp
@@ -0,0 +1,18 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#include "Threshold.h"

+

+Threshold::Threshold(int new_plane1Low, int new_plane1High, int new_plane2Low,

+		int new_plane2High, int new_plane3Low, int new_plane3High)

+{

+	plane1Low = new_plane1Low;

+	plane1High = new_plane1High;

+	plane2Low = new_plane2Low;

+	plane2High = new_plane2High;

+	plane3Low = new_plane3Low;

+	plane3High = new_plane3High;

+}

diff --git a/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/Threshold.h b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/Threshold.h
new file mode 100644
index 0000000..faf2718
--- /dev/null
+++ b/azaleasource/WPILibCProgramming/trunk/WPILib/Vision/Threshold.h
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------------------------*/

+/* Copyright (c) FIRST 2008. All Rights Reserved.							  */

+/* Open Source Software - may be modified and shared by FRC teams. The code   */

+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */

+/*----------------------------------------------------------------------------*/

+

+#ifndef __THRESHOLD_H__

+#define __THRESHOLD_H__

+

+/**

+ * Color threshold values.

+ * This object represnts the threshold values for any type of color object

+ * that is used in a threshhold operation. It simplifies passing values

+ * around in a program for color detection.

+ */

+class Threshold 

+{

+public:

+	int plane1Low;

+	int plane1High;

+	int plane2Low;

+	int plane2High;

+	int plane3Low;

+	int plane3High;

+	Threshold(int plane1Low, int plane1High,

+		int plane2Low, int plane2High,

+		int plane3Low, int plane3High);

+};

+

+#endif