rays 0.1.15 → 0.1.20

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,74 @@
1
+ // -*- mode: c++ -*-
2
+ #pragma once
3
+ #ifndef __RAYS_CAMERA_H__
4
+ #define __RAYS_CAMERA_H__
5
+
6
+
7
+ #include <vector>
8
+ #include <xot/pimpl.h>
9
+ #include <rays/defs.h>
10
+ #include <rays/image.h>
11
+
12
+
13
+ namespace Rays
14
+ {
15
+
16
+
17
+ class Camera
18
+ {
19
+
20
+ typedef Camera This;
21
+
22
+ public:
23
+
24
+ Camera (
25
+ const char* device_name = NULL,
26
+ int min_width = -1,
27
+ int min_height = -1,
28
+ bool resize = true,
29
+ bool crop = true);
30
+
31
+ ~Camera ();
32
+
33
+ bool start ();
34
+
35
+ void stop ();
36
+
37
+ bool is_active () const;
38
+
39
+ void set_min_width (int width);
40
+
41
+ int min_width () const;
42
+
43
+ void set_min_height (int height);
44
+
45
+ int min_height () const;
46
+
47
+ void set_resize (bool resize = true);
48
+
49
+ bool is_resize () const;
50
+
51
+ void set_crop (bool crop = true);
52
+
53
+ bool is_crop () const;
54
+
55
+ const Image* image () const;
56
+
57
+ operator bool () const;
58
+
59
+ bool operator ! () const;
60
+
61
+ struct Data;
62
+
63
+ Xot::PSharedImpl<Data> self;
64
+
65
+ };// Camera
66
+
67
+
68
+ std::vector<String> get_camera_device_names ();
69
+
70
+
71
+ }// Rays
72
+
73
+
74
+ #endif//EOH
@@ -31,9 +31,13 @@ namespace Rays
31
31
 
32
32
  using namespace Xot::ErrorFunctions;
33
33
 
34
- void rays_error (const char* file, int line, const char* format = NULL, ...);
34
+ [[noreturn]]
35
+ void rays_error (
36
+ const char* file, int line, const char* format = NULL, ...);
35
37
 
36
- void opengl_error (const char* file, int line, const char* format = NULL, ...);
38
+ [[noreturn]]
39
+ void opengl_error (
40
+ const char* file, int line, const char* format = NULL, ...);
37
41
 
38
42
  }// ErrorFunctions
39
43
 
@@ -0,0 +1,41 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __RAYS_RUBY_CAMERA_H__
4
+ #define __RAYS_RUBY_CAMERA_H__
5
+
6
+
7
+ #include <rucy/rucy.h>
8
+ #include <rucy/class.h>
9
+ #include <rucy/extension.h>
10
+ #include <rays/camera.h>
11
+
12
+
13
+ namespace Rays
14
+ {
15
+
16
+
17
+ Rucy::Class camera_class ();
18
+ // class Rays::Camera
19
+
20
+
21
+ }// Rays
22
+
23
+
24
+ RUCY_DECLARE_VALUE_FROM_TO(Rays::Camera)
25
+
26
+
27
+ namespace Rucy
28
+ {
29
+
30
+
31
+ template <> inline Class
32
+ get_ruby_class<Rays::Camera> ()
33
+ {
34
+ return Rays::camera_class();
35
+ }
36
+
37
+
38
+ }// Rucy
39
+
40
+
41
+ #endif//EOH
@@ -21,9 +21,9 @@ namespace Rays
21
21
  }// Rays
22
22
 
23
23
 
24
- RUCY_DECLARE_VALUE_OR_ARRAY_TO(Rays::CapType)
24
+ RUCY_DECLARE_CONVERT_TO(Rays::CapType)
25
25
 
26
- RUCY_DECLARE_VALUE_OR_ARRAY_TO(Rays::JoinType)
26
+ RUCY_DECLARE_CONVERT_TO(Rays::JoinType)
27
27
 
28
28
 
29
29
  #endif//EOH
@@ -10,6 +10,7 @@ require 'rays/color'
10
10
  require 'rays/color_space'
11
11
  require 'rays/matrix'
12
12
 
13
+ require 'rays/painter'
13
14
  require 'rays/polyline'
14
15
  require 'rays/polygon'
15
16
  require 'rays/polygon_line'
@@ -17,5 +18,4 @@ require 'rays/bitmap'
17
18
  require 'rays/image'
18
19
  require 'rays/font'
19
20
  require 'rays/shader'
20
-
21
- require 'rays/painter'
21
+ require 'rays/camera'
@@ -0,0 +1,24 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ require 'xot/block_util'
5
+ require 'rays/ext'
6
+
7
+
8
+ module Rays
9
+
10
+
11
+ class Camera
12
+
13
+ def initialize (
14
+ min_width = -1, min_height = -1,
15
+ device_name: nil, resize: true, crop: true, &block)
16
+
17
+ setup device_name, min_width, min_height, resize, crop
18
+ Xot::BlockUtil.instance_eval_or_block_call self, &block if block
19
+ end
20
+
21
+ end# Camera
22
+
23
+
24
+ end# Rays
@@ -28,8 +28,8 @@ Gem::Specification.new do |s|
28
28
  s.platform = Gem::Platform::RUBY
29
29
  s.required_ruby_version = '~> 2'
30
30
 
31
- s.add_runtime_dependency 'xot', '~> 0.1'
32
- s.add_runtime_dependency 'rucy', '~> 0.1'
31
+ s.add_runtime_dependency 'xot', '~> 0.1.20'
32
+ s.add_runtime_dependency 'rucy', '~> 0.1.20'
33
33
 
34
34
  s.files = `git ls-files`.split $/
35
35
  s.executables = s.files.grep(%r{^bin/}) {|f| File.basename f}
@@ -1,4 +1,4 @@
1
- #include "rays/image.h"
1
+ #include "image.h"
2
2
 
3
3
 
4
4
  #include <math.h>
@@ -0,0 +1,23 @@
1
+ // -*- mode: c++ -*-
2
+ #pragma once
3
+ #ifndef __RAYS_SRC_IOS_BITMAP_H__
4
+ #define __RAYS_SRC_IOS_BITMAP_H__
5
+
6
+
7
+ #import <CoreGraphics/CGImage.h>
8
+ #include "../bitmap.h"
9
+
10
+
11
+ namespace Rays
12
+ {
13
+
14
+
15
+ void Bitmap_draw_image (
16
+ Bitmap* bitmap, CGImageRef image,
17
+ coord x = 0, coord y = 0, coord width = -1, coord height = -1);
18
+
19
+
20
+ }// Rays
21
+
22
+
23
+ #endif//EOH
@@ -1,5 +1,5 @@
1
1
  // -*- objc -*-
2
- #import "../bitmap.h"
2
+ #import "bitmap.h"
3
3
 
4
4
 
5
5
  #import <ImageIO/CGImageDestination.h>
@@ -175,6 +175,27 @@ namespace Rays
175
175
  return bmp;
176
176
  }
177
177
 
178
+ void
179
+ Bitmap_draw_image (
180
+ Bitmap* bitmap, CGImageRef image,
181
+ coord x, coord y, coord width, coord height)
182
+ {
183
+ if (width == 0 || height == 0) return;
184
+
185
+ if (!bitmap || !image)
186
+ argument_error(__FILE__, __LINE__);
187
+
188
+ CGContextRef context = bitmap->self->get_context();
189
+ if (!context)
190
+ rays_error(__FILE__, __LINE__, "getting CGContext failed.");
191
+
192
+ if (width < 0) width = (coord) CGImageGetWidth(image);
193
+ if (height < 0) height = (coord) CGImageGetHeight(image);
194
+ CGContextDrawImage(context, CGRectMake(x, y, width, height), image);
195
+
196
+ Bitmap_set_modified(bitmap);
197
+ }
198
+
178
199
  void
179
200
  Bitmap_draw_string (
180
201
  Bitmap* bitmap, const RawFont& font, const char* str, coord x, coord y)
@@ -185,6 +206,7 @@ namespace Rays
185
206
  if (*str == '\0') return;
186
207
 
187
208
  font.draw_string(bitmap->self->get_context(), bitmap->height(), str, x, y);
209
+
188
210
  Bitmap_set_modified(bitmap);
189
211
  }
190
212
 
@@ -247,11 +269,7 @@ namespace Rays
247
269
  if (!bmp)
248
270
  rays_error(__FILE__, __LINE__, "invalid bitmap.");
249
271
 
250
- CGContextRef context = bmp.self->get_context();
251
- if (!context)
252
- rays_error(__FILE__, __LINE__, "creating CGContext failed.");
253
-
254
- CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
272
+ Bitmap_draw_image(&bmp, image);
255
273
  return bmp;
256
274
  }
257
275
 
@@ -329,7 +347,10 @@ namespace Rays
329
347
  Bitmap::operator bool () const
330
348
  {
331
349
  return
332
- self->width > 0 && self->height > 0 && self->color_space && self->pixels;
350
+ self->width > 0 &&
351
+ self->height > 0 &&
352
+ self->color_space &&
353
+ self->pixels;
333
354
  }
334
355
 
335
356
  bool
@@ -0,0 +1,517 @@
1
+ // -*- mode: objc -*-
2
+ #import "rays/camera.h"
3
+
4
+
5
+ #import <AVFoundation/AVFoundation.h>
6
+ #include "rays/exception.h"
7
+ #include "bitmap.h"
8
+
9
+
10
+ static int video_input_queue_index = 0;
11
+
12
+
13
+ @interface VideoInput : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>
14
+ @end
15
+
16
+
17
+ @implementation VideoInput
18
+
19
+ {
20
+ AVCaptureSession* session;
21
+ dispatch_queue_t queue;
22
+ CGImageRef image;
23
+ AVCaptureVideoOrientation orientation;
24
+ }
25
+
26
+ - (id) init
27
+ {
28
+ self = [super init];
29
+ if (self)
30
+ {
31
+ session = nil;
32
+ queue = nil;
33
+ image = nil;
34
+ orientation = AVCaptureVideoOrientationPortrait;
35
+ }
36
+ return self;
37
+ }
38
+
39
+ - (void) dealloc
40
+ {
41
+ [self stop];
42
+ [self clearImage];
43
+
44
+ if (queue)
45
+ {
46
+ dispatch_release(queue);
47
+ queue = nil;
48
+ }
49
+
50
+ [super dealloc];
51
+ }
52
+
53
+ - (dispatch_queue_t) getQueue
54
+ {
55
+ if (!queue)
56
+ {
57
+ auto name = Xot::stringf(
58
+ "org.xord.RaysVideoInputQueue_%d",
59
+ video_input_queue_index++);
60
+ queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);
61
+ }
62
+ return queue;
63
+ }
64
+
65
+ - (BOOL) start: (AVCaptureDevice*) device
66
+ preset: (AVCaptureSessionPreset) preset
67
+ {
68
+ if (!device) return NO;
69
+
70
+ [self stop];
71
+ [self updateOrientation];
72
+
73
+ AVCaptureSession* sess = [[[AVCaptureSession alloc] init] autorelease];
74
+ if (preset != nil)
75
+ sess.sessionPreset = preset;
76
+
77
+ //device.activeVideoMinFrameDuration = CMTimeMake(1, 30);
78
+
79
+ NSError* error = nil;
80
+ AVCaptureDeviceInput* input = [[[AVCaptureDeviceInput alloc]
81
+ initWithDevice: device error: &error]
82
+ autorelease];
83
+ if (!input || error || ![sess canAddInput: input])
84
+ return NO;
85
+
86
+ AVCaptureVideoDataOutput* output =
87
+ [[[AVCaptureVideoDataOutput alloc] init] autorelease];
88
+ output.videoSettings = @{
89
+ (NSString*) kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)
90
+ };
91
+ output.alwaysDiscardsLateVideoFrames = YES;
92
+ [output setSampleBufferDelegate: self queue: [self getQueue]];
93
+ if (![sess canAddOutput: output])
94
+ return NO;
95
+
96
+ [sess addInput: input];
97
+ [sess addOutput: output];
98
+
99
+ AVCaptureConnection* connection =
100
+ [output connectionWithMediaType: AVMediaTypeVideo];
101
+ if (connection)
102
+ {
103
+ if (connection.isVideoOrientationSupported)
104
+ [connection setVideoOrientation: orientation];
105
+
106
+ if (connection.isVideoMirroringSupported)
107
+ {
108
+ [connection setVideoMirrored:
109
+ device.position == AVCaptureDevicePositionFront];
110
+ }
111
+ }
112
+
113
+ [sess startRunning];
114
+
115
+ session = [sess retain];
116
+ return YES;
117
+ }
118
+
119
+ - (void) updateOrientation
120
+ {
121
+ assert(NSThread.isMainThread);
122
+
123
+ switch (UIApplication.sharedApplication.statusBarOrientation)
124
+ {
125
+ case UIInterfaceOrientationPortraitUpsideDown:
126
+ orientation = AVCaptureVideoOrientationPortraitUpsideDown;
127
+ break;
128
+
129
+ case UIInterfaceOrientationLandscapeLeft:
130
+ orientation = AVCaptureVideoOrientationLandscapeLeft;
131
+ break;
132
+
133
+ case UIInterfaceOrientationLandscapeRight:
134
+ orientation = AVCaptureVideoOrientationLandscapeRight;
135
+ break;
136
+
137
+ default:
138
+ orientation = AVCaptureVideoOrientationPortrait;
139
+ break;
140
+ }
141
+ }
142
+
143
+ - (void) captureOutput: (AVCaptureOutput*) output
144
+ didOutputSampleBuffer: (CMSampleBufferRef) sampleBuffer
145
+ fromConnection: (AVCaptureConnection*) connection
146
+ {
147
+ [connection setVideoOrientation: orientation];
148
+
149
+ CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
150
+ if (!pixelBuffer) return;
151
+
152
+ CIImage* ciImage = [CIImage imageWithCVPixelBuffer: pixelBuffer];
153
+ if (!ciImage) return;
154
+
155
+ CIContext* context = [CIContext contextWithOptions: nil];
156
+ size_t width = CVPixelBufferGetWidth(pixelBuffer);
157
+ size_t height = CVPixelBufferGetHeight(pixelBuffer);
158
+ CGRect rect = CGRectMake(0, 0, width, height);
159
+ CGImageRef cgImage = [context createCGImage: ciImage fromRect: rect];
160
+
161
+ dispatch_async(dispatch_get_main_queue(), ^{
162
+ [self clearImage];
163
+ image = cgImage;
164
+
165
+ [self updateOrientation];
166
+ });
167
+ }
168
+
169
+ - (void) stop
170
+ {
171
+ if (!session) return;
172
+
173
+ [session stopRunning];
174
+ [session release];
175
+ session = nil;
176
+ }
177
+
178
+ - (BOOL) isActive
179
+ {
180
+ return session != nil;
181
+ }
182
+
183
+ - (void) clearImage
184
+ {
185
+ if (!image) return;
186
+
187
+ CGImageRelease(image);
188
+ image = nil;
189
+ }
190
+
191
+ - (CGImageRef) getImage
192
+ {
193
+ return image;
194
+ }
195
+
196
+ @end// VideoInput
197
+
198
+
199
+ namespace Rays
200
+ {
201
+
202
+
203
+ struct Camera::Data
204
+ {
205
+
206
+ String device_name;
207
+
208
+ int min_width = -1, min_height = -1;
209
+
210
+ bool resize = false, crop = false;
211
+
212
+ mutable Image image;
213
+
214
+ VideoInput* video_input = nil;
215
+
216
+ AVCaptureSessionPreset get_preset (AVCaptureDevice* device)
217
+ {
218
+ int w = min_width, h = min_height;
219
+ if (w > 0 && h > 0)
220
+ {
221
+ #define SUPPORT(x) \
222
+ [device supportsAVCaptureSessionPreset: AVCaptureSessionPreset##x]
223
+
224
+ //if (w <= 320 && h <= 240 && SUPPORT(320x240))
225
+ // return AVCaptureSessionPreset320x240;
226
+
227
+ if (w <= 352 && h <= 288 && SUPPORT(352x288))
228
+ return AVCaptureSessionPreset352x288;
229
+
230
+ if (w <= 640 && h <= 480 && SUPPORT(640x480))
231
+ return AVCaptureSessionPreset640x480;
232
+
233
+ //if (w <= 960 && h <= 540 && SUPPORT(960x540))
234
+ // return AVCaptureSessionPreset960x540;
235
+
236
+ if (w <= 1280 && h <= 720 && SUPPORT(1280x720))
237
+ return AVCaptureSessionPreset1280x720;
238
+
239
+ if (/*w <= 1920 && h <= 1080 &&*/ SUPPORT(1920x1080))
240
+ return AVCaptureSessionPreset1920x1080;
241
+
242
+ //if (SUPPORT(3840x2160))
243
+ // return AVCaptureSessionPreset3840x2160;
244
+
245
+ #undef SUPPORT
246
+ }
247
+
248
+ return nil;
249
+ }
250
+
251
+ void update_image_from_video_input () const
252
+ {
253
+ if (!video_input) return;
254
+
255
+ CGImageRef cgImage = [video_input getImage];
256
+ if (!cgImage) return;
257
+
258
+ coord draw_x, draw_y, draw_width, draw_height;
259
+ int bitmap_width, bitmap_height;
260
+ get_draw_bounds(
261
+ &draw_x, &draw_y, &draw_width, &draw_height,
262
+ &bitmap_width, &bitmap_height,
263
+ cgImage);
264
+
265
+ if (
266
+ !image ||
267
+ image.bitmap().width() != bitmap_width ||
268
+ image.bitmap().height() != bitmap_height)
269
+ {
270
+ image = Image(Bitmap(bitmap_width, bitmap_height));
271
+ }
272
+
273
+ Bitmap_draw_image(
274
+ &image.bitmap(), cgImage,
275
+ draw_x, draw_y, draw_width, draw_height);
276
+
277
+ [video_input clearImage];
278
+ }
279
+
280
+ void get_draw_bounds (
281
+ coord* draw_x, coord* draw_y, coord* draw_width, coord* draw_height,
282
+ int* bitmap_width, int* bitmap_height,
283
+ CGImageRef image) const
284
+ {
285
+ int image_width = (int) CGImageGetWidth(image);
286
+ int image_height = (int) CGImageGetHeight(image);
287
+ float image_ratio = (float) image_width / (float) image_height;
288
+
289
+ if (resize && min_width > 0 && min_height > 0)
290
+ {
291
+ float min_size_ratio = (float) min_width / (float) min_height;
292
+ if (image_ratio > min_size_ratio)
293
+ {
294
+ *draw_width = min_height * image_ratio;
295
+ *draw_height = min_height;
296
+ }
297
+ else
298
+ {
299
+ *draw_width = min_width;
300
+ *draw_height = min_width / image_ratio;
301
+ }
302
+ }
303
+ else if (resize && min_width > 0)
304
+ {
305
+ *draw_width = min_width;
306
+ *draw_height = min_width / image_ratio;
307
+ }
308
+ else if (resize && min_height > 0)
309
+ {
310
+ *draw_width = min_height * image_ratio;
311
+ *draw_height = min_height;
312
+ }
313
+ else
314
+ {
315
+ *draw_width = image_width;
316
+ *draw_height = image_height;
317
+ }
318
+
319
+ *draw_x = 0;
320
+ *draw_y = 0;
321
+ *bitmap_width = *draw_width;
322
+ *bitmap_height = *draw_height;
323
+
324
+ if (crop && min_width > 0)
325
+ {
326
+ *draw_x = min_width / 2 - *draw_width / 2;
327
+ *bitmap_width = min_width;
328
+ }
329
+ if (crop && min_height > 0)
330
+ {
331
+ *draw_y = min_height / 2 - *draw_height / 2;
332
+ *bitmap_height = min_height;
333
+ }
334
+ }
335
+
336
+ };// Camera::Data
337
+
338
+
339
+ static NSArray<AVCaptureDevice*>*
340
+ get_video_devices ()
341
+ {
342
+ #if 0
343
+ AVCaptureDeviceDiscoverySession* discoverySession =
344
+ [AVCaptureDeviceDiscoverySession
345
+ discoverySessionWithDeviceTypes: @[
346
+ AVCaptureDeviceTypeBuiltInTripleCamera,
347
+ AVCaptureDeviceTypeBuiltInDualWideCamera,
348
+ AVCaptureDeviceTypeBuiltInDualCamera,
349
+ AVCaptureDeviceTypeBuiltInUltraWideCamera,
350
+ AVCaptureDeviceTypeBuiltInTelephotoCamera,
351
+ AVCaptureDeviceTypeBuiltInWideAngleCamera
352
+ ]
353
+ mediaType: AVMediaTypeVideo
354
+ position: AVCaptureDevicePositionUnspecified];
355
+ NSArray<AVCaptureDevice*>* devices = discoverySession.devices;
356
+ for (AVCaptureDevice* d in devices)
357
+ {
358
+ printf("%s\n", d.localizedName.UTF8String);
359
+ }
360
+ #endif
361
+ NSMutableArray<AVCaptureDevice*>* devices = [NSMutableArray array];
362
+ for (AVCaptureDevice* d in AVCaptureDevice.devices)
363
+ {
364
+ if ([d hasMediaType: AVMediaTypeVideo])
365
+ [devices addObject: d];
366
+ }
367
+ return devices;
368
+ }
369
+
370
+ static AVCaptureDevice*
371
+ get_default_video_device ()
372
+ {
373
+ AVCaptureDevice* device =
374
+ [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
375
+ if (!device)
376
+ rays_error(__FILE__, __LINE__, "Default camera device is not found.");
377
+
378
+ return device;
379
+ }
380
+
381
+ static AVCaptureDevice*
382
+ get_video_device (const char* name)
383
+ {
384
+ if (!name || *name == 0)
385
+ return get_default_video_device();
386
+
387
+ for (AVCaptureDevice* d in get_video_devices())
388
+ {
389
+ if (strcmp(name, d.localizedName.UTF8String) == 0)
390
+ return d;
391
+ }
392
+
393
+ rays_error(__FILE__, __LINE__, "Camera device '%s' is not found.", name);
394
+ return nil;
395
+ }
396
+
397
+ std::vector<String>
398
+ get_camera_device_names ()
399
+ {
400
+ std::vector<String> names;
401
+ for (AVCaptureDevice* d in get_video_devices())
402
+ names.emplace_back(d.localizedName.UTF8String);
403
+ return names;
404
+ }
405
+
406
+
407
+ Camera::Camera (
408
+ const char* device_name,
409
+ int min_width, int min_height, bool resize, bool crop)
410
+ {
411
+ if (device_name)
412
+ self->device_name = device_name;
413
+
414
+ self->min_width = min_width;
415
+ self->min_height = min_height;
416
+ self->resize = resize;
417
+ self->crop = crop;
418
+ }
419
+
420
+ Camera::~Camera ()
421
+ {
422
+ stop();
423
+ }
424
+
425
+ bool
426
+ Camera::start ()
427
+ {
428
+ if (!self->video_input) self->video_input = [[VideoInput alloc] init];
429
+
430
+ AVCaptureDevice* device = get_video_device(self->device_name.c_str());
431
+ return [self->video_input start: device preset: self->get_preset(device)];
432
+ }
433
+
434
+ void
435
+ Camera::stop ()
436
+ {
437
+ if (!self->video_input) return;
438
+
439
+ [self->video_input stop];
440
+ [self->video_input release];
441
+ self->video_input = nil;
442
+ }
443
+
444
+ bool
445
+ Camera::is_active () const
446
+ {
447
+ return self->video_input && [self->video_input isActive];
448
+ }
449
+
450
+ void
451
+ Camera::set_min_width (int width)
452
+ {
453
+ self->min_width = width;
454
+ }
455
+
456
+ int
457
+ Camera::min_width () const
458
+ {
459
+ return self->min_width;
460
+ }
461
+
462
+ void
463
+ Camera::set_min_height (int height)
464
+ {
465
+ self->min_height = height;
466
+ }
467
+
468
+ int
469
+ Camera::min_height () const
470
+ {
471
+ return self->min_height;
472
+ }
473
+
474
+ void
475
+ Camera::set_resize (bool resize)
476
+ {
477
+ self->resize = resize;
478
+ }
479
+
480
+ bool
481
+ Camera::is_resize () const
482
+ {
483
+ return self->resize;
484
+ }
485
+
486
+ void
487
+ Camera::set_crop (bool crop)
488
+ {
489
+ self->crop = crop;
490
+ }
491
+
492
+ bool
493
+ Camera::is_crop () const
494
+ {
495
+ return self->crop;
496
+ }
497
+
498
+ const Image*
499
+ Camera::image () const
500
+ {
501
+ self->update_image_from_video_input();
502
+ return self->image ? &self->image : NULL;
503
+ }
504
+
505
+ Camera::operator bool () const
506
+ {
507
+ return true;
508
+ }
509
+
510
+ bool
511
+ Camera::operator ! () const
512
+ {
513
+ return !operator bool();
514
+ }
515
+
516
+
517
+ }// Rays