rays 0.1.14 → 0.1.19
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.
- checksums.yaml +4 -4
- data/.doc/ext/rays/camera.cpp +171 -0
- data/.doc/ext/rays/color.cpp +2 -3
- data/.doc/ext/rays/color_space.cpp +22 -14
- data/.doc/ext/rays/font.cpp +30 -0
- data/.doc/ext/rays/image.cpp +1 -1
- data/.doc/ext/rays/native.cpp +4 -4
- data/.doc/ext/rays/painter.cpp +83 -0
- data/.doc/ext/rays/point.cpp +14 -0
- data/.doc/ext/rays/polygon.cpp +33 -7
- data/.doc/ext/rays/polyline.cpp +12 -6
- data/.doc/ext/rays/rays.cpp +105 -1
- data/Rakefile +3 -0
- data/VERSION +1 -1
- data/ext/rays/bitmap.cpp +1 -1
- data/ext/rays/camera.cpp +186 -0
- data/ext/rays/color.cpp +2 -3
- data/ext/rays/color_space.cpp +22 -14
- data/ext/rays/extconf.rb +1 -1
- data/ext/rays/font.cpp +35 -2
- data/ext/rays/image.cpp +2 -2
- data/ext/rays/native.cpp +4 -4
- data/ext/rays/painter.cpp +94 -3
- data/ext/rays/point.cpp +16 -0
- data/ext/rays/polygon.cpp +34 -6
- data/ext/rays/polyline.cpp +11 -5
- data/ext/rays/rays.cpp +105 -1
- data/include/rays/camera.h +74 -0
- data/include/rays/color_space.h +4 -2
- data/include/rays/defs.h +33 -0
- data/include/rays/exception.h +6 -2
- data/include/rays/image.h +1 -1
- data/include/rays/painter.h +38 -0
- data/include/rays/polygon.h +35 -1
- data/include/rays/polyline.h +7 -1
- data/include/rays/ruby/camera.h +41 -0
- data/include/rays/ruby/rays.h +8 -0
- data/lib/rays.rb +2 -2
- data/lib/rays/camera.rb +24 -0
- data/lib/rays/image.rb +1 -1
- data/lib/rays/painter.rb +23 -1
- data/lib/rays/polygon.rb +8 -0
- data/rays.gemspec +2 -2
- data/src/color_space.cpp +2 -2
- data/src/image.cpp +1 -1
- data/src/ios/bitmap.h +23 -0
- data/src/ios/bitmap.mm +32 -11
- data/src/ios/camera.mm +517 -0
- data/src/ios/font.mm +2 -2
- data/src/ios/helper.h +2 -2
- data/src/osx/bitmap.h +23 -0
- data/src/osx/bitmap.mm +28 -10
- data/src/osx/camera.mm +452 -0
- data/src/osx/font.mm +2 -2
- data/src/painter.cpp +100 -10
- data/src/polygon.cpp +203 -37
- data/src/polyline.cpp +4 -2
- data/src/polyline.h +3 -1
- data/test/test_font.rb +5 -0
- data/test/test_painter.rb +65 -5
- data/test/test_painter_shape.rb +48 -3
- data/test/test_point.rb +8 -0
- data/test/test_polyline.rb +26 -0
- metadata +19 -9
data/include/rays/ruby/rays.h
CHANGED
@@ -4,7 +4,10 @@
|
|
4
4
|
#define __RAYS_RUBY_RAYS_H__
|
5
5
|
|
6
6
|
|
7
|
+
#include <rucy/rucy.h>
|
7
8
|
#include <rucy/module.h>
|
9
|
+
#include <rucy/extension.h>
|
10
|
+
#include <rays/rays.h>
|
8
11
|
|
9
12
|
|
10
13
|
namespace Rays
|
@@ -18,4 +21,9 @@ namespace Rays
|
|
18
21
|
}// Rays
|
19
22
|
|
20
23
|
|
24
|
+
RUCY_DECLARE_CONVERT_TO(Rays::CapType)
|
25
|
+
|
26
|
+
RUCY_DECLARE_CONVERT_TO(Rays::JoinType)
|
27
|
+
|
28
|
+
|
21
29
|
#endif//EOH
|
data/lib/rays.rb
CHANGED
@@ -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'
|
data/lib/rays/camera.rb
ADDED
@@ -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
|
data/lib/rays/image.rb
CHANGED
data/lib/rays/painter.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
|
4
|
+
require 'xot/const_symbol_accessor'
|
4
5
|
require 'xot/universal_accessor'
|
5
6
|
require 'xot/block_util'
|
6
7
|
require 'rays/ext'
|
@@ -73,6 +74,14 @@ module Rays
|
|
73
74
|
draw_ellipse args, center, radius, hole, from, to
|
74
75
|
end
|
75
76
|
|
77
|
+
def curve (*args, loop: false)
|
78
|
+
draw_curve args, loop
|
79
|
+
end
|
80
|
+
|
81
|
+
def bezier (*args, loop: false)
|
82
|
+
draw_bezier args, loop
|
83
|
+
end
|
84
|
+
|
76
85
|
def color= (fill, stroke = nil)
|
77
86
|
self.fill fill
|
78
87
|
self.stroke stroke
|
@@ -87,8 +96,21 @@ module Rays
|
|
87
96
|
set_shader shader
|
88
97
|
end
|
89
98
|
|
99
|
+
const_symbol_accessor :stroke_cap, {
|
100
|
+
butt: CAP_BUTT,
|
101
|
+
round: CAP_ROUND,
|
102
|
+
square: CAP_SQUARE
|
103
|
+
}
|
104
|
+
|
105
|
+
const_symbol_accessor :stroke_join, {
|
106
|
+
miter: JOIN_MITER,
|
107
|
+
round: JOIN_ROUND,
|
108
|
+
square: JOIN_SQUARE
|
109
|
+
}
|
110
|
+
|
90
111
|
universal_accessor :background, :fill, :stroke, :color,
|
91
|
-
:stroke_width, :
|
112
|
+
:stroke_width, :stroke_cap, :stroke_join, :miter_limit,
|
113
|
+
:nsegment, :shader, :clip, :font
|
92
114
|
|
93
115
|
private
|
94
116
|
|
data/lib/rays/polygon.rb
CHANGED
@@ -44,6 +44,14 @@ module Rays
|
|
44
44
|
create_ellipse args, center, radius, hole, from, to, nsegment
|
45
45
|
end
|
46
46
|
|
47
|
+
def self.curve (*args, loop: false)
|
48
|
+
create_curve args, loop
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.bezier (*args, loop: false)
|
52
|
+
create_bezier args, loop
|
53
|
+
end
|
54
|
+
|
47
55
|
end# Polygon
|
48
56
|
|
49
57
|
|
data/rays.gemspec
CHANGED
@@ -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.19'
|
32
|
+
s.add_runtime_dependency 'rucy', '~> 0.1.18'
|
33
33
|
|
34
34
|
s.files = `git ls-files`.split $/
|
35
35
|
s.executables = s.files.grep(%r{^bin/}) {|f| File.basename f}
|
data/src/color_space.cpp
CHANGED
@@ -55,7 +55,7 @@ namespace Rays
|
|
55
55
|
32, 32, 32, // RGB(A) float
|
56
56
|
32, 32, 32, // BGR(A) float
|
57
57
|
};
|
58
|
-
if (type_ < 0 ||
|
58
|
+
if (type_ < 0 || COLORSPACE_MAX <= type_) return BPPS[COLORSPACE_UNKNOWN];
|
59
59
|
return BPPS[type_];
|
60
60
|
}
|
61
61
|
|
@@ -78,7 +78,7 @@ namespace Rays
|
|
78
78
|
96, 128, 128, // RGB(A) float
|
79
79
|
96, 128, 128, // BGR(A) float
|
80
80
|
};
|
81
|
-
if (type_ < 0 ||
|
81
|
+
if (type_ < 0 || COLORSPACE_MAX <= type_) return BPPS[COLORSPACE_UNKNOWN];
|
82
82
|
return BPPS[type_];
|
83
83
|
}
|
84
84
|
|
data/src/image.cpp
CHANGED
data/src/ios/bitmap.h
ADDED
@@ -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
|
data/src/ios/bitmap.mm
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
// -*- objc -*-
|
2
|
-
#import "
|
2
|
+
#import "bitmap.h"
|
3
3
|
|
4
4
|
|
5
5
|
#import <ImageIO/CGImageDestination.h>
|
@@ -27,14 +27,14 @@ namespace Rays
|
|
27
27
|
if (cs.is_alpha_first())
|
28
28
|
{
|
29
29
|
info |= cs.is_premult()
|
30
|
-
?
|
31
|
-
:
|
30
|
+
? kCGImageAlphaPremultipliedFirst
|
31
|
+
: kCGImageAlphaFirst;
|
32
32
|
}
|
33
33
|
else if (cs.is_alpha_last())
|
34
34
|
{
|
35
35
|
info |= cs.is_premult()
|
36
|
-
?
|
37
|
-
:
|
36
|
+
? kCGImageAlphaPremultipliedLast
|
37
|
+
: kCGImageAlphaLast;
|
38
38
|
}
|
39
39
|
else if (cs.is_skip_first())
|
40
40
|
info |= kCGImageAlphaNoneSkipFirst;
|
@@ -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
|
-
|
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
|
350
|
+
self->width > 0 &&
|
351
|
+
self->height > 0 &&
|
352
|
+
self->color_space &&
|
353
|
+
self->pixels;
|
333
354
|
}
|
334
355
|
|
335
356
|
bool
|
data/src/ios/camera.mm
ADDED
@@ -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
|