rays 0.1.15 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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