-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSingleFrameMode.cpp
638 lines (550 loc) · 21.9 KB
/
SingleFrameMode.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
/**
* @file SingleFrameMode.cpp
*
* @brief C++ Program to take a single frame from a QHYCCD camera.
* The program loops over different temperature, offset, gain, and exposure settings to take multiple pictures in one go.
*
* @author Emaad Paracha
*
*/
// Dependencies
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fitsio.h>
#include "qhyccd.h"
#include <ctime>
#include <cmath>
#include <iostream>
using namespace std;
// !!Important!! -- These functions were tested with the QHY600 camera, some functions may not work properly with other QHYCCD cameras.
// Please comment out relevant functions accordingly
//=============================================
//=============================================
//=================|---------|=================
//=================|FUNCTIONS|=================
//=================|---------|=================
//=============================================
//=============================================
/**
@fn qhyccd_handle CamInitialize(unsigned int retVal, int USB_TRAFFIC, unsigned int roiStartX, unsigned int roiStartY, unsigned int roiSizeX, unsigned int roiSizeY, int camBinX, int camBinY, int readMode)
@brief Initialize the camera, set the readmode, image resolution, binning mode, and bit resolution, and return the camera handle
@param retVal Return value
@param USB_TRAFFIC USB traffic value
@param roiStartX Region of Interest starting X coordinate
@param roiStartY Region of Interest starting Y coordinate
@param roiSizeX Region of Interest size in X
@param roiSizeY Region of Interest size in Y
@param camBinX Camera binning size (X)
@param camBinY Camera binning size (Y)
@param readMode Camera readmode
@return Return QHY camera handle and set readmode, image resolution, binning mode, and bit resolution
*/
qhyccd_handle *CamInitialize(unsigned int retVal, int USB_TRAFFIC, unsigned int roiStartX, unsigned int roiStartY,
unsigned int roiSizeX, unsigned int roiSizeY, int camBinX, int camBinY, int readMode)
{
// Check number of cameras connected
int numCams = ScanQHYCCD();
if (numCams > 0)
{
printf("Number of QHYCCD cameras found: %d. \n", numCams);
printf("\n");
}
else
{
printf("No QHYCCD camera found. Please check USB or power.\n");
exit(1);
}
// Get Camera ID
char camId[32];
retVal = GetQHYCCDId(0, camId);
// Check if we could get camera ID
if (retVal == QHYCCD_SUCCESS)
{
printf("Got Camera ID successfully. ID is %s .\n", camId);
printf("\n");
}
else
{
printf("Could not get camera ID. Error: %d. Program will now exit. \n", retVal);
exit(1);
}
// Open Camera
qhyccd_handle *pCamHandle = OpenQHYCCD(camId);
// Check if we could open the camera
if (retVal == QHYCCD_SUCCESS)
{
printf("Camera opened successfully.\n");
printf("\n");
}
else
{
printf("Could not open camera. Error: %d. Program will now exit. \n", retVal);
exit(1);
}
// Set ReadMode
retVal = SetQHYCCDReadMode(pCamHandle, readMode);
if (retVal != QHYCCD_SUCCESS)
{
printf("Could not set read mode. Error: %d. Program will now exit. \n", retVal);
exit(1);
}
// Set Single Frame Mode (mode = 0)
retVal = SetQHYCCDStreamMode(pCamHandle, 0);
if (retVal != QHYCCD_SUCCESS)
{
printf("Could not set stream mode. Error: %d. Program will now exit. \n", retVal);
exit(1);
}
// Initialize Camera
retVal = InitQHYCCD(pCamHandle);
if (retVal != QHYCCD_SUCCESS)
{
printf("Could not initialize camera. Error: %d. Program will now exit. \n", retVal);
exit(1);
}
printf(" \n");
printf("Hello! Welcome to the QHY Imaging Centre.\n");
printf(" \n");
printf("Connecting to QHY Camera.\n");
printf("QHY Camera initialized successfully. \n");
printf("This is camera ID: %s \n", camId); // To print camera ID
printf(" \n");
printf("Camera readmode set to %d.\n", readMode);
// Set USB Traffic Setting
retVal = SetQHYCCDParam(pCamHandle, CONTROL_USBTRAFFIC, USB_TRAFFIC);
if (retVal == QHYCCD_SUCCESS)
{
printf("USB traffic set to %d.\n", USB_TRAFFIC);
}
else
{
printf("Could not set USB traffic setting. Error: %d.\n", retVal);
}
// Set Image Resolution
retVal = SetQHYCCDResolution(pCamHandle, roiStartX, roiStartY, roiSizeX, roiSizeY);
if (retVal == QHYCCD_SUCCESS)
{
printf("Image resolution set to %dx%d.\n", roiSizeX, roiSizeY);
}
else
{
printf("Could not set the image resolution. Error: %d.\n", retVal);
}
// Set Binning mode
retVal = SetQHYCCDBinMode(pCamHandle, camBinX, camBinY);
if (retVal == QHYCCD_SUCCESS)
{
printf("Binning mode set to %dx%d.\n", camBinX, camBinY);
}
else
{
printf("Could not set the binning mode. Error: %d.\n", retVal);
}
// Set Bit Resolution
retVal = SetQHYCCDBitsMode(pCamHandle, 16);
if (retVal == QHYCCD_SUCCESS)
{
printf("Camera bit resolution set to %d.\n", 16);
}
else
{
printf("Could not set the bit resolution. Error: %d.\n", retVal);
}
printf(" \n");
return pCamHandle;
}
/**
@fn void CamSettings(unsigned int retVal, qhyccd_handle *pCamHandle, int gainSetting, int offsetSetting, double exposureTime)
@brief Sets the gain, offset, and exposure time of the camera
@param retVal Return value
@param pCamHandle Camera handle
@param gainSetting Gain setting to set camera to
@param offsetSetting Offset setting to set camera to
@param exposureTime Exposure time
*/
void CamSettings(unsigned int retVal, qhyccd_handle *pCamHandle, int gainSetting, int offsetSetting,
double exposureTime)
{
// Set Gain Setting
retVal = SetQHYCCDParam(pCamHandle, CONTROL_GAIN, gainSetting);
if (retVal == QHYCCD_SUCCESS)
{
printf("Gain set to %d.\n", gainSetting);
}
else
{
printf("Could not set the gain setting. Error: %d.\n", retVal);
}
// Set Offset
retVal = SetQHYCCDParam(pCamHandle, CONTROL_OFFSET, offsetSetting);
if (retVal == QHYCCD_SUCCESS)
{
printf("Offset set to %d.\n", offsetSetting);
}
else
{
printf("Could not set the offset setting. Error: %d.\n", retVal);
}
// Set Exposure Time
retVal = SetQHYCCDParam(pCamHandle, CONTROL_EXPOSURE, exposureTime);
if (retVal == QHYCCD_SUCCESS)
{
printf("Exposure set to %.6f seconds. \n", exposureTime / 1000000);
}
else
{
printf("Could not set the exposure time. Error: %d.\n", retVal);
}
}
/**
@fn void TempRegulation(unsigned int retVal, qhyccd_handle *pCamHandle, double tempSetting, double tempError)
@brief Sets the temperature of the camera sensor within the specified temperature error range
@param retVal Return value
@param pCamHandle Camera handle
@param tempSetting Temperature to set camera to
@param tempError Temperature setting error range
*/
void TempRegulation(unsigned int retVal, qhyccd_handle *pCamHandle, double tempSetting, double tempError)
{
printf(" \n"); // Print new line
// Get Current Temperature
double currentTemp = GetQHYCCDParam(pCamHandle, CONTROL_CURTEMP);
// Set Temperature to the temperature setting we want
retVal = SetQHYCCDParam(pCamHandle, CONTROL_COOLER, tempSetting);
if (retVal != QHYCCD_SUCCESS)
{
printf("Could not set the temperature. Error: %d.\n", retVal);
return; // Return if we could not set the temperature
}
// Get cooler PWM value
double pwmValue = GetQHYCCDParam(pCamHandle, CONTROL_CURPWM);
// If the temperature is not within the error range
if (abs(currentTemp - tempSetting) > tempError)
{
// Then run the check temperature loop thrice to avoid overshooting
for (int tempLoop = 0; tempLoop < 3; tempLoop++)
{
// Sleep for 1 second to get new temperature
sleep(1);
// Get current temperature again to loop
currentTemp = GetQHYCCDParam(pCamHandle, CONTROL_CURTEMP);
// While the temperature is outside of the error range
while (abs(currentTemp - tempSetting) > tempError)
{
// Get cooler PWM again
pwmValue = GetQHYCCDParam(pCamHandle, CONTROL_CURPWM);
// Report temperature progress and cooler PWM to screen
if ((currentTemp - tempSetting) > tempError)
{
printf("Current Temperature: %.2f || You Want: %.2f . Camera is cooling down. \n", currentTemp, tempSetting);
printf("Cooler PWM is %.1f, running at %.1f%% of full power. \n", pwmValue, pwmValue / 255.0 * 100);
printf(" \n");
}
else
{
printf("Current Temperature: %.2f || You Want: %.2f . Camera is heating up. \n", currentTemp, tempSetting);
printf("Cooler PWM is %.1f, running at %.1f%% of full power. \n", pwmValue, pwmValue / 255.0 * 100);
printf(" \n");
}
// Try again in 2 seconds
sleep(2);
// Get current temperature again to loop again
currentTemp = GetQHYCCDParam(pCamHandle, CONTROL_CURTEMP);
}
}
// Sleep for 1 second before running
sleep(1);
}
printf("Camera temperature set to %.2f C. \n", tempSetting);
}
/**
@fn void FilterWheelControl(unsigned int retVal, qhyccd_handle *pCamHandle, char fwPosition)
@brief Checks if a filter wheel is connected and if so, moves the filter wheel to the requested position
@param retVal Return value
@param pCamHandle Camera handle
@param fwPosition Filter wheel position to move to
*/
void FilterWheelControl(unsigned int retVal, qhyccd_handle *pCamHandle, int fwPos)
{
retVal = IsQHYCCDCFWPlugged(pCamHandle); // Check if filter wheel is plugged in
char fwPosition = '0' + fwPos;
// If filter wheel is plugged in
if (retVal == QHYCCD_SUCCESS)
{
char status[64] = {0};
retVal = GetQHYCCDCFWStatus(pCamHandle, status); // Get current position
if (retVal == QHYCCD_SUCCESS)
{
printf("Filter wheel is plugged in and is at position: %s. \n", status); // Print current position
}
else
{
printf("Could not get filter wheel status. Error: %d.\n", retVal); // Print error
}
// Compare if the filter wheel is at the position we want it to be
if (status[0] != fwPosition)
{
retVal = SendOrder2QHYCCDCFW(pCamHandle, &fwPosition, 1); // Send order to filter wheel to move to new position
if (retVal == QHYCCD_SUCCESS)
{
printf("Filter wheel is moving to position: %c. \n", fwPosition); // Print that the filter wheel is moving
}
else
{
printf("Could not move filter wheel. Error: %d.\n", retVal); // Print error
}
// Check if filter wheel is moving
retVal = GetQHYCCDCFWStatus(pCamHandle, status);
if (retVal != QHYCCD_SUCCESS)
{
printf("Could not get filter wheel status. Error: %d.\n", retVal); // Print error
}
// If filter wheel needs to go to position 0 (slot 1)
if (status[0] == fwPosition)
{
int sleeper = 0; // To print progress on screen
while (sleeper < 11)
{
sleep(1); // Sleep for 1 second
printf("Filter wheel is still moving.\n");
sleeper++; // Add onto sleeper
}
}
else // If filter wheel needs to go to any other position
{
// While camera is moving
while (fwPosition != status[0])
{
sleep(1); // Sleep for 1 second
retVal = GetQHYCCDCFWStatus(pCamHandle, status); // Check status again
if (retVal != QHYCCD_SUCCESS)
{
printf("Could not get filter wheel status. Error: %d.\n", retVal); // Print error
}
else
{
printf("Filter wheel is still moving.\n"); // Print that the filter wheel is still moving
}
}
}
// Print final position of filter wheel
printf("Filter wheel has been moved to position: %c. \n", fwPosition); // Print new position
}
}
// If filter wheel is not detected
else
{
printf("No filter wheel detected. \n"); // Print that it is not detected
}
printf("\n");
}
/**
@fn void CamCapture(unsigned int retVal, qhyccd_handle *pCamHandle, int runTimes, int runner, unsigned int roiStartX, unsigned int roiStartY, unsigned int roiSizeX, unsigned int roiSizeY, unsigned int bpp, int gainSetting, int offsetSetting, double exposureTime, double tempSetting, int readMode, string savePath)
@brief Takes an image and saves a .fits file to disk with the settings in the filename
@param retVal Return value
@param pCamHandle Camera handle
@param runTimes Number of times to take pictures at each specific setting
@param runner The number of image being taken at that specific setting
@param roiStartX Region of Interest starting X coordinate
@param roiStartY Region of Interest starting Y coordinate
@param roiSizeX Region of Interest size in X
@param roiSizeY Region of Interest size in Y
@param bpp Channel of image
@param gainSetting Gain setting to set camera to
@param offsetSetting Offset setting to set camera to
@param exposureTime Exposure time
@param tempSetting Temperature to set camera to
@param readMode Camera readmode
@param savePath Path to save image to
*/
void CamCapture(unsigned int retVal, qhyccd_handle *pCamHandle, int runTimes, int runner, unsigned int roiStartX,
unsigned int roiStartY, unsigned int roiSizeX, unsigned int roiSizeY, unsigned int bpp, int gainSetting,
int offsetSetting, double exposureTime, double tempSetting, int readMode, string savePath)
{
// Channel of Image
unsigned int channels;
// Single Frame
retVal = ExpQHYCCDSingleFrame(pCamHandle);
if (retVal != QHYCCD_SUCCESS)
{
printf("Could not start exposure. Error: %d. \n", retVal);
}
// Image Data Variable
unsigned char *pImgData = 0;
// Get Requested Memory Length
uint32_t length = GetQHYCCDMemLength(pCamHandle);
pImgData = new unsigned char[length];
memset(pImgData, 0, length);
printf("Buffer length = %d.\n", length);
// Take Single Frame
retVal = GetQHYCCDSingleFrame(pCamHandle, &roiSizeX, &roiSizeY, &bpp, &channels, pImgData);
if (retVal == QHYCCD_SUCCESS)
{
printf("Successfully got image of size: %dx%d.\n", roiSizeX, roiSizeY);
}
else
{
printf("Could not grab image data from camera. Error: %d. \n", retVal);
}
// Image Processing to .fits file
// Create File
fitsfile *fptr;
int status = 0;
long naxes[2] = {roiSizeX, roiSizeY};
long curUnixTime = time(0);
// Naming:
string fitname = savePath + "_" + to_string(curUnixTime) + "_exp_" + to_string((int)exposureTime) + "us_gain_" + to_string(gainSetting) + "_offset_" + to_string(offsetSetting) + "_temp_" + to_string((int)tempSetting) + "_" + to_string(runner) + ".fits";
const char *fitsfilename = fitname.c_str();
// Remove if exists already
remove(fitsfilename);
// Create File
fits_create_file(&fptr, fitsfilename, &status);
fits_create_img(fptr, USHORT_IMG, 2, naxes, &status);
// Headers Information
fits_update_key(fptr, TDOUBLE, "INTTEMP", &tempSetting, "Camera Temperature", &status);
fits_update_key(fptr, TINT, "EXPTIME", &exposureTime, "Exposure time in microseconds", &status);
fits_update_key(fptr, TINT, "OFFSET", &offsetSetting, "Offset Setting", &status);
fits_update_key(fptr, TINT, "GAIN", &gainSetting, "Gain Setting", &status);
fits_update_key(fptr, TINT, "QHREADMOE", &readMode, "ReadMode Setting", &status);
fits_update_key(fptr, TLONG, "TIME", &curUnixTime, "UNIX Time", &status);
// Write to File
fits_write_img(fptr, TUSHORT, 1, roiSizeX * roiSizeY, pImgData, &status);
// Close File
fits_close_file(fptr, &status);
// Report progress
printf("Image with temp %.2fC, exp %.3fsec, offset %d, gain %d, saved successfully to disc.\n", tempSetting, exposureTime / 1000000, offsetSetting, gainSetting);
printf(" \n");
// Delete Image Data
delete[] pImgData;
// Cancel Exposing and Readout
retVal = CancelQHYCCDExposingAndReadout(pCamHandle);
if (retVal == QHYCCD_SUCCESS)
{
printf("Exposure and readout cancelled successfully.\n");
}
else
{
printf("Could not cancel exposure and readout. Error: %d. \n", retVal);
}
}
/**
@fn void CamExit(unsigned int retVal, qhyccd_handle *pCamHandle)
@brief Closes camera and releases SDK resource
@param retVal Return value
@param pCamHandle Camera handle
*/
void CamExit(unsigned int retVal, qhyccd_handle *pCamHandle)
{
// Close Camera Handle
retVal = CloseQHYCCD(pCamHandle);
if (retVal == QHYCCD_SUCCESS)
{
printf("Camera handle closed successfully. \n");
}
else
{
printf("Could not close camera handle. Error: %d. \n", retVal);
}
// Release SDK Resources
retVal = ReleaseQHYCCDResource();
if (retVal == QHYCCD_SUCCESS)
{
printf("SDK resources released successfully. \n");
}
else
{
printf("Could not release SDK resources. Error: %d. Program will now exit.\n", retVal);
exit(1);
}
printf("Goodbye! Please visit us again.\n");
}
//===============================================
//===============================================
//=================|-----------|=================
//=================|THE PROGRAM|=================
//=================|-----------|=================
//===============================================
//===============================================
int main(int argc, char *argv[])
{
// Variables Preset
unsigned int roiStartX = 0; // ROI Start x
unsigned int roiStartY = 0; // ROI Start y
unsigned int roiSizeX = 9600; // Max x
unsigned int roiSizeY = 6422; // Max y
int camBinX = 1; // Binning
int camBinY = 1; // Binning
int USB_TRAFFIC = 10; // USB Traffic
unsigned int bpp = 16; // Bit Depth of Image
int readMode = 1; // ReadMode
const int SECOND = 1000000; // Constant to multiply exposure time with, since QHY600M takes microseconds
// Initialize SDK
unsigned int retVal = InitQHYCCDResource();
// Check if SDK resources were initialized
if (retVal == QHYCCD_SUCCESS)
{
printf("SDK resources initialized successfully .\n");
printf("\n");
}
else
{
printf("SDK resources could not be initialized. Error: %d. Program will now exit. \n", retVal);
exit(1);
}
// Initialize the camera and set initial settings
qhyccd_handle *pCamHandle = CamInitialize(retVal, USB_TRAFFIC, roiStartX, roiStartY, roiSizeX, roiSizeY, camBinX, camBinY, readMode);
retVal = SetQHYCCDParam(pCamHandle, CONTROL_MANULPWM, 0);
// The List of All Variables -- SET THESE TO TAKE IMAGES
int sampleGains[] = {56,60}; // List of gain settings to loop over
int sampleOffsets[] = {20,40}; // List of offset setings to loop over
double sampleTemps[] = {18,20}; // List of temperatures to loop over (in Celsius)
double sampleExps[] = {5,10}; // List of exposure times to loop over (in seconds)
int howManyTimesToRun = 2; // How many times to take pictures at each unique setting
double tempError = 0.3; // Temperature regulation error range
int fwPosition = 2; // Set this to the filter wheel position you want (between 0 and 6)
int totalNumberOfFiles = sizeof(sampleTemps) / sizeof(sampleTemps[0]) * sizeof(sampleOffsets) / sizeof(sampleOffsets[0]) * sizeof(sampleGains) / sizeof(sampleGains[0]) * sizeof(sampleExps) / sizeof(sampleExps[0]) * howManyTimesToRun; // How many images will be taken
int takingImage = 1; // Which image is being taken
// LoOp ThE lOoPs and take the pictures
for (unsigned int t = 0; t < sizeof(sampleTemps) / sizeof(sampleTemps[0]); t++)
{
for (unsigned int o = 0; o < sizeof(sampleOffsets) / sizeof(sampleOffsets[0]); o++)
{
for (unsigned int g = 0; g < sizeof(sampleGains) / sizeof(sampleGains[0]); g++)
{
for (unsigned int e = 0; e < sizeof(sampleExps) / sizeof(sampleExps[0]); e++)
{
double exposureTime = sampleExps[e] * SECOND; // Exposure time (in us)
int gainSetting = sampleGains[g]; // Gain Setting
int offsetSetting = sampleOffsets[o]; // Offset Setting
double tempSetting = sampleTemps[t]; // Temperature of Camera
int runTimes = howManyTimesToRun; // How Many Pictures To Get
string savePath = "/home/user/Documents/Images/qhyImg"; // Path to save image with first part of image name at the end
// Operate filter wheel
FilterWheelControl(retVal, pCamHandle, fwPosition);
// Set camera settings
CamSettings(retVal, pCamHandle, gainSetting, offsetSetting, exposureTime);
// Set and regulate temperature
TempRegulation(retVal, pCamHandle, tempSetting, tempError);
// Loop to take multiple pictures
for (int runner = 0; runner < runTimes; runner++)
{
// Set and regulate temperature again
TempRegulation(retVal, pCamHandle, tempSetting, tempError);
// Print which image is being taken
printf("Taking image %d of %d images... \n", takingImage, totalNumberOfFiles);
// Take the picture and save it
CamCapture(retVal, pCamHandle, runTimes, runner, roiStartX, roiStartY, roiSizeX, roiSizeY, bpp, gainSetting, offsetSetting, exposureTime, tempSetting, readMode, savePath);
// Increment takingImage
takingImage++;
}
}
}
}
}
// Close camera and release SDK resources
CamExit(retVal, pCamHandle);
// Exit
return 0;
}