8a9 > #if !TARGET_OS_MACCATALYST 9a11 > #endif 33,34c35,36 < self.session = [AVCaptureSession new]; < #if !(TARGET_IPHONE_SIMULATOR) --- > self.session = [AVCaptureSession new]; > #if !(TARGET_IPHONE_SIMULATOR) 37,42c39,44 < #endif < < if(!self.camera){ < self.camera = [[RCTCamera alloc] initWithManager:self bridge:self.bridge]; < } < return self.camera; --- > #endif > > if(!self.camera){ > self.camera = [[RCTCamera alloc] initWithManager:self bridge:self.bridge]; > } > return self.camera; 47c49 < return NO; --- > return NO; 52c54 < --- > 55,66c57,68 < @"upce": AVMetadataObjectTypeUPCECode, < @"code39": AVMetadataObjectTypeCode39Code, < @"code39mod43": AVMetadataObjectTypeCode39Mod43Code, < @"ean13": AVMetadataObjectTypeEAN13Code, < @"ean8": AVMetadataObjectTypeEAN8Code, < @"code93": AVMetadataObjectTypeCode93Code, < @"code128": AVMetadataObjectTypeCode128Code, < @"pdf417": AVMetadataObjectTypePDF417Code, < @"qr": AVMetadataObjectTypeQRCode, < @"aztec": AVMetadataObjectTypeAztecCode < }]; < --- > @"upce": AVMetadataObjectTypeUPCECode, > @"code39": AVMetadataObjectTypeCode39Code, > @"code39mod43": AVMetadataObjectTypeCode39Mod43Code, > @"ean13": AVMetadataObjectTypeEAN13Code, > @"ean8": AVMetadataObjectTypeEAN8Code, > @"code93": AVMetadataObjectTypeCode93Code, > @"code128": AVMetadataObjectTypeCode128Code, > @"pdf417": AVMetadataObjectTypePDF417Code, > @"qr": AVMetadataObjectTypeQRCode, > @"aztec": AVMetadataObjectTypeAztecCode > }]; > 70c72 < --- > 74c76 < --- > 78,136c80,138 < < < return @{ < @"Aspect": @{ < @"stretch": @(RCTCameraAspectStretch), < @"fit": @(RCTCameraAspectFit), < @"fill": @(RCTCameraAspectFill) < }, < @"BarCodeType": runtimeBarcodeTypes, < @"Type": @{ < @"front": @(RCTCameraTypeFront), < @"back": @(RCTCameraTypeBack) < }, < @"CaptureMode": @{ < @"still": @(RCTCameraCaptureModeStill), < @"video": @(RCTCameraCaptureModeVideo) < }, < @"CaptureQuality": @{ < @"low": @(RCTCameraCaptureSessionPresetLow), < @"AVCaptureSessionPresetLow": @(RCTCameraCaptureSessionPresetLow), < @"medium": @(RCTCameraCaptureSessionPresetMedium), < @"AVCaptureSessionPresetMedium": @(RCTCameraCaptureSessionPresetMedium), < @"high": @(RCTCameraCaptureSessionPresetHigh), < @"AVCaptureSessionPresetHigh": @(RCTCameraCaptureSessionPresetHigh), < @"photo": @(RCTCameraCaptureSessionPresetPhoto), < @"AVCaptureSessionPresetPhoto": @(RCTCameraCaptureSessionPresetPhoto), < @"480p": @(RCTCameraCaptureSessionPreset480p), < @"AVCaptureSessionPreset640x480": @(RCTCameraCaptureSessionPreset480p), < @"720p": @(RCTCameraCaptureSessionPreset720p), < @"AVCaptureSessionPreset1280x720": @(RCTCameraCaptureSessionPreset720p), < @"1080p": @(RCTCameraCaptureSessionPreset1080p), < @"AVCaptureSessionPreset1920x1080": @(RCTCameraCaptureSessionPreset1080p), < @"4k": @(RCTCameraCaptureSessionPreset4k), < @"AVCaptureSessionPreset3840x2160": @(RCTCameraCaptureSessionPreset4k) < }, < @"CaptureTarget": @{ < @"memory": @(RCTCameraCaptureTargetMemory), < @"disk": @(RCTCameraCaptureTargetDisk), < @"temp": @(RCTCameraCaptureTargetTemp), < @"cameraRoll": @(RCTCameraCaptureTargetCameraRoll) < }, < @"Orientation": @{ < @"auto": @(RCTCameraOrientationAuto), < @"landscapeLeft": @(RCTCameraOrientationLandscapeLeft), < @"landscapeRight": @(RCTCameraOrientationLandscapeRight), < @"portrait": @(RCTCameraOrientationPortrait), < @"portraitUpsideDown": @(RCTCameraOrientationPortraitUpsideDown) < }, < @"FlashMode": @{ < @"off": @(RCTCameraFlashModeOff), < @"on": @(RCTCameraFlashModeOn), < @"auto": @(RCTCameraFlashModeAuto) < }, < @"TorchMode": @{ < @"off": @(RCTCameraTorchModeOff), < @"on": @(RCTCameraTorchModeOn), < @"auto": @(RCTCameraTorchModeAuto) < } < }; --- > > > return @{ > @"Aspect": @{ > @"stretch": @(RCTCameraAspectStretch), > @"fit": @(RCTCameraAspectFit), > @"fill": @(RCTCameraAspectFill) > }, > @"BarCodeType": runtimeBarcodeTypes, > @"Type": @{ > @"front": @(RCTCameraTypeFront), > @"back": @(RCTCameraTypeBack) > }, > @"CaptureMode": @{ > @"still": @(RCTCameraCaptureModeStill), > @"video": @(RCTCameraCaptureModeVideo) > }, > @"CaptureQuality": @{ > @"low": @(RCTCameraCaptureSessionPresetLow), > @"AVCaptureSessionPresetLow": @(RCTCameraCaptureSessionPresetLow), > @"medium": @(RCTCameraCaptureSessionPresetMedium), > @"AVCaptureSessionPresetMedium": @(RCTCameraCaptureSessionPresetMedium), > @"high": @(RCTCameraCaptureSessionPresetHigh), > @"AVCaptureSessionPresetHigh": @(RCTCameraCaptureSessionPresetHigh), > @"photo": @(RCTCameraCaptureSessionPresetPhoto), > @"AVCaptureSessionPresetPhoto": @(RCTCameraCaptureSessionPresetPhoto), > @"480p": @(RCTCameraCaptureSessionPreset480p), > @"AVCaptureSessionPreset640x480": @(RCTCameraCaptureSessionPreset480p), > @"720p": @(RCTCameraCaptureSessionPreset720p), > @"AVCaptureSessionPreset1280x720": @(RCTCameraCaptureSessionPreset720p), > @"1080p": @(RCTCameraCaptureSessionPreset1080p), > @"AVCaptureSessionPreset1920x1080": @(RCTCameraCaptureSessionPreset1080p), > @"4k": @(RCTCameraCaptureSessionPreset4k), > @"AVCaptureSessionPreset3840x2160": @(RCTCameraCaptureSessionPreset4k) > }, > @"CaptureTarget": @{ > @"memory": @(RCTCameraCaptureTargetMemory), > @"disk": @(RCTCameraCaptureTargetDisk), > @"temp": @(RCTCameraCaptureTargetTemp), > @"cameraRoll": @(RCTCameraCaptureTargetCameraRoll) > }, > @"Orientation": @{ > @"auto": @(RCTCameraOrientationAuto), > @"landscapeLeft": @(RCTCameraOrientationLandscapeLeft), > @"landscapeRight": @(RCTCameraOrientationLandscapeRight), > @"portrait": @(RCTCameraOrientationPortrait), > @"portraitUpsideDown": @(RCTCameraOrientationPortraitUpsideDown) > }, > @"FlashMode": @{ > @"off": @(RCTCameraFlashModeOff), > @"on": @(RCTCameraFlashModeOn), > @"auto": @(RCTCameraFlashModeAuto) > }, > @"TorchMode": @{ > @"off": @(RCTCameraTorchModeOff), > @"on": @(RCTCameraTorchModeOn), > @"auto": @(RCTCameraTorchModeAuto) > } > }; 145,175c147,177 < NSInteger quality = [RCTConvert NSInteger:json]; < NSString *qualityString; < switch (quality) { < default: < case RCTCameraCaptureSessionPresetHigh: < qualityString = AVCaptureSessionPresetHigh; < break; < case RCTCameraCaptureSessionPresetMedium: < qualityString = AVCaptureSessionPresetMedium; < break; < case RCTCameraCaptureSessionPresetLow: < qualityString = AVCaptureSessionPresetLow; < break; < case RCTCameraCaptureSessionPresetPhoto: < qualityString = AVCaptureSessionPresetPhoto; < break; < case RCTCameraCaptureSessionPreset4k: < qualityString = AVCaptureSessionPreset3840x2160; < break; < case RCTCameraCaptureSessionPreset1080p: < qualityString = AVCaptureSessionPreset1920x1080; < break; < case RCTCameraCaptureSessionPreset720p: < qualityString = AVCaptureSessionPreset1280x720; < break; < case RCTCameraCaptureSessionPreset480p: < qualityString = AVCaptureSessionPreset640x480; < break; < } < < [self setCaptureQuality:qualityString]; --- > NSInteger quality = [RCTConvert NSInteger:json]; > NSString *qualityString; > switch (quality) { > default: > case RCTCameraCaptureSessionPresetHigh: > qualityString = AVCaptureSessionPresetHigh; > break; > case RCTCameraCaptureSessionPresetMedium: > qualityString = AVCaptureSessionPresetMedium; > break; > case RCTCameraCaptureSessionPresetLow: > qualityString = AVCaptureSessionPresetLow; > break; > case RCTCameraCaptureSessionPresetPhoto: > qualityString = AVCaptureSessionPresetPhoto; > break; > case RCTCameraCaptureSessionPreset4k: > qualityString = AVCaptureSessionPreset3840x2160; > break; > case RCTCameraCaptureSessionPreset1080p: > qualityString = AVCaptureSessionPreset1920x1080; > break; > case RCTCameraCaptureSessionPreset720p: > qualityString = AVCaptureSessionPreset1280x720; > break; > case RCTCameraCaptureSessionPreset480p: > qualityString = AVCaptureSessionPreset640x480; > break; > } > > [self setCaptureQuality:qualityString]; 179,194c181,196 < NSInteger aspect = [RCTConvert NSInteger:json]; < NSString *aspectString; < switch (aspect) { < default: < case RCTCameraAspectFill: < aspectString = AVLayerVideoGravityResizeAspectFill; < break; < case RCTCameraAspectFit: < aspectString = AVLayerVideoGravityResizeAspect; < break; < case RCTCameraAspectStretch: < aspectString = AVLayerVideoGravityResize; < break; < } < < self.previewLayer.videoGravity = aspectString; --- > NSInteger aspect = [RCTConvert NSInteger:json]; > NSString *aspectString; > switch (aspect) { > default: > case RCTCameraAspectFill: > aspectString = AVLayerVideoGravityResizeAspectFill; > break; > case RCTCameraAspectFit: > aspectString = AVLayerVideoGravityResizeAspect; > break; > case RCTCameraAspectStretch: > aspectString = AVLayerVideoGravityResize; > break; > } > > self.previewLayer.videoGravity = aspectString; 198,243c200,245 < NSInteger type = [RCTConvert NSInteger:json]; < < self.presetCamera = type; < if (self.session.isRunning) { < dispatch_async(self.sessionQueue, ^{ < AVCaptureDevice *currentCaptureDevice = [self.videoCaptureDeviceInput device]; < AVCaptureDevicePosition position = (AVCaptureDevicePosition)type; < AVCaptureDevice *captureDevice = [self deviceWithMediaType:AVMediaTypeVideo preferringPosition:(AVCaptureDevicePosition)position]; < < if (captureDevice == nil) { < return; < } < < self.presetCamera = type; < < NSError *error = nil; < AVCaptureDeviceInput *captureDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error]; < < if (error || captureDeviceInput == nil) < { < NSLog(@"%@", error); < return; < } < < [self.session beginConfiguration]; < < [self.session removeInput:self.videoCaptureDeviceInput]; < < if ([self.session canAddInput:captureDeviceInput]) < { < [self.session addInput:captureDeviceInput]; < < [NSNotificationCenter.defaultCenter removeObserver:self name:AVCaptureDeviceSubjectAreaDidChangeNotification object:currentCaptureDevice]; < [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(subjectAreaDidChange:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice]; < self.videoCaptureDeviceInput = captureDeviceInput; < [self setFlashMode]; < } < else < { < [self.session addInput:self.videoCaptureDeviceInput]; < } < < [self.session commitConfiguration]; < }); < } < [self initializeCaptureSessionInput:AVMediaTypeVideo]; --- > NSInteger type = [RCTConvert NSInteger:json]; > > self.presetCamera = type; > if (self.session.isRunning) { > dispatch_async(self.sessionQueue, ^{ > AVCaptureDevice *currentCaptureDevice = [self.videoCaptureDeviceInput device]; > AVCaptureDevicePosition position = (AVCaptureDevicePosition)type; > AVCaptureDevice *captureDevice = [self deviceWithMediaType:AVMediaTypeVideo preferringPosition:(AVCaptureDevicePosition)position]; > > if (captureDevice == nil) { > return; > } > > self.presetCamera = type; > > NSError *error = nil; > AVCaptureDeviceInput *captureDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error]; > > if (error || captureDeviceInput == nil) > { > NSLog(@"%@", error); > return; > } > > [self.session beginConfiguration]; > > [self.session removeInput:self.videoCaptureDeviceInput]; > > if ([self.session canAddInput:captureDeviceInput]) > { > [self.session addInput:captureDeviceInput]; > > [NSNotificationCenter.defaultCenter removeObserver:self name:AVCaptureDeviceSubjectAreaDidChangeNotification object:currentCaptureDevice]; > [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(subjectAreaDidChange:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice]; > self.videoCaptureDeviceInput = captureDeviceInput; > [self setFlashMode]; > } > else > { > [self.session addInput:self.videoCaptureDeviceInput]; > } > > [self.session commitConfiguration]; > }); > } > [self initializeCaptureSessionInput:AVMediaTypeVideo]; 254c256 < --- > 277,289c279,291 < dispatch_async(self.sessionQueue, ^{ < NSInteger *torchMode = [RCTConvert NSInteger:json]; < AVCaptureDevice *device = [self.videoCaptureDeviceInput device]; < NSError *error = nil; < < if (![device hasTorch]) return; < if (![device lockForConfiguration:&error]) { < NSLog(@"%@", error); < return; < } < [device setTorchMode: torchMode]; < [device unlockForConfiguration]; < }); --- > dispatch_async(self.sessionQueue, ^{ > NSInteger *torchMode = [RCTConvert NSInteger:json]; > AVCaptureDevice *device = [self.videoCaptureDeviceInput device]; > NSError *error = nil; > > if (![device hasTorch]) return; > if (![device lockForConfiguration:&error]) { > NSLog(@"%@", error); > return; > } > [device setTorchMode: torchMode]; > [device unlockForConfiguration]; > }); 293,294c295,296 < BOOL enabled = [RCTConvert BOOL:json]; < [UIApplication sharedApplication].idleTimerDisabled = enabled; --- > BOOL enabled = [RCTConvert BOOL:json]; > [UIApplication sharedApplication].idleTimerDisabled = enabled; 298c300 < self.mirrorImage = [RCTConvert BOOL:json]; --- > self.mirrorImage = [RCTConvert BOOL:json]; 310c312 < self.barCodeTypes = [RCTConvert NSArray:json]; --- > self.barCodeTypes = [RCTConvert NSArray:json]; 314,318c316,320 < BOOL captureAudio = [RCTConvert BOOL:json]; < if (captureAudio) { < RCTLog(@"capturing audio"); < [self initializeCaptureSessionInput:AVMediaTypeAudio]; < } --- > BOOL captureAudio = [RCTConvert BOOL:json]; > if (captureAudio) { > RCTLog(@"capturing audio"); > [self initializeCaptureSessionInput:AVMediaTypeAudio]; > } 324,325c326,327 < @"focusChanged", < @"zoomChanged", --- > @"focusChanged", > @"zoomChanged", 330,338c332,340 < if ((self = [super init])) { < self.mirrorImage = false; < self.mirrorVideo = false; < < self.sessionQueue = dispatch_queue_create("cameraManagerQueue", DISPATCH_QUEUE_SERIAL); < < self.sensorOrientationChecker = [RCTSensorOrientationChecker new]; < } < return self; --- > if ((self = [super init])) { > self.mirrorImage = false; > self.mirrorVideo = false; > > self.sessionQueue = dispatch_queue_create("cameraManagerQueue", DISPATCH_QUEUE_SERIAL); > > self.sensorOrientationChecker = [RCTSensorOrientationChecker new]; > } > return self; 343,355c345,357 < __block NSString *mediaType = AVMediaTypeVideo; < < [AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) { < if (!granted) { < resolve(@(granted)); < } < else { < mediaType = AVMediaTypeAudio; < [AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) { < resolve(@(granted)); < }]; < } < }]; --- > __block NSString *mediaType = AVMediaTypeVideo; > > [AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) { > if (!granted) { > resolve(@(granted)); > } > else { > mediaType = AVMediaTypeAudio; > [AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) { > resolve(@(granted)); > }]; > } > }]; 362c364 < --- > 371c373 < --- > 378c380 < [self setOrientation:orientation]; --- > [self setOrientation:orientation]; 384,392c386,394 < NSInteger captureMode = [[options valueForKey:@"mode"] intValue]; < NSInteger captureTarget = [[options valueForKey:@"target"] intValue]; < < if (captureMode == RCTCameraCaptureModeStill) { < [self captureStill:captureTarget options:options resolve:resolve reject:reject]; < } < else if (captureMode == RCTCameraCaptureModeVideo) { < [self captureVideo:captureTarget options:options resolve:resolve reject:reject]; < } --- > NSInteger captureMode = [[options valueForKey:@"mode"] intValue]; > NSInteger captureTarget = [[options valueForKey:@"target"] intValue]; > > if (captureMode == RCTCameraCaptureModeStill) { > [self captureStill:captureTarget options:options resolve:resolve reject:reject]; > } > else if (captureMode == RCTCameraCaptureModeVideo) { > [self captureVideo:captureTarget options:options resolve:resolve reject:reject]; > } 418,420c420,422 < if (self.movieFileOutput.recording) { < [self.movieFileOutput stopRecording]; < } --- > if (self.movieFileOutput.recording) { > [self.movieFileOutput stopRecording]; > } 424,452c426,454 < NSArray *devices = [AVCaptureDevice devices]; < AVCaptureDevice *frontCamera; < AVCaptureDevice *backCamera; < double frontFov = 0.0; < double backFov = 0.0; < < for (AVCaptureDevice *device in devices) { < < NSLog(@"Device name: %@", [device localizedName]); < < if ([device hasMediaType:AVMediaTypeVideo]) { < < if ([device position] == AVCaptureDevicePositionBack) { < NSLog(@"Device position : back"); < backCamera = device; < backFov = backCamera.activeFormat.videoFieldOfView; < } < else { < NSLog(@"Device position : front"); < frontCamera = device; < frontFov = frontCamera.activeFormat.videoFieldOfView; < } < } < } < < resolve(@{ < [NSNumber numberWithInt:RCTCameraTypeBack]: [NSNumber numberWithDouble: backFov], < [NSNumber numberWithInt:RCTCameraTypeFront]: [NSNumber numberWithDouble: frontFov] < }); --- > NSArray *devices = [AVCaptureDevice devices]; > AVCaptureDevice *frontCamera; > AVCaptureDevice *backCamera; > double frontFov = 0.0; > double backFov = 0.0; > > for (AVCaptureDevice *device in devices) { > > NSLog(@"Device name: %@", [device localizedName]); > > if ([device hasMediaType:AVMediaTypeVideo]) { > > if ([device position] == AVCaptureDevicePositionBack) { > NSLog(@"Device position : back"); > backCamera = device; > backFov = backCamera.activeFormat.videoFieldOfView; > } > else { > NSLog(@"Device position : front"); > frontCamera = device; > frontFov = frontCamera.activeFormat.videoFieldOfView; > } > } > } > > resolve(@{ > [NSNumber numberWithInt:RCTCameraTypeBack]: [NSNumber numberWithDouble: backFov], > [NSNumber numberWithInt:RCTCameraTypeFront]: [NSNumber numberWithDouble: frontFov] > }); 476c478 < return; --- > return; 478,516c480,518 < dispatch_async(self.sessionQueue, ^{ < if (self.presetCamera == AVCaptureDevicePositionUnspecified) { < self.presetCamera = AVCaptureDevicePositionBack; < } < < AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; < if ([self.session canAddOutput:stillImageOutput]) < { < stillImageOutput.outputSettings = @{AVVideoCodecKey : AVVideoCodecJPEG}; < [self.session addOutput:stillImageOutput]; < self.stillImageOutput = stillImageOutput; < } < < AVCaptureMovieFileOutput *movieFileOutput = [[AVCaptureMovieFileOutput alloc] init]; < if ([self.session canAddOutput:movieFileOutput]) < { < [self.session addOutput:movieFileOutput]; < self.movieFileOutput = movieFileOutput; < } < < AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init]; < if ([self.session canAddOutput:metadataOutput]) { < [metadataOutput setMetadataObjectsDelegate:self queue:self.sessionQueue]; < [self.session addOutput:metadataOutput]; < [metadataOutput setMetadataObjectTypes:self.barCodeTypes]; < self.metadataOutput = metadataOutput; < } < < __weak RCTCameraManager *weakSelf = self; < [self setRuntimeErrorHandlingObserver:[NSNotificationCenter.defaultCenter addObserverForName:AVCaptureSessionRuntimeErrorNotification object:self.session queue:nil usingBlock:^(NSNotification *note) { < RCTCameraManager *strongSelf = weakSelf; < dispatch_async(strongSelf.sessionQueue, ^{ < // Manually restarting the session since it must have been stopped due to an error. < [strongSelf.session startRunning]; < }); < }]]; < < [self.session startRunning]; < }); --- > dispatch_async(self.sessionQueue, ^{ > if (self.presetCamera == AVCaptureDevicePositionUnspecified) { > self.presetCamera = AVCaptureDevicePositionBack; > } > > AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; > if ([self.session canAddOutput:stillImageOutput]) > { > stillImageOutput.outputSettings = @{AVVideoCodecKey : AVVideoCodecJPEG}; > [self.session addOutput:stillImageOutput]; > self.stillImageOutput = stillImageOutput; > } > > AVCaptureMovieFileOutput *movieFileOutput = [[AVCaptureMovieFileOutput alloc] init]; > if ([self.session canAddOutput:movieFileOutput]) > { > [self.session addOutput:movieFileOutput]; > self.movieFileOutput = movieFileOutput; > } > > AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init]; > if ([self.session canAddOutput:metadataOutput]) { > [metadataOutput setMetadataObjectsDelegate:self queue:self.sessionQueue]; > [self.session addOutput:metadataOutput]; > [metadataOutput setMetadataObjectTypes:self.barCodeTypes]; > self.metadataOutput = metadataOutput; > } > > __weak RCTCameraManager *weakSelf = self; > [self setRuntimeErrorHandlingObserver:[NSNotificationCenter.defaultCenter addObserverForName:AVCaptureSessionRuntimeErrorNotification object:self.session queue:nil usingBlock:^(NSNotification *note) { > RCTCameraManager *strongSelf = weakSelf; > dispatch_async(strongSelf.sessionQueue, ^{ > // Manually restarting the session since it must have been stopped due to an error. > [strongSelf.session startRunning]; > }); > }]]; > > [self.session startRunning]; > }); 521,524d522 < self.camera = nil; < return; < #endif < dispatch_async(self.sessionQueue, ^{ 526,536c524,538 < [self.previewLayer removeFromSuperlayer]; < [self.session commitConfiguration]; < [self.session stopRunning]; < for(AVCaptureInput *input in self.session.inputs) { < [self.session removeInput:input]; < } < < for(AVCaptureOutput *output in self.session.outputs) { < [self.session removeOutput:output]; < } < }); --- > return; > #endif > dispatch_async(self.sessionQueue, ^{ > self.camera = nil; > [self.previewLayer removeFromSuperlayer]; > [self.session commitConfiguration]; > [self.session stopRunning]; > for(AVCaptureInput *input in self.session.inputs) { > [self.session removeInput:input]; > } > > for(AVCaptureOutput *output in self.session.outputs) { > [self.session removeOutput:output]; > } > }); 540,545c542,549 < dispatch_async(self.sessionQueue, ^{ < if (type == AVMediaTypeAudio) { < for (AVCaptureDeviceInput* input in [self.session inputs]) { < if ([input.device hasMediaType:AVMediaTypeAudio]) { < // If an audio input has been configured we don't need to set it up again < return; --- > dispatch_async(self.sessionQueue, ^{ > if (type == AVMediaTypeAudio) { > for (AVCaptureDeviceInput* input in [self.session inputs]) { > if ([input.device hasMediaType:AVMediaTypeAudio]) { > // If an audio input has been configured we don't need to set it up again > return; > } > } 547,596c551,598 < } < } < < [self.session beginConfiguration]; < < NSError *error = nil; < < AVCaptureDevice *currentCaptureDevice = [self.videoCaptureDeviceInput device]; < AVCaptureDevice *captureDevice; < < if (type == AVMediaTypeAudio) { < captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; < } < else if (type == AVMediaTypeVideo) { < captureDevice = [self deviceWithMediaType:AVMediaTypeVideo preferringPosition:self.presetCamera]; < } < < if (captureDevice == nil) { < return; < } < < AVCaptureDeviceInput *captureDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error]; < < if (error || captureDeviceInput == nil) { < NSLog(@"%@", error); < return; < } < < if (type == AVMediaTypeVideo) { < [self.session removeInput:self.videoCaptureDeviceInput]; < } < < if ([self.session canAddInput:captureDeviceInput]) { < [self.session addInput:captureDeviceInput]; < < if (type == AVMediaTypeAudio) { < self.audioCaptureDeviceInput = captureDeviceInput; < } < else if (type == AVMediaTypeVideo) { < [NSNotificationCenter.defaultCenter removeObserver:self name:AVCaptureDeviceSubjectAreaDidChangeNotification object:currentCaptureDevice]; < [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(subjectAreaDidChange:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice]; < < self.videoCaptureDeviceInput = captureDeviceInput; < [self setFlashMode]; < } < [self.metadataOutput setMetadataObjectTypes:self.metadataOutput.availableMetadataObjectTypes]; < } < < [self.session commitConfiguration]; < }); --- > > [self.session beginConfiguration]; > > NSError *error = nil; > > AVCaptureDevice *currentCaptureDevice = [self.videoCaptureDeviceInput device]; > AVCaptureDevice *captureDevice; > > if (type == AVMediaTypeAudio) { > captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; > } > else if (type == AVMediaTypeVideo) { > captureDevice = [self deviceWithMediaType:AVMediaTypeVideo preferringPosition:self.presetCamera]; > } > > if (captureDevice == nil) { > return; > } > > AVCaptureDeviceInput *captureDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error]; > > if (error || captureDeviceInput == nil) { > NSLog(@"%@", error); > return; > } > > if (type == AVMediaTypeVideo) { > [self.session removeInput:self.videoCaptureDeviceInput]; > } > > if ([self.session canAddInput:captureDeviceInput]) { > [self.session addInput:captureDeviceInput]; > > if (type == AVMediaTypeAudio) { > self.audioCaptureDeviceInput = captureDeviceInput; > } > else if (type == AVMediaTypeVideo) { > [NSNotificationCenter.defaultCenter removeObserver:self name:AVCaptureDeviceSubjectAreaDidChangeNotification object:currentCaptureDevice]; > [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(subjectAreaDidChange:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice]; > > self.videoCaptureDeviceInput = captureDeviceInput; > [self setFlashMode]; > } > [self.metadataOutput setMetadataObjectTypes:self.metadataOutput.availableMetadataObjectTypes]; > } > > [self.session commitConfiguration]; > }); 603,609c605,611 < #if TARGET_IPHONE_SIMULATOR < [self captureStill:target options:options orientation:self.previewLayer.connection.videoOrientation resolve:resolve reject:reject]; < #else < [self.sensorOrientationChecker getDeviceOrientationWithBlock:^(UIInterfaceOrientation orientation) { < [self captureStill:target options:options orientation:[self.sensorOrientationChecker convertToAVCaptureVideoOrientation: orientation] resolve:resolve reject:reject]; < }]; < #endif --- > #if TARGET_IPHONE_SIMULATOR > [self captureStill:target options:options orientation:self.previewLayer.connection.videoOrientation resolve:resolve reject:reject]; > #else > [self.sensorOrientationChecker getDeviceOrientationWithBlock:^(UIInterfaceOrientation orientation) { > [self captureStill:target options:options orientation:[self.sensorOrientationChecker convertToAVCaptureVideoOrientation: orientation] resolve:resolve reject:reject]; > }]; > #endif 617c619 < dispatch_async(self.sessionQueue, ^{ --- > dispatch_async(self.sessionQueue, ^{ 619,642c621,644 < CGSize size = CGSizeMake(720, 1280); < UIGraphicsBeginImageContextWithOptions(size, YES, 0); < // Thanks https://gist.github.com/kylefox/1689973 < CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0 < CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white < CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black < UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1]; < [color setFill]; < UIRectFill(CGRectMake(0, 0, size.width, size.height)); < NSDate *currentDate = [NSDate date]; < NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; < [dateFormatter setDateFormat:@"dd.MM.YY HH:mm:ss"]; < NSString *text = [dateFormatter stringFromDate:currentDate]; < UIFont *font = [UIFont systemFontOfSize:40.0]; < NSDictionary *attributes = [NSDictionary dictionaryWithObjects: < @[font, [UIColor blackColor]] < forKeys: < @[NSFontAttributeName, NSForegroundColorAttributeName]]; < [text drawAtPoint:CGPointMake(size.width/3, size.height/2) withAttributes:attributes]; < UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); < UIGraphicsEndImageContext(); < < NSData *imageData = UIImageJPEGRepresentation(image, 1.0); < [self saveImage:imageData imageSize:size target:target metadata:nil resolve:resolve reject:reject]; --- > CGSize size = CGSizeMake(720, 1280); > UIGraphicsBeginImageContextWithOptions(size, YES, 0); > // Thanks https://gist.github.com/kylefox/1689973 > CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0 > CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white > CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black > UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1]; > [color setFill]; > UIRectFill(CGRectMake(0, 0, size.width, size.height)); > NSDate *currentDate = [NSDate date]; > NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; > [dateFormatter setDateFormat:@"dd.MM.YY HH:mm:ss"]; > NSString *text = [dateFormatter stringFromDate:currentDate]; > UIFont *font = [UIFont systemFontOfSize:40.0]; > NSDictionary *attributes = [NSDictionary dictionaryWithObjects: > @[font, [UIColor blackColor]] > forKeys: > @[NSFontAttributeName, NSForegroundColorAttributeName]]; > [text drawAtPoint:CGPointMake(size.width/3, size.height/2) withAttributes:attributes]; > UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); > UIGraphicsEndImageContext(); > > NSData *imageData = UIImageJPEGRepresentation(image, 1.0); > [self saveImage:imageData imageSize:size target:target metadata:nil resolve:resolve reject:reject]; 644,680c646,735 < [[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:orientation]; < < [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { < < if (imageDataSampleBuffer) { < NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; < < // Create image source < CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imageData, NULL); < //get all the metadata in the image < NSMutableDictionary *imageMetadata = [(NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source, 0, NULL)) mutableCopy]; < < // create cgimage < CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, NULL); < < // setup viewport size before using < CGSize viewportSize; < < // Rotate it < CGImageRef rotatedCGImage; < if ([options objectForKey:@"rotation"]) { < float rotation = [[options objectForKey:@"rotation"] floatValue]; < rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:rotation]; < } else if ([[options objectForKey:@"fixOrientation"] boolValue] == YES) { < // Get metadata orientation < int metadataOrientation = [[imageMetadata objectForKey:(NSString *)kCGImagePropertyOrientation] intValue]; < < bool rotated = false; < //see http://www.impulseadventure.com/photo/exif-orientation.html < if (metadataOrientation == 6) { < rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:270]; < rotated = true; < } else if (metadataOrientation == 3) { < rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:180]; < rotated = true; < } else { < rotatedCGImage = cgImage; --- > [[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:orientation]; > > [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { > > if (imageDataSampleBuffer) { > NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; > > // Create image source > CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imageData, NULL); > //get all the metadata in the image > NSMutableDictionary *imageMetadata = [(NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source, 0, NULL)) mutableCopy]; > > // create cgimage > CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, NULL); > > // setup viewport size before using > CGSize viewportSize; > > // Rotate it > CGImageRef rotatedCGImage; > if ([options objectForKey:@"rotation"]) { > float rotation = [[options objectForKey:@"rotation"] floatValue]; > rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:rotation]; > } else if ([[options objectForKey:@"fixOrientation"] boolValue] == YES) { > // Get metadata orientation > int metadataOrientation = [[imageMetadata objectForKey:(NSString *)kCGImagePropertyOrientation] intValue]; > > bool rotated = false; > //see http://www.impulseadventure.com/photo/exif-orientation.html > if (metadataOrientation == 6) { > rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:270]; > rotated = true; > } else if (metadataOrientation == 3) { > rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:180]; > rotated = true; > } else { > rotatedCGImage = cgImage; > } > > if(rotated) { > [imageMetadata setObject:[NSNumber numberWithInteger:1] forKey:(NSString *)kCGImagePropertyOrientation]; > CGImageRelease(cgImage); > } > } else { > rotatedCGImage = cgImage; > } > > // Crop it > if (self.cropToPreview) { > > if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) > { > viewportSize = CGSizeMake(self.previewLayer.frame.size.height, self.previewLayer.frame.size.width); > } else { > viewportSize = CGSizeMake(self.previewLayer.frame.size.width, self.previewLayer.frame.size.height); > } > > CGRect captureRect = CGRectMake(0, 0, CGImageGetWidth(rotatedCGImage), CGImageGetHeight(rotatedCGImage)); > CGRect croppedSize = AVMakeRectWithAspectRatioInsideRect(viewportSize, captureRect); > rotatedCGImage = CGImageCreateWithImageInRect(rotatedCGImage, croppedSize); > } > > // Erase stupid TIFF stuff > [imageMetadata removeObjectForKey:(NSString *)kCGImagePropertyTIFFDictionary]; > > // Add input metadata > [imageMetadata mergeMetadata:[options objectForKey:@"metadata"]]; > > // Create destination thing > NSMutableData *rotatedImageData = [NSMutableData data]; > CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)rotatedImageData, CGImageSourceGetType(source), 1, NULL); > CFRelease(source); > // add the image to the destination, reattaching metadata > CGImageDestinationAddImage(destination, rotatedCGImage, (CFDictionaryRef) imageMetadata); > // And write > CGImageDestinationFinalize(destination); > CGSize frameSize; > if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) > { > frameSize = CGSizeMake(CGImageGetHeight(rotatedCGImage), > CGImageGetWidth(rotatedCGImage)); > } else { > frameSize = CGSizeMake(CGImageGetWidth(rotatedCGImage), > CGImageGetHeight(rotatedCGImage)); > } > CFRelease(destination); > > [self saveImage:rotatedImageData imageSize:frameSize target:target metadata:imageMetadata resolve:resolve reject:reject]; > > CGImageRelease(rotatedCGImage); 682,685c737,738 < < if(rotated) { < [imageMetadata setObject:[NSNumber numberWithInteger:1] forKey:(NSString *)kCGImagePropertyOrientation]; < CGImageRelease(cgImage); --- > else { > reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); 687,738c740 < } else { < rotatedCGImage = cgImage; < } < < // Crop it < if (self.cropToPreview) { < < if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) < { < viewportSize = CGSizeMake(self.previewLayer.frame.size.height, self.previewLayer.frame.size.width); < } else { < viewportSize = CGSizeMake(self.previewLayer.frame.size.width, self.previewLayer.frame.size.height); < } < < CGRect captureRect = CGRectMake(0, 0, CGImageGetWidth(rotatedCGImage), CGImageGetHeight(rotatedCGImage)); < CGRect croppedSize = AVMakeRectWithAspectRatioInsideRect(viewportSize, captureRect); < rotatedCGImage = CGImageCreateWithImageInRect(rotatedCGImage, croppedSize); < } < < // Erase stupid TIFF stuff < [imageMetadata removeObjectForKey:(NSString *)kCGImagePropertyTIFFDictionary]; < < // Add input metadata < [imageMetadata mergeMetadata:[options objectForKey:@"metadata"]]; < < // Create destination thing < NSMutableData *rotatedImageData = [NSMutableData data]; < CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)rotatedImageData, CGImageSourceGetType(source), 1, NULL); < CFRelease(source); < // add the image to the destination, reattaching metadata < CGImageDestinationAddImage(destination, rotatedCGImage, (CFDictionaryRef) imageMetadata); < // And write < CGImageDestinationFinalize(destination); < CGSize frameSize; < if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) < { < frameSize = CGSizeMake(CGImageGetHeight(rotatedCGImage), < CGImageGetWidth(rotatedCGImage)); < } else { < frameSize = CGSizeMake(CGImageGetWidth(rotatedCGImage), < CGImageGetHeight(rotatedCGImage)); < } < CFRelease(destination); < < [self saveImage:rotatedImageData imageSize:frameSize target:target metadata:imageMetadata resolve:resolve reject:reject]; < < CGImageRelease(rotatedCGImage); < } < else { < reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); < } < }]; --- > }]; 740c742 < }); --- > }); 745,783c747,787 < NSString *responseString; < < if (target == RCTCameraCaptureTargetMemory) { < resolve(@{@"data":[imageData base64EncodedStringWithOptions:0]}); < return; < } < < else if (target == RCTCameraCaptureTargetDisk) { < NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); < NSString *documentsDirectory = [paths firstObject]; < < NSFileManager *fileManager = [NSFileManager defaultManager]; < NSString *fullPath = [[documentsDirectory stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]] stringByAppendingPathExtension:@"jpg"]; < < [fileManager createFileAtPath:fullPath contents:imageData attributes:nil]; < responseString = fullPath; < } < < else if (target == RCTCameraCaptureTargetTemp) { < NSString *fileName = [[NSProcessInfo processInfo] globallyUniqueString]; < NSString *fullPath = [NSString stringWithFormat:@"%@%@.jpg", NSTemporaryDirectory(), fileName]; < < [imageData writeToFile:fullPath atomically:YES]; < responseString = fullPath; < } < < else if (target == RCTCameraCaptureTargetCameraRoll) { < [[[ALAssetsLibrary alloc] init] writeImageDataToSavedPhotosAlbum:imageData metadata:metadata completionBlock:^(NSURL* url, NSError* error) { < if (error == nil) { < //path isn't really applicable here (this is an asset uri), but left it in for backward comparability < resolve(@{@"path":[url absoluteString], @"mediaUri":[url absoluteString]}); < } < else { < reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); < } < }]; < return; < } < resolve(@{@"path":responseString, @"width":[NSNumber numberWithFloat:imageSize.width], @"height":[NSNumber numberWithFloat:imageSize.height]}); --- > NSString *responseString; > > if (target == RCTCameraCaptureTargetMemory) { > resolve(@{@"data":[imageData base64EncodedStringWithOptions:0]}); > return; > } > > else if (target == RCTCameraCaptureTargetDisk) { > NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); > NSString *documentsDirectory = [paths firstObject]; > > NSFileManager *fileManager = [NSFileManager defaultManager]; > NSString *fullPath = [[documentsDirectory stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]] stringByAppendingPathExtension:@"jpg"]; > > [fileManager createFileAtPath:fullPath contents:imageData attributes:nil]; > responseString = fullPath; > } > > else if (target == RCTCameraCaptureTargetTemp) { > NSString *fileName = [[NSProcessInfo processInfo] globallyUniqueString]; > NSString *fullPath = [NSString stringWithFormat:@"%@%@.jpg", NSTemporaryDirectory(), fileName]; > > [imageData writeToFile:fullPath atomically:YES]; > responseString = fullPath; > } > > else if (target == RCTCameraCaptureTargetCameraRoll) { > #if !TARGET_OS_MACCATALYST > [[[ALAssetsLibrary alloc] init] writeImageDataToSavedPhotosAlbum:imageData metadata:metadata completionBlock:^(NSURL* url, NSError* error) { > if (error == nil) { > //path isn't really applicable here (this is an asset uri), but left it in for backward comparability > resolve(@{@"path":[url absoluteString], @"mediaUri":[url absoluteString]}); > } > else { > reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); > } > }]; > #endif > return; > } > resolve(@{@"path":responseString, @"width":[NSNumber numberWithFloat:imageSize.width], @"height":[NSNumber numberWithFloat:imageSize.height]}); 788,818c792,822 < CGFloat angleInRadians = angle * (M_PI / 180); < CGFloat width = CGImageGetWidth(imgRef); < CGFloat height = CGImageGetHeight(imgRef); < < CGRect imgRect = CGRectMake(0, 0, width, height); < CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians); < CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, transform); < < CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); < CGContextRef bmContext = CGBitmapContextCreate(NULL, rotatedRect.size.width, rotatedRect.size.height, 8, 0, colorSpace, (CGBitmapInfo) kCGImageAlphaPremultipliedFirst); < < if (self.mirrorImage) { < CGAffineTransform transform = CGAffineTransformMakeTranslation(rotatedRect.size.width, 0.0); < transform = CGAffineTransformScale(transform, -1.0, 1.0); < CGContextConcatCTM(bmContext, transform); < } < < CGContextSetAllowsAntialiasing(bmContext, TRUE); < CGContextSetInterpolationQuality(bmContext, kCGInterpolationNone); < < CGColorSpaceRelease(colorSpace); < < CGContextTranslateCTM(bmContext, +(rotatedRect.size.width/2), +(rotatedRect.size.height/2)); < CGContextRotateCTM(bmContext, angleInRadians); < CGContextTranslateCTM(bmContext, -(rotatedRect.size.width/2), -(rotatedRect.size.height/2)); < < CGContextDrawImage(bmContext, CGRectMake((rotatedRect.size.width-width)/2.0f, (rotatedRect.size.height-height)/2.0f, width, height), imgRef); < < CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext); < CFRelease(bmContext); < return rotatedImage; --- > CGFloat angleInRadians = angle * (M_PI / 180); > CGFloat width = CGImageGetWidth(imgRef); > CGFloat height = CGImageGetHeight(imgRef); > > CGRect imgRect = CGRectMake(0, 0, width, height); > CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians); > CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, transform); > > CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); > CGContextRef bmContext = CGBitmapContextCreate(NULL, rotatedRect.size.width, rotatedRect.size.height, 8, 0, colorSpace, (CGBitmapInfo) kCGImageAlphaPremultipliedFirst); > > if (self.mirrorImage) { > CGAffineTransform transform = CGAffineTransformMakeTranslation(rotatedRect.size.width, 0.0); > transform = CGAffineTransformScale(transform, -1.0, 1.0); > CGContextConcatCTM(bmContext, transform); > } > > CGContextSetAllowsAntialiasing(bmContext, TRUE); > CGContextSetInterpolationQuality(bmContext, kCGInterpolationNone); > > CGColorSpaceRelease(colorSpace); > > CGContextTranslateCTM(bmContext, +(rotatedRect.size.width/2), +(rotatedRect.size.height/2)); > CGContextRotateCTM(bmContext, angleInRadians); > CGContextTranslateCTM(bmContext, -(rotatedRect.size.width/2), -(rotatedRect.size.height/2)); > > CGContextDrawImage(bmContext, CGRectMake((rotatedRect.size.width-width)/2.0f, (rotatedRect.size.height-height)/2.0f, width, height), imgRef); > > CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext); > CFRelease(bmContext); > return rotatedImage; 835,866c839,841 < if (self.movieFileOutput.recording) { < reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(@"Already recording")); < return; < } < < if ([[options valueForKey:@"audio"] boolValue]) { < [self initializeCaptureSessionInput:AVMediaTypeAudio]; < } < < Float64 totalSeconds = [[options valueForKey:@"totalSeconds"] floatValue]; < if (totalSeconds > -1) { < int32_t preferredTimeScale = [[options valueForKey:@"preferredTimeScale"] intValue]; < CMTime maxDuration = CMTimeMakeWithSeconds(totalSeconds, preferredTimeScale); < self.movieFileOutput.maxRecordedDuration = maxDuration; < } < < dispatch_async(self.sessionQueue, ^{ < [[self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:orientation]; < < if (self.mirrorVideo) { < [[self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo] setVideoMirrored:YES]; < } < //Create temporary URL to record to < NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"]; < NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath]; < NSFileManager *fileManager = [NSFileManager defaultManager]; < if ([fileManager fileExistsAtPath:outputPath]) { < NSError *error; < if ([fileManager removeItemAtPath:outputPath error:&error] == NO) { < reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); < return; < } --- > if (self.movieFileOutput.recording) { > reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(@"Already recording")); > return; 868,875c843,879 < < //Start recording < [self.movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self]; < < self.videoResolve = resolve; < self.videoReject = reject; < self.videoTarget = target; < }); --- > > if ([[options valueForKey:@"audio"] boolValue]) { > [self initializeCaptureSessionInput:AVMediaTypeAudio]; > } > > Float64 totalSeconds = [[options valueForKey:@"totalSeconds"] floatValue]; > if (totalSeconds > -1) { > int32_t preferredTimeScale = [[options valueForKey:@"preferredTimeScale"] intValue]; > CMTime maxDuration = CMTimeMakeWithSeconds(totalSeconds, preferredTimeScale); > self.movieFileOutput.maxRecordedDuration = maxDuration; > } > > dispatch_async(self.sessionQueue, ^{ > [[self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:orientation]; > > if (self.mirrorVideo) { > [[self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo] setVideoMirrored:YES]; > } > //Create temporary URL to record to > NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"]; > NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath]; > NSFileManager *fileManager = [NSFileManager defaultManager]; > if ([fileManager fileExistsAtPath:outputPath]) { > NSError *error; > if ([fileManager removeItemAtPath:outputPath error:&error] == NO) { > reject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); > return; > } > } > > //Start recording > [self.movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self]; > > self.videoResolve = resolve; > self.videoReject = reject; > self.videoTarget = target; > }); 883,967c887,896 < BOOL recordSuccess = YES; < if ([error code] != noErr) { < // A problem occurred: Find out if the recording was successful. < id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey]; < if (value) { < recordSuccess = [value boolValue]; < } < } < if (!recordSuccess) { < self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(@"Error while recording")); < return; < } < < AVURLAsset* videoAsAsset = [AVURLAsset URLAssetWithURL:outputFileURL options:nil]; < AVAssetTrack* videoTrack = [[videoAsAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; < float videoWidth; < float videoHeight; < < CGSize videoSize = [videoTrack naturalSize]; < CGAffineTransform txf = [videoTrack preferredTransform]; < < if ((txf.tx == videoSize.width && txf.ty == videoSize.height) || (txf.tx == 0 && txf.ty == 0)) { < // Video recorded in landscape orientation < videoWidth = videoSize.width; < videoHeight = videoSize.height; < } else { < // Video recorded in portrait orientation, so have to swap reported width/height < videoWidth = videoSize.height; < videoHeight = videoSize.width; < } < < NSMutableDictionary *videoInfo = [NSMutableDictionary dictionaryWithDictionary:@{ < @"duration":[NSNumber numberWithFloat:CMTimeGetSeconds(videoAsAsset.duration)], < @"width":[NSNumber numberWithFloat:videoWidth], < @"height":[NSNumber numberWithFloat:videoHeight], < @"size":[NSNumber numberWithLongLong:captureOutput.recordedFileSize], < }]; < < if (self.videoTarget == RCTCameraCaptureTargetCameraRoll) { < ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; < if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputFileURL]) { < [library writeVideoAtPathToSavedPhotosAlbum:outputFileURL < completionBlock:^(NSURL *assetURL, NSError *error) { < if (error) { < self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); < return; < } else if (assetURL == nil) { < //It's possible for writing to camera roll to fail, < //without receiving an error message, but assetURL will be nil < //Happens when disk is (almost) full < self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(@"Not enough storage")); < return; < } < < [videoInfo setObject:[assetURL absoluteString] forKey:@"path"]; < self.videoResolve(videoInfo); < }]; < } < } < else if (self.videoTarget == RCTCameraCaptureTargetDisk) { < NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); < NSString *documentsDirectory = [paths firstObject]; < NSString *fullPath = [[documentsDirectory stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]] stringByAppendingPathExtension:@"mov"]; < < NSFileManager * fileManager = [NSFileManager defaultManager]; < NSError * error = nil; < < //moving to destination < if (!([fileManager moveItemAtPath:[outputFileURL path] toPath:fullPath error:&error])) { < self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); < return; < } < [videoInfo setObject:fullPath forKey:@"path"]; < self.videoResolve(videoInfo); < } < else if (self.videoTarget == RCTCameraCaptureTargetTemp) { < NSString *fileName = [[NSProcessInfo processInfo] globallyUniqueString]; < NSString *fullPath = [NSString stringWithFormat:@"%@%@.mov", NSTemporaryDirectory(), fileName]; < < NSFileManager * fileManager = [NSFileManager defaultManager]; < NSError * error = nil; < < //moving to destination < if (!([fileManager moveItemAtPath:[outputFileURL path] toPath:fullPath error:&error])) { < self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); --- > BOOL recordSuccess = YES; > if ([error code] != noErr) { > // A problem occurred: Find out if the recording was successful. > id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey]; > if (value) { > recordSuccess = [value boolValue]; > } > } > if (!recordSuccess) { > self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(@"Error while recording")); 970,975c899,982 < [videoInfo setObject:fullPath forKey:@"path"]; < self.videoResolve(videoInfo); < } < else { < self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(@"Target not supported")); < } --- > > AVURLAsset* videoAsAsset = [AVURLAsset URLAssetWithURL:outputFileURL options:nil]; > AVAssetTrack* videoTrack = [[videoAsAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; > float videoWidth; > float videoHeight; > > CGSize videoSize = [videoTrack naturalSize]; > CGAffineTransform txf = [videoTrack preferredTransform]; > > if ((txf.tx == videoSize.width && txf.ty == videoSize.height) || (txf.tx == 0 && txf.ty == 0)) { > // Video recorded in landscape orientation > videoWidth = videoSize.width; > videoHeight = videoSize.height; > } else { > // Video recorded in portrait orientation, so have to swap reported width/height > videoWidth = videoSize.height; > videoHeight = videoSize.width; > } > > NSMutableDictionary *videoInfo = [NSMutableDictionary dictionaryWithDictionary:@{ > @"duration":[NSNumber numberWithFloat:CMTimeGetSeconds(videoAsAsset.duration)], > @"width":[NSNumber numberWithFloat:videoWidth], > @"height":[NSNumber numberWithFloat:videoHeight], > @"size":[NSNumber numberWithLongLong:captureOutput.recordedFileSize], > }]; > > if (self.videoTarget == RCTCameraCaptureTargetCameraRoll) { > #if !TARGET_OS_MACCATALYST > ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; > if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputFileURL]) { > [library writeVideoAtPathToSavedPhotosAlbum:outputFileURL > completionBlock:^(NSURL *assetURL, NSError *error) { > if (error) { > self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); > return; > } else if (assetURL == nil) { > //It's possible for writing to camera roll to fail, > //without receiving an error message, but assetURL will be nil > //Happens when disk is (almost) full > self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(@"Not enough storage")); > return; > } > > [videoInfo setObject:[assetURL absoluteString] forKey:@"path"]; > self.videoResolve(videoInfo); > }]; > } > > #endif > } > else if (self.videoTarget == RCTCameraCaptureTargetDisk) { > NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); > NSString *documentsDirectory = [paths firstObject]; > NSString *fullPath = [[documentsDirectory stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]] stringByAppendingPathExtension:@"mov"]; > > NSFileManager * fileManager = [NSFileManager defaultManager]; > NSError * error = nil; > > //moving to destination > if (!([fileManager moveItemAtPath:[outputFileURL path] toPath:fullPath error:&error])) { > self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); > return; > } > [videoInfo setObject:fullPath forKey:@"path"]; > self.videoResolve(videoInfo); > } > else if (self.videoTarget == RCTCameraCaptureTargetTemp) { > NSString *fileName = [[NSProcessInfo processInfo] globallyUniqueString]; > NSString *fullPath = [NSString stringWithFormat:@"%@%@.mov", NSTemporaryDirectory(), fileName]; > > NSFileManager * fileManager = [NSFileManager defaultManager]; > NSError * error = nil; > > //moving to destination > if (!([fileManager moveItemAtPath:[outputFileURL path] toPath:fullPath error:&error])) { > self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(error.description)); > return; > } > [videoInfo setObject:fullPath forKey:@"path"]; > self.videoResolve(videoInfo); > } > else { > self.videoReject(RCTErrorUnspecified, nil, RCTErrorWithMessage(@"Target not supported")); > } 979,996c986,1008 < < for (AVMetadataMachineReadableCodeObject *metadata in metadataObjects) { < for (id barcodeType in self.barCodeTypes) { < if ([metadata.type isEqualToString:barcodeType] && metadata.stringValue) { < // Transform the meta-data coordinates to screen coords < AVMetadataMachineReadableCodeObject *transformed = (AVMetadataMachineReadableCodeObject *)[_previewLayer transformedMetadataObjectForMetadataObject:metadata]; < < NSDictionary *event = @{ < @"type": metadata.type, < @"data": metadata.stringValue, < @"bounds": @{ < @"origin": @{ < @"x": [NSString stringWithFormat:@"%f", transformed.bounds.origin.x], < @"y": [NSString stringWithFormat:@"%f", transformed.bounds.origin.y] < }, < @"size": @{ < @"height": [NSString stringWithFormat:@"%f", transformed.bounds.size.height], < @"width": [NSString stringWithFormat:@"%f", transformed.bounds.size.width], --- > > for (AVMetadataMachineReadableCodeObject *metadata in metadataObjects) { > for (id barcodeType in self.barCodeTypes) { > if ([metadata.type isEqualToString:barcodeType] && metadata.stringValue) { > // Transform the meta-data coordinates to screen coords > AVMetadataMachineReadableCodeObject *transformed = (AVMetadataMachineReadableCodeObject *)[_previewLayer transformedMetadataObjectForMetadataObject:metadata]; > > NSDictionary *event = @{ > @"type": metadata.type, > @"data": metadata.stringValue, > @"bounds": @{ > @"origin": @{ > @"x": [NSString stringWithFormat:@"%f", transformed.bounds.origin.x], > @"y": [NSString stringWithFormat:@"%f", transformed.bounds.origin.y] > }, > @"size": @{ > @"height": [NSString stringWithFormat:@"%f", transformed.bounds.size.height], > @"width": [NSString stringWithFormat:@"%f", transformed.bounds.size.width], > } > } > }; > > [self.bridge.eventDispatcher sendAppEventWithName:@"CameraBarCodeRead" body:event]; 998,1002c1010 < } < }; < < [self.bridge.eventDispatcher sendAppEventWithName:@"CameraBarCodeRead" body:event]; < } --- > } 1004d1011 < } 1010,1015c1017,1020 < NSArray *devices = [AVCaptureDevice devicesWithMediaType:mediaType]; < AVCaptureDevice *captureDevice = [devices firstObject]; < < for (AVCaptureDevice *device in devices) < { < if ([device position] == position) --- > NSArray *devices = [AVCaptureDevice devicesWithMediaType:mediaType]; > AVCaptureDevice *captureDevice = [devices firstObject]; > > for (AVCaptureDevice *device in devices) 1017,1018c1022,1026 < captureDevice = device; < break; --- > if ([device position] == position) > { > captureDevice = device; > break; > } 1020,1022c1028,1029 < } < < return captureDevice; --- > > return captureDevice; 1027,1028c1034,1044 < CGPoint devicePoint = CGPointMake(.5, .5); < [self focusWithMode:AVCaptureFocusModeContinuousAutoFocus exposeWithMode:AVCaptureExposureModeContinuousAutoExposure atDevicePoint:devicePoint monitorSubjectAreaChange:NO]; --- > CGPoint devicePoint = CGPointMake(.5, .5); > [self focusWithMode:AVCaptureFocusModeContinuousAutoFocus exposeWithMode:AVCaptureExposureModeContinuousAutoExposure atDevicePoint:devicePoint monitorSubjectAreaChange:NO]; > > if (self.camera.camFocus) > { > [self.camera.camFocus removeFromSuperview]; > } > self.camera.camFocus = [[RCTCameraFocusSquare alloc]initWithFrame:CGRectMake([self.view center].x-80, [self.view center].y-80, 160, 160)]; > [self.camera.camFocus setBackgroundColor:[UIColor clearColor]]; > [self.view addSubview:self.camera.camFocus]; > [self.camera.camFocus setNeedsDisplay]; 1030,1042c1046,1049 < if (self.camera.camFocus) < { < [self.camera.camFocus removeFromSuperview]; < } < self.camera.camFocus = [[RCTCameraFocusSquare alloc]initWithFrame:CGRectMake([self.view center].x-80, [self.view center].y-80, 160, 160)]; < [self.camera.camFocus setBackgroundColor:[UIColor clearColor]]; < [self.view addSubview:self.camera.camFocus]; < [self.camera.camFocus setNeedsDisplay]; < < [UIView beginAnimations:nil context:NULL]; < [UIView setAnimationDuration:1.0]; < [self.camera.camFocus setAlpha:0.0]; < [UIView commitAnimations]; --- > [UIView beginAnimations:nil context:NULL]; > [UIView setAnimationDuration:1.0]; > [self.camera.camFocus setAlpha:0.0]; > [UIView commitAnimations]; 1047,1069c1054,1076 < dispatch_async([self sessionQueue], ^{ < AVCaptureDevice *device = [[self videoCaptureDeviceInput] device]; < NSError *error = nil; < if ([device lockForConfiguration:&error]) < { < if ([device isFocusPointOfInterestSupported] && [device isFocusModeSupported:focusMode]) < { < [device setFocusMode:focusMode]; < [device setFocusPointOfInterest:point]; < } < if ([device isExposurePointOfInterestSupported] && [device isExposureModeSupported:exposureMode]) < { < [device setExposureMode:exposureMode]; < [device setExposurePointOfInterest:point]; < } < [device setSubjectAreaChangeMonitoringEnabled:monitorSubjectAreaChange]; < [device unlockForConfiguration]; < } < else < { < NSLog(@"%@", error); < } < }); --- > dispatch_async([self sessionQueue], ^{ > AVCaptureDevice *device = [[self videoCaptureDeviceInput] device]; > NSError *error = nil; > if ([device lockForConfiguration:&error]) > { > if ([device isFocusPointOfInterestSupported] && [device isFocusModeSupported:focusMode]) > { > [device setFocusMode:focusMode]; > [device setFocusPointOfInterest:point]; > } > if ([device isExposurePointOfInterestSupported] && [device isExposureModeSupported:exposureMode]) > { > [device setExposureMode:exposureMode]; > [device setExposurePointOfInterest:point]; > } > [device setSubjectAreaChangeMonitoringEnabled:monitorSubjectAreaChange]; > [device unlockForConfiguration]; > } > else > { > NSLog(@"%@", error); > } > }); 1115c1122 < --- > 1117,1119c1124,1126 < @"target": reactTag, < @"zoomFactor": [NSNumber numberWithDouble:zoomFactor], < @"velocity": [NSNumber numberWithDouble:velocity] --- > @"target": reactTag, > @"zoomFactor": [NSNumber numberWithDouble:zoomFactor], > @"velocity": [NSNumber numberWithDouble:velocity] 1121c1128 < --- > 1123c1130 < --- > 1133,1145c1140,1152 < #if !(TARGET_IPHONE_SIMULATOR) < if (quality) { < dispatch_async([self sessionQueue], ^{ < [self.session beginConfiguration]; < if ([self.session canSetSessionPreset:quality]) { < self.session.sessionPreset = quality; < } else { < self.session.sessionPreset = AVCaptureSessionPresetHigh; < } < [self.session commitConfiguration]; < }); < } < #endif --- > #if !(TARGET_IPHONE_SIMULATOR) > if (quality) { > dispatch_async([self sessionQueue], ^{ > [self.session beginConfiguration]; > if ([self.session canSetSessionPreset:quality]) { > self.session.sessionPreset = quality; > } else { > self.session.sessionPreset = AVCaptureSessionPresetHigh; > } > [self.session commitConfiguration]; > }); > } > #endif