Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2484 - 1
using System;
2
using System.Collections.Generic;
3
using System.Drawing;
4
using System.Drawing.Imaging;
5
using System.Runtime.InteropServices;
6
using WebCamLib;
7
 
8
namespace Touchless.Vision.Camera
9
{
10
   public enum CameraProperty : int
11
   {
12
      Pan_degrees = WebCamLib.CameraProperty.Pan_degrees,
13
      Tilt_degrees = WebCamLib.CameraProperty.Tilt_degrees,
14
      Roll_degrees = WebCamLib.CameraProperty.Roll_degrees,
15
      Zoom_mm = WebCamLib.CameraProperty.Zoom_mm,
16
      Exposure_lgSec = WebCamLib.CameraProperty.Exposure_lgSec,
17
      Iris_10f = WebCamLib.CameraProperty.Iris_10f,
18
      FocalLength_mm = WebCamLib.CameraProperty.FocalLength_mm,
19
      Flash = WebCamLib.CameraProperty.Flash,
20
      Brightness = WebCamLib.CameraProperty.Brightness,
21
      Contrast = WebCamLib.CameraProperty.Brightness,
22
      Hue = WebCamLib.CameraProperty.Contrast,
23
      Saturation = WebCamLib.CameraProperty.Saturation,
24
      Sharpness = WebCamLib.CameraProperty.Sharpness,
25
      Gamma = WebCamLib.CameraProperty.Gamma,
26
      ColorEnable = WebCamLib.CameraProperty.ColorEnable,
27
      WhiteBalance = WebCamLib.CameraProperty.WhiteBalance,
28
      BacklightCompensation = WebCamLib.CameraProperty.BacklightCompensation,
29
      Gain = WebCamLib.CameraProperty.Gain,
30
   }
31
 
32
   public sealed class CameraPropertyValue : IComparable<CameraPropertyValue>, IEquatable<CameraPropertyValue>
33
   {
34
      public CameraPropertyValue( bool isPercentageValue, int value, bool isAuto )
35
      {
36
         IsPercentageValue = isPercentageValue;
37
         Value = value;
38
         IsAuto = isAuto;
39
      }
40
 
41
      public int Value
42
      {
43
         get;
44
         set;
45
      }
46
 
47
      private bool isAuto;
48
 
49
      public bool IsAuto
50
      {
51
         get
52
         {
53
            return isAuto;
54
         }
55
 
56
         set
57
         {
58
            isAuto = value;
59
         }
60
      }
61
 
62
      public bool IsManual
63
      {
64
         get
65
         {
66
            return !IsAuto;
67
         }
68
 
69
         set
70
         {
71
            IsAuto = !value;
72
         }
73
      }
74
 
75
      private bool isPercentageValue;
76
 
77
      public bool IsActualValue
78
      {
79
         get
80
         {
81
            return !IsPercentageValue;
82
         }
83
 
84
         set
85
         {
86
            IsPercentageValue = !value;
87
         }
88
      }
89
 
90
      public bool IsPercentageValue
91
      {
92
         get
93
         {
94
            return isPercentageValue;
95
         }
96
 
97
         set
98
         {
99
            isPercentageValue = value;
100
         }
101
      }
102
 
103
      #region ICompare<CameraPropertyValue> Members
104
 
105
      public int CompareTo( CameraPropertyValue other )
106
      {
107
         int result = 0;
108
 
109
         if( IsActualValue && other.IsPercentageValue )
110
            result = -1;
111
         else if( IsPercentageValue && other.IsActualValue )
112
            result = 1;
113
         else
114
         {
115
            if( Value < other.Value )
116
               result = -1;
117
            else if( Value > other.Value )
118
               result = 1;
119
            else
120
            {
121
               if( IsAuto && other.IsManual )
122
                  result = -1;
123
               else if( IsManual && other.IsAuto )
124
                  result = 1;
125
            }
126
         }
127
 
128
         return result;
129
      }
130
 
131
      #endregion
132
 
133
      #region IEquatable<CameraPropertyValue> Members
134
 
135
      public bool Equals( CameraPropertyValue other )
136
      {
137
         return Object.ReferenceEquals( this, other ) || CompareTo( other ) == 0;
138
      }
139
 
140
      #endregion
141
 
142
      public override bool Equals( Object obj )
143
      {
144
         bool result;
145
 
146
         if( !( result = Object.ReferenceEquals( this, obj ) ) )
147
         {
148
            CameraPropertyValue other = obj as CameraPropertyValue;
149
 
150
            if( result = other != null )
151
               result = Equals( other );
152
         }
153
 
154
         return result;
155
      }
156
   }
157
 
158
   public sealed class CameraPropertyRange : IComparable<CameraPropertyRange>, IEquatable<CameraPropertyRange>
159
   {
160
      public CameraPropertyRange( int minimum, int maximum, int step, int defaults, bool isAuto )
161
      {
162
         Minimum = minimum;
163
         Maximum = maximum;
164
         Step = step;
165
         Defaults = defaults;
166
         IsAuto = isAuto;
167
      }
168
 
169
      public int Minimum
170
      {
171
         get;
172
         private set;
173
      }
174
 
175
      public int Maximum
176
      {
177
         get;
178
         private set;
179
      }
180
 
181
      public int Range
182
      {
183
         get
184
         {
185
            return Maximum - Minimum;
186
         }
187
      }
188
 
189
      public int DomainSize
190
      {
191
         get
192
         {
193
            return Range + 1;
194
         }
195
      }
196
 
197
      public int Step
198
      {
199
         get;
200
         private set;
201
      }
202
 
203
      public int Defaults
204
      {
205
         get;
206
         private set;
207
      }
208
 
209
      public bool IsAuto
210
      {
211
         get;
212
         private set;
213
      }
214
 
215
      public bool IsManual
216
      {
217
         get
218
         {
219
            return !IsAuto;
220
         }
221
      }
222
 
223
      #region ICompare<CameraPropertyRange> Members
224
 
225
      public int CompareTo( CameraPropertyRange other )
226
      {
227
         int result = 0;
228
 
229
         if( Minimum < other.Minimum )
230
            result = -1;
231
         else if( Minimum > other.Minimum )
232
            result = 1;
233
         else
234
         {
235
            if( Maximum < other.Maximum )
236
               result = -1;
237
            else if( Maximum > other.Maximum )
238
               result = 1;
239
            else
240
            {
241
               if( Step < other.Step )
242
                  result = -1;
243
               else if( Step > other.Step )
244
                  result = 1;
245
               else
246
               {
247
                  if( Defaults < other.Defaults )
248
                     result = -1;
249
                  else if( Defaults > other.Defaults )
250
                     result = 1;
251
                  else
252
                  {
253
                     if( IsAuto && other.IsManual )
254
                        result = -1;
255
                     else if( IsManual && other.IsAuto )
256
                        result = 1;
257
                  }
258
               }
259
            }
260
         }
261
 
262
         return result;
263
      }
264
 
265
      #endregion
266
 
267
      #region IEquatable<CameraPropertyRange> Members
268
 
269
      public bool Equals( CameraPropertyRange other )
270
      {
271
         return Object.ReferenceEquals( this, other ) || CompareTo( other ) == 0;
272
      }
273
 
274
      #endregion
275
 
276
      public override bool Equals( Object obj )
277
      {
278
         bool result;
279
 
280
         if( !( result = Object.ReferenceEquals( this, obj ) ) )
281
         {
282
            CameraPropertyRange other = obj as CameraPropertyRange;
283
 
284
            if( result = other != null )
285
               result = Equals( other );
286
         }
287
 
288
         return result;
289
      }
290
   }
291
 
292
   public sealed class CameraPropertyCapabilities : IComparable<CameraPropertyCapabilities>, IEquatable<CameraPropertyCapabilities>
293
   {
294
      internal CameraPropertyCapabilities( Camera camera, WebCamLib.CameraPropertyCapabilities capabilities )
295
      {
296
         Camera = camera;
297
         InternalCapabilities = capabilities;
298
      }
299
 
300
      public Camera Camera
301
      {
302
         get;
303
         private set;
304
      }
305
 
306
      internal WebCamLib.CameraPropertyCapabilities InternalCapabilities
307
      {
308
         get;
309
         private set;
310
      }
311
 
312
      public bool IsSupported
313
      {
314
         get
315
         {
316
            return InternalCapabilities.IsSupported;
317
         }
318
      }
319
 
320
      public bool IsFullySupported
321
      {
322
         get
323
         {
324
            return InternalCapabilities.IsFullySupported;
325
         }
326
      }
327
 
328
      public bool IsGetSupported
329
      {
330
         get
331
         {
332
            return InternalCapabilities.IsGetSupported;
333
         }
334
      }
335
 
336
      public bool IsSetSupported
337
      {
338
         get
339
         {
340
            return InternalCapabilities.IsSetSupported;
341
         }
342
      }
343
 
344
      public bool IsGetRangeSupported
345
      {
346
         get
347
         {
348
            return InternalCapabilities.IsGetRangeSupported;
349
         }
350
      }
351
 
352
      #region IComparable<CameraPropertyCapabilities> Members
353
      // sort order: IsGetSupported, IsSetSupported, IsGetRangeSupported; this exists and other doesn't first/less for all keys
354
      public int CompareTo( CameraPropertyCapabilities other )
355
      {
356
         int result = 0;
357
 
358
         if( IsGetSupported && !other.IsGetSupported )
359
            result = -1;
360
         else if( !IsGetSupported && other.IsGetSupported )
361
            result = 1;
362
         else
363
         {
364
            if( IsSetSupported && !other.IsSetSupported )
365
               result = -1;
366
            else if( !IsSetSupported && other.IsSetSupported )
367
               result = 1;
368
            else
369
            {
370
               if( IsGetRangeSupported && !other.IsGetRangeSupported )
371
                  result = -1;
372
               else if( !IsGetRangeSupported && other.IsGetRangeSupported )
373
                  result = 1;
374
            }
375
         }
376
 
377
         return result;
378
      }
379
      #endregion
380
 
381
      #region IEquatable<CameraPropertyCapabilities>
382
      public bool Equals( CameraPropertyCapabilities other )
383
      {
384
         return CompareTo( other ) == 0;
385
      }
386
      #endregion
387
 
388
      public override bool Equals( object obj )
389
      {
390
         bool result;
391
 
392
         CameraPropertyCapabilities capabilities = obj as CameraPropertyCapabilities;
393
 
394
         if( result = capabilities != null )
395
            result = Equals( capabilities );
396
 
397
         return result;
398
      }
399
   }
400
 
401
   public sealed class CaptureSize : IComparable<CaptureSize>, IEquatable<CaptureSize>
402
   {
403
      public CaptureSize( int width, int height, int colorDepth )
404
      {
405
         Width = width;
406
         Height = height;
407
         ColorDepth = colorDepth;
408
      }
409
 
410
      public int Width
411
      {
412
         get;
413
         private set;
414
      }
415
 
416
      public int Height
417
      {
418
         get;
419
         private set;
420
      }
421
 
422
      public int ColorDepth
423
      {
424
         get;
425
         private set;
426
      }
427
 
428
      public override String ToString()
429
      {
430
         return String.Format( "{0} x {1} @ {2}", Width, Height, ColorDepth );
431
      }
432
 
433
      #region IComparable<CaptureSize> Members
434
 
435
      public int CompareTo( CaptureSize other )
436
      {
437
         int result;
438
 
439
         if( Width < other.Width )
440
            result = -1;
441
         else if( Width > other.Width )
442
            result = 1;
443
         else
444
         {
445
            if( Height < other.Height )
446
               result = -1;
447
            else if( Height > other.Height )
448
               result = 1;
449
            else
450
            {
451
               if( ColorDepth < other.ColorDepth )
452
                  result = -1;
453
               else if( ColorDepth > other.ColorDepth )
454
                  result = 1;
455
               else
456
                  result = 0;
457
            }
458
         }
459
 
460
         return result;
461
      }
462
 
463
      #endregion
464
 
465
      #region IEquatable<CaptureSize> Members
466
 
467
      public bool Equals( CaptureSize other )
468
      {
469
         return Object.ReferenceEquals( this, other ) || CompareTo( other ) == 0;
470
      }
471
 
472
      #endregion
473
 
474
      public override bool Equals( Object obj )
475
      {
476
         bool result;
477
 
478
         if( !( result = Object.ReferenceEquals( this, obj ) ) )
479
         {
480
            CaptureSize other = obj as CaptureSize;
481
            if( result = other != null )
482
               result = Equals( other );
483
         }
484
 
485
         return result;
486
      }
487
 
488
      public override int GetHashCode()
489
      {
490
         int result = 0;
491
 
492
         result ^= Width;
493
         result ^= Height << 11;
494
         result ^= ColorDepth << 23;
495
 
496
         return result;
497
      }
498
   }
499
 
500
   /// <summary>
501
   /// Represents a camera in use by the Touchless system
502
   /// </summary>
503
   public class Camera : IDisposable
504
   {
505
      public const int IgnoredBitsPerPixel = -1;
506
 
507
      private readonly Object CameraMethodsLock = new Object();
508
 
509
      private readonly CameraMethods _cameraMethods;
510
      private RotateFlipType _rotateFlip = RotateFlipType.RotateNoneFlipNone;
511
 
512
      public Camera( CameraMethods cameraMethods, string name, int index )
513
      {
514
         _name = name;
515
         _index = index;
516
 
517
         lock( CameraMethodsLock )
518
         {
519
            _cameraMethods = cameraMethods;
520
            _cameraMethods.OnImageCapture += CaptureCallbackProc;
521
         }
522
      }
523
 
524
      public string Name
525
      {
526
         get
527
         {
528
            return _name;
529
         }
530
      }
531
 
532
      /// <summary>
533
      /// Defines the frames per second limit that is in place, -1 means no limit
534
      /// </summary>
535
      public int Fps
536
      {
537
         get
538
         {
539
            return _fpslimit;
540
         }
541
         set
542
         {
543
            _fpslimit = value;
544
            _timeBetweenFrames = ( 1000.0 / _fpslimit );
545
         }
546
      }
547
 
548
      /// <summary>
549
      /// Determines the width of the image captured
550
      /// </summary>
551
      public int CaptureWidth
552
      {
553
         get
554
         {
555
            return _width;
556
         }
557
         set
558
         {
559
            _width = value;
560
         }
561
      }
562
 
563
      /// <summary>
564
      /// Defines the height of the image captured
565
      /// </summary>
566
      public int CaptureHeight
567
      {
568
         get
569
         {
570
            return _height;
571
         }
572
         set
573
         {
574
            _height = value;
575
         }
576
      }
577
 
578
      /// <summary>
579
      /// Defines the bits per pixel of image captured.
580
      /// </summary>
581
      public int CaptureBitsPerPixel
582
      {
583
         get
584
         {
585
            return _bpp;
586
         }
587
 
588
         set
589
         {
590
            _bpp = value;
591
         }
592
      }
593
 
594
      public bool HasFrameLimit
595
      {
596
         get
597
         {
598
            return _fpslimit != -1;
599
         }
600
      }
601
 
602
      public bool FlipHorizontal
603
      {
604
         get
605
         {
606
            return RotateFlip == RotateFlipType.RotateNoneFlipX || RotateFlip == RotateFlipType.Rotate180FlipNone;
607
         }
608
 
609
         set
610
         {
611
            if( value && FlipVertical )
612
            {
613
               RotateFlip = RotateFlipType.Rotate180FlipNone;
614
            }
615
            else if( value && !FlipVertical )
616
            {
617
               RotateFlip = RotateFlipType.RotateNoneFlipX;
618
            }
619
            else if( !value && FlipVertical )
620
            {
621
               RotateFlip = RotateFlipType.Rotate180FlipX;
622
            }
623
            else if( !value && !FlipVertical )
624
            {
625
               RotateFlip = RotateFlipType.RotateNoneFlipNone;
626
            }
627
         }
628
      }
629
 
630
      public bool FlipVertical
631
      {
632
         get
633
         {
634
            return RotateFlip == RotateFlipType.Rotate180FlipX || RotateFlip == RotateFlipType.Rotate180FlipNone;
635
         }
636
 
637
         set
638
         {
639
            if( value && FlipHorizontal )
640
            {
641
               RotateFlip = RotateFlipType.Rotate180FlipNone;
642
            }
643
            else if( value && !FlipHorizontal )
644
            {
645
               RotateFlip = RotateFlipType.Rotate180FlipX;
646
            }
647
            else if( !value && FlipHorizontal )
648
            {
649
               RotateFlip = RotateFlipType.RotateNoneFlipX;
650
            }
651
            else if( !value && !FlipHorizontal )
652
            {
653
               RotateFlip = RotateFlipType.RotateNoneFlipNone;
654
            }
655
         }
656
      }
657
 
658
      /// <summary>
659
      /// Command for rotating and flipping incoming images
660
      /// </summary>
661
      public RotateFlipType RotateFlip
662
      {
663
         get
664
         {
665
            return _rotateFlip;
666
         }
667
         set
668
         {
669
            // Swap height/width when rotating by 90 or 270
670
            if( ( int ) _rotateFlip % 2 != ( int ) value % 2 )
671
            {
672
               int temp = CaptureWidth;
673
               CaptureWidth = CaptureHeight;
674
               CaptureHeight = temp;
675
            }
676
            _rotateFlip = value;
677
         }
678
      }
679
 
680
      #region IDisposable Members
681
 
682
      /// <summary>
683
      /// Cleanup function for the camera
684
      /// </summary>
685
      public void Dispose()
686
      {
687
         StopCapture();
688
      }
689
 
690
      #endregion
691
 
692
      /// <summary>
693
      /// Returns the last image acquired from the camera
694
      /// </summary>
695
      /// <returns>A bitmap of the last image acquired from the camera</returns>
696
      public Bitmap GetCurrentImage()
697
      {
698
         Bitmap b = null;
699
         lock( _bitmapLock )
700
         {
701
            if( _bitmap == null )
702
            {
703
               return null;
704
            }
705
 
706
            b = new Bitmap( _bitmap );
707
         }
708
 
709
         return b;
710
      }
711
 
712
      public void ShowPropertiesDialog()
713
      {
714
         lock( CameraMethodsLock )
715
         {
716
            _cameraMethods.DisplayCameraPropertiesDialog( _index );
717
         }
718
      }
719
 
720
      public CameraInfo GetCameraInfo()
721
      {
722
         lock( CameraMethodsLock )
723
         {
724
            return _cameraMethods.GetCameraInfo( _index );
725
         }
726
      }
727
 
728
      #region Camera Properties
729
      public bool IsCameraPropertySupported( CameraProperty property )
730
      {
731
         bool result = false;
732
 
733
         lock( CameraMethodsLock )
734
         {
735
            _cameraMethods.IsPropertySupported( ( WebCamLib.CameraProperty ) property, ref result );
736
         }
737
 
738
         return result;
739
      }
740
 
741
      public bool SetCameraProperty( CameraProperty property, CameraPropertyValue value )
742
      {
743
         bool result;
744
 
745
         if( value.IsActualValue )
746
            result = SetCameraProperty_value( property, value.Value, value.IsAuto );
747
         else // if( value.IsPercentageValue )
748
            result = SetCameraProperty_percentage( property, value.Value, value.IsAuto );
749
 
750
         return result;
751
      }
752
 
753
      public bool SetCameraProperty( CameraProperty property, bool isActualValue, int value )
754
      {
755
         bool result = false;
756
 
757
         if( isActualValue )
758
            result = SetCameraProperty_value( property, value );
759
         else // is percentage value
760
            result = SetCameraProperty_percentage( property, value );
761
 
762
         return result;
763
      }
764
 
765
      public bool SetCameraProperty( CameraProperty property, bool isActualValue, int value, bool auto )
766
      {
767
         bool result = false;
768
 
769
         if( isActualValue )
770
            result = SetCameraProperty_value( property, value, auto );
771
         else // is percentage value
772
            result = SetCameraProperty_percentage( property, value, auto );
773
 
774
         return result;
775
      }
776
 
777
      public bool SetCameraProperty_value( CameraProperty property, bool auto )
778
      {
779
         return SetCameraProperty_value( property, 0, auto );
780
      }
781
 
782
      // Assume manual control
783
      public bool SetCameraProperty_value( CameraProperty property, int value )
784
      {
785
         return SetCameraProperty_value( property, value, false );
786
      }
787
 
788
      public bool SetCameraProperty_value( CameraProperty property, int value, bool auto )
789
      {
790
         bool result = false;
791
 
792
         lock( CameraMethodsLock )
793
         {
794
            _cameraMethods.SetProperty_value( ( WebCamLib.CameraProperty ) property, value, auto, ref result );
795
         }
796
 
797
         return result;
798
      }
799
 
800
      public bool SetCameraProperty_percentage( CameraProperty property, bool auto )
801
      {
802
         return SetCameraProperty_percentage( property, 0, auto );
803
      }
804
 
805
      // Assume manual control
806
      public bool SetCameraProperty_percentage( CameraProperty property, int percentage )
807
      {
808
         return SetCameraProperty_percentage( property, percentage, false );
809
      }
810
 
811
      public bool SetCameraProperty_percentage( CameraProperty property, int percentage, bool auto )
812
      {
813
         bool result = false;
814
 
815
         lock( CameraMethodsLock )
816
         {
817
            _cameraMethods.SetProperty_percentage( ( WebCamLib.CameraProperty ) property, percentage, auto, ref result );
818
         }
819
 
820
         return result;
821
      }
822
 
823
      public CameraPropertyValue GetCameraProperty( CameraProperty property, bool isActualValue )
824
      {
825
         CameraPropertyValue result;
826
 
827
         if( isActualValue )
828
            result = GetCameraProperty_value( property );
829
         else // is percentage value
830
            result = GetCameraProperty_percentage( property );
831
 
832
         return result;
833
      }
834
 
835
      public CameraPropertyValue GetCameraProperty_value( CameraProperty property )
836
      {
837
         CameraPropertyValue result;
838
 
839
         bool successful = false;
840
 
841
         int value = -1;
842
         bool isAuto = false;
843
 
844
         lock( CameraMethodsLock )
845
         {
846
            _cameraMethods.GetProperty_value( ( WebCamLib.CameraProperty ) property, ref value, ref isAuto, ref successful );
847
         }
848
 
849
         if( successful )
850
            result = new CameraPropertyValue( false, value, isAuto );
851
         else
852
            result = null;
853
 
854
         return result;
855
      }
856
 
857
      public CameraPropertyValue GetCameraProperty_percentage( CameraProperty property )
858
      {
859
         CameraPropertyValue result;
860
 
861
         bool successful = false;
862
 
863
         int value = -1;
864
         bool isAuto = false;
865
 
866
         lock( CameraMethodsLock )
867
         {
868
            _cameraMethods.GetProperty_percentage( ( WebCamLib.CameraProperty ) property, ref value, ref isAuto, ref successful );
869
         }
870
 
871
         if( successful )
872
            result = new CameraPropertyValue( true, value, isAuto );
873
         else
874
            result = null;
875
 
876
         return result;
877
      }
878
 
879
      public CameraPropertyRange GetCameraPropertyRange( CameraProperty property )
880
      {
881
         CameraPropertyRange result;
882
 
883
         bool successful = false;
884
 
885
         int minimum, maximum, step, defaults;
886
         bool isAuto;
887
 
888
         minimum = maximum = step = defaults = -1;
889
         isAuto = false;
890
 
891
         lock( CameraMethodsLock )
892
         {
893
            _cameraMethods.GetPropertyRange( ( WebCamLib.CameraProperty ) property, ref minimum, ref maximum, ref step, ref defaults, ref isAuto, ref successful );
894
         }
895
 
896
         if( successful )
897
            result = new CameraPropertyRange( minimum, maximum, step, defaults, isAuto );
898
         else
899
            result = null;
900
 
901
         return result;
902
      }
903
 
904
      public bool CameraPropertyHasRange( CameraProperty property )
905
      {
906
         bool result = false;
907
 
908
         _cameraMethods.PropertyHasRange( ( WebCamLib.CameraProperty ) property, ref result );
909
 
910
         return result;
911
      }
912
 
913
      public bool ValidateCameraProperty( CameraProperty property, int value )
914
      {
915
         bool result = false;
916
 
917
         _cameraMethods.ValidatePropertyValue( ( WebCamLib.CameraProperty ) property, value, ref result );
918
 
919
         return result;
920
      }
921
 
922
      public IDictionary<CameraProperty, CameraPropertyCapabilities> CameraPropertyCapabilities
923
      {
924
         get
925
         {
926
            IDictionary<CameraProperty, CameraPropertyCapabilities> result = new Dictionary<CameraProperty, CameraPropertyCapabilities>( _cameraMethods.PropertyCapabilities.Count );
927
 
928
            foreach( WebCamLib.CameraProperty property in _cameraMethods.PropertyCapabilities.Keys )
929
            {
930
               CameraProperty prop = ( CameraProperty ) property;
931
               CameraPropertyCapabilities capabilities = new CameraPropertyCapabilities( this, _cameraMethods.PropertyCapabilities[ property ] );
932
 
933
               result.Add( prop, capabilities );
934
            }
935
 
936
            return result;
937
         }
938
      }
939
      #endregion
940
 
941
      public IList<CaptureSize> CaptureSizes
942
      {
943
         get
944
         {
945
            IList<Tuple<int, int, int>> rawSizes = new List<Tuple<int, int, int>>();
946
 
947
            lock( CameraMethodsLock )
948
            {
949
               _cameraMethods.GetCaptureSizes( _index, rawSizes );
950
            }
951
 
952
            IList<CaptureSize> result = new List<CaptureSize>( rawSizes.Count );
953
            foreach( Tuple<int, int, int> size in rawSizes )
954
            {
955
               CaptureSize newSize = new CaptureSize( size.Item1, size.Item2, size.Item3 );
956
               result.Add( newSize );
957
            }
958
 
959
            return result;
960
         }
961
      }
962
 
963
      /// <summary>
964
      /// Event fired when an image from the camera is captured
965
      /// </summary>
966
      public event EventHandler<CameraEventArgs> OnImageCaptured;
967
 
968
      /// <summary>
969
      /// Returns the camera name as the ToString implementation
970
      /// </summary>
971
      /// <returns>The name of the camera</returns>
972
      public override string ToString()
973
      {
974
         return _name;
975
      }
976
 
977
      #region Internal Implementation
978
 
979
      private readonly object _bitmapLock = new object();
980
      private readonly int _index;
981
      private readonly string _name;
982
      private Bitmap _bitmap;
983
      private DateTime _dtLastCap = DateTime.MinValue;
984
      private int _fpslimit = -1;
985
      private int _height = 240;
986
      private double _timeBehind;
987
      private double _timeBetweenFrames;
988
      private int _width = 320;
989
      private int _bpp = 24;
990
 
991
      internal bool StartCapture()
992
      {
993
         bool result = false;
994
 
995
         lock( CameraMethodsLock )
996
         {
997
            _cameraMethods.StartCamera( _index, ref _width, ref _height, ref _bpp, ref result );
998
            _cameraMethods.OnImageCapture += CaptureCallbackProc;
999
         }
1000
 
1001
         return result;
1002
      }
1003
 
1004
      internal void StopCapture()
1005
      {
1006
         lock( CameraMethodsLock )
1007
         {
1008
            _cameraMethods.StopCamera();
1009
            _cameraMethods.OnImageCapture -= CaptureCallbackProc;
1010
         }
1011
      }
1012
 
1013
      /// <summary>
1014
      /// Here is where the images come in as they are collected, as fast as they can and on a background thread
1015
      /// </summary>
1016
      private void CaptureCallbackProc( int dataSize, byte[] data )
1017
      {
1018
         // Do the magic to create a bitmap
1019
         int stride = _width * 3;
1020
         GCHandle handle = GCHandle.Alloc( data, GCHandleType.Pinned );
1021
         var scan0 = handle.AddrOfPinnedObject();
1022
         scan0 += ( _height - 1 ) * stride;
1023
         var b = new Bitmap( _width, _height, -stride, PixelFormat.Format24bppRgb, scan0 );
1024
         b.RotateFlip( _rotateFlip );
1025
         // NOTE: It seems that bntr has made that resolution property work properly
1026
         var copyBitmap = ( Bitmap ) b.Clone();
1027
         // Copy the image using the Thumbnail function to also resize if needed
1028
         //var copyBitmap = (Bitmap)b.GetThumbnailImage(_width, _height, null, IntPtr.Zero);
1029
 
1030
         // Now you can free the handle
1031
         handle.Free();
1032
 
1033
         ImageCaptured( copyBitmap );
1034
      }
1035
 
1036
      private void ImageCaptured( Bitmap bitmap )
1037
      {
1038
         DateTime dtCap = DateTime.Now;
1039
 
1040
         // Always save the bitmap
1041
         lock( _bitmapLock )
1042
         {
1043
            _bitmap = bitmap;
1044
         }
1045
 
1046
         // FPS affects the callbacks only
1047
         if( _fpslimit != -1 )
1048
         {
1049
            if( _dtLastCap != DateTime.MinValue )
1050
            {
1051
               double milliseconds = ( ( dtCap.Ticks - _dtLastCap.Ticks ) / TimeSpan.TicksPerMillisecond ) * 1.15;
1052
               if( milliseconds + _timeBehind >= _timeBetweenFrames )
1053
               {
1054
                  _timeBehind = ( milliseconds - _timeBetweenFrames );
1055
                  if( _timeBehind < 0.0 )
1056
                  {
1057
                     _timeBehind = 0.0;
1058
                  }
1059
               }
1060
               else
1061
               {
1062
                  _timeBehind = 0.0;
1063
                  return; // ignore the frame
1064
               }
1065
            }
1066
         }
1067
 
1068
            var handler = OnImageCaptured;
1069
 
1070
         if ( handler != null )
1071
         {
1072
            var fps = ( int ) ( 1 / dtCap.Subtract( _dtLastCap ).TotalSeconds );
1073
            handler.Invoke( this, new CameraEventArgs( bitmap, fps ) );
1074
         }
1075
 
1076
         _dtLastCap = dtCap;
1077
      }
1078
 
1079
      #endregion
1080
   }
1081
 
1082
   /// <summary>
1083
   /// Camera specific EventArgs that provides the Image being captured
1084
   /// </summary>
1085
   public class CameraEventArgs : EventArgs
1086
   {
1087
      /// <summary>
1088
      /// Current Camera Image
1089
      /// </summary>
1090
      public Bitmap Image
1091
      {
1092
         get
1093
         {
1094
            return _image;
1095
         }
1096
      }
1097
 
1098
      public int CameraFps
1099
      {
1100
         get
1101
         {
1102
            return _cameraFps;
1103
         }
1104
      }
1105
 
1106
      #region Internal Implementation
1107
 
1108
      private readonly int _cameraFps;
1109
      private readonly Bitmap _image;
1110
 
1111
      internal CameraEventArgs( Bitmap i, int fps )
1112
      {
1113
         _image = i;
1114
         _cameraFps = fps;
1115
      }
1116
 
1117
      #endregion
1118
   }
1119
}