Skip to content
This repository has been archived by the owner on Jun 16, 2023. It is now read-only.

Commit

Permalink
Improvements to PRs and working towards v2. WIP.
Browse files Browse the repository at this point in the history
  • Loading branch information
lwansbrough committed May 1, 2015
1 parent e33127e commit 6dfcfa1
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 86 deletions.
107 changes: 71 additions & 36 deletions Camera.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ var NativeMethodsMixin = require('NativeMethodsMixin');
var flattenStyle = require('flattenStyle');
var merge = require('merge');

var constants = {
Aspect: NativeModules.CameraManager.Aspect,
Camera: NativeModules.CameraManager.Camera,
CaptureMode: NativeModules.CameraManager.CaptureMode,
CaptureTarget: NativeModules.CameraManager.CaptureTarget,
Orientation: NativeModules.CameraManager.Orientation
};

var Camera = React.createClass({
propTypes: {
aspect: PropTypes.string,
Expand All @@ -24,51 +32,75 @@ var Camera = React.createClass({
validAttributes: ReactIOSViewAttributes.UIView
},

Aspect: {
stretch: NativeModules.CameraManager.Aspect.stretch,
fit: NativeModules.CameraManager.Aspect.fit,
fill: NativeModules.CameraManager.Aspect.fill
},

Camera: {
front: NativeModules.CameraManager.Camera.front,
back: NativeModules.CameraManager.Camera.back
},

Orientation: {
landscapeLeft: NativeModules.CameraManager.Orientation.landscapeLeft,
landscapeRight: NativeModules.CameraManager.Orientation.landscapeRight,
portrait: NativeModules.CameraManager.Orientation.portrait,
portraitUpsideDown: NativeModules.CameraManager.Orientation.portraitUpsideDown
getDefaultProps() {
return {
aspect: constants.Aspect.fill,
type: constants.Camera.back,
orientation: constants.Orientation.portrait,
captureMode: constants.CaptureMode.still,
captureTarget: constants.CaptureTarget.memory
};
},

getInitialState: function() {
getInitialState() {
return {
isAuthorized: false,
aspect: this.props.aspect || 'Fill',
type: this.props.type || 'Back',
orientation: this.props.orientation || 'Portrait'
isAuthorized: false
};
},

componentWillMount: function() {
componentWillMount() {
NativeModules.CameraManager.checkDeviceAuthorizationStatus((function(err, isAuthorized) {
this.state.isAuthorized = isAuthorized;
this.setState(this.state);
}).bind(this));
this.cameraBarCodeReadListener = DeviceEventEmitter.addListener('CameraBarCodeRead', this._onBarCodeRead);
},

componentWillUnmount: function() {
componentWillUnmount() {
this.cameraBarCodeReadListener.remove();
},

render: function() {
render() {
var style = flattenStyle([styles.base, this.props.style]);

var aspect = NativeModules.CameraManager.aspects[this.state.aspect];
var type = NativeModules.CameraManager.cameras[this.state.type];
var orientation = NativeModules.CameraManager.orientations[this.state.orientation];
var aspect = this.props.aspect,
type = this.props.type,
orientation = this.props.orientation;

switch (aspect.toLowerCase()) {

This comment has been minimized.

Copy link
@amccloud

amccloud May 1, 2015

Contributor

Should we raise deprecation warning? Could also use a object to make this cleaner:

var legacyAspects = {
  'Fill': 'fill',
  'Fit': 'fit',
  'Stretch': 'stretch'
}

var foundLegacyAspect = legacyAspects[aspect];

if (foundLegacyAspect && __DEV__) {
  console.log(`aspect="${aspect}" is deprecated, use aspect={Camera.Aspect.${foundLegacyAspect}} instead.`);
  aspect = Camera.Aspect[foundLegacyAspect];
}

Same for orientation.

case 'fill':
aspect = constants.Aspect.fill;
break;
case 'fit':
aspect = constants.Aspect.fit;
break;
case 'stretch':
aspect = constants.Aspect.stretch;
break;
default:
break;
}

if (typeof orientation !== 'number') {
switch (orientation.toLowerCase()) {
case 'landscapeleft':
orientation = constants.Orientation.landscapeLeft;
break;
case 'landscaperight':
orientation = constants.Orientation.landscapeRight;
break;
case 'portrait':
orientation = constants.Orientation.portrait;
break;
case 'portraitUpsideDown':
orientation = constants.Orientation.portraitUpsideDown;
break;
}
}

if (typeof type !== 'number') {
type = constants.Camera[type];
}

var nativeProps = merge(this.props, {
style,
Expand All @@ -84,17 +116,19 @@ var Camera = React.createClass({
this.props.onBarCodeRead && this.props.onBarCodeRead(e);
},

switch: function() {
this.state.type = this.state.type == 'Back' ? 'Front' : 'Back';
this.setState(this.state);
},
capture(options, cb) {

takePicture: function(cb) {
NativeModules.CameraManager.takePicture(cb);
},
if (arguments.length == 1) {
cb = options;
options = {};
}

options = Object.assign({}, {
mode: this.props.captureMode,
target: this.props.captureTarget
}, options);

capturePictureToDisk: function(cb) {
NativeModules.CameraManager.capturePictureToDisk(cb)
NativeModules.CameraManager.capture(options, cb);
}

});
Expand All @@ -112,4 +146,5 @@ var styles = StyleSheet.create({
base: { },
});

Camera.constants = constants;
module.exports = Camera;
61 changes: 39 additions & 22 deletions RCTCameraManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
#import "UIImage+Resize.h"
#import <AVFoundation/AVFoundation.h>

typedef NS_ENUM(NSInteger, RCTCameraCaptureMode) {
RCTCameraCaptureModeStill = 0,
RCTCameraCaptureModeVideo = 1
};

typedef NS_ENUM(NSInteger, RCTCameraCaptureTarget) {
RCTCameraCaptureTargetMemory = 0,
RCTCameraCaptureTargetDisk = 1
};

@implementation RCTCameraManager

RCT_EXPORT_MODULE();
Expand All @@ -33,6 +43,14 @@ - (NSDictionary *)constantsToExport
@"front": @(AVCaptureDevicePositionFront),
@"back": @(AVCaptureDevicePositionBack)
},
@"CaptureMode": @{
@"still": @(RCTCameraCaptureModeStill),
@"video": @(RCTCameraCaptureModeVideo)
},
@"CaptureTarget": @{
@"memory": @(RCTCameraCaptureTargetMemory),
@"disk": @(RCTCameraCaptureTargetDisk)
},
@"Orientation": @{
@"landscapeLeft": @(AVCaptureVideoOrientationLandscapeLeft),
@"landscapeRight": @(AVCaptureVideoOrientationLandscapeRight),
Expand Down Expand Up @@ -166,25 +184,19 @@ - (id)init {
self.previewLayer.connection.videoOrientation = orientation;
}

RCT_EXPORT_METHOD(takePicture:(RCTResponseSenderBlock)callback) {
[[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:self.previewLayer.connection.videoOrientation];
[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {

if (imageDataSampleBuffer)
{
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [UIImage imageWithData:imageData];
UIImage *rotatedImage = [image resizedImage:CGSizeMake(image.size.width, image.size.height) interpolationQuality:kCGInterpolationDefault];
NSString *imageBase64 = [UIImageJPEGRepresentation(rotatedImage, 1.0) base64EncodedStringWithOptions:0];
callback(@[[NSNull null], imageBase64]);
}
else {
callback(@[RCTMakeError(error.description, nil, nil)]);
}
}];
RCT_EXPORT_METHOD(capture:(NSDictionary *)options callback:(RCTResponseSenderBlock)callback) {
NSInteger captureMode = [[options valueForKey:@"mode"] intValue];
NSInteger captureTarget = [[options valueForKey:@"target"] intValue];

if (captureMode == RCTCameraCaptureModeStill) {
[self captureStill:captureTarget callback:callback];
}
else if (captureMode == RCTCameraCaptureModeVideo) {
// waiting for incoming PRs
}
}

RCT_EXPORT_METHOD(capturePictureToDisk:(RCTResponseSenderBlock)callback) {
-(void)captureStill:(NSInteger)target callback:(RCTResponseSenderBlock)callback {
[[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:self.previewLayer.connection.videoOrientation];
[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {

Expand All @@ -193,10 +205,16 @@ - (id)init {
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [UIImage imageWithData:imageData];
UIImage *rotatedImage = [image resizedImage:CGSizeMake(image.size.width, image.size.height) interpolationQuality:kCGInterpolationDefault];
NSString *uuid = [[NSUUID UUID] UUIDString];
NSString *fullPath = [self saveImage:rotatedImage withName:uuid];

callback(@[[NSNull null], fullPath]);

NSString *responseString;

if (target == RCTCameraCaptureTargetMemory) {
responseString = [UIImageJPEGRepresentation(rotatedImage, 1.0) base64EncodedStringWithOptions:0];
}
else if (target == RCTCameraCaptureTargetDisk) {
responseString = [self saveImage:rotatedImage withName:[[NSUUID UUID] UUIDString]];
}
callback(@[[NSNull null], responseString]);
}
else {
callback(@[RCTMakeError(error.description, nil, nil)]);
Expand All @@ -211,7 +229,6 @@ - (NSString *)saveImage:(UIImage *)image withName:(NSString *)name {
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
NSLog(@"writing path %@", fullPath);

[fileManager createFileAtPath:fullPath contents:data attributes:nil];
return fullPath;
Expand Down

0 comments on commit 6dfcfa1

Please sign in to comment.