UNPKG

@nativescript-community/ui-cameraview

Version:

A CameraView allowing custom live processing for NativeScript

356 lines 15 kB
import { CameraViewBase, ScaleType, autoFocusProperty, flashModeProperty, frontMirroredProperty, stretchProperty, zoomProperty } from './index.common'; import { Property, Utils } from '@nativescript/core'; function getScaleType(scaleType) { if (typeof scaleType === 'string') { switch (scaleType) { case ScaleType.FitCenter: case ScaleType.AspectFit: case ScaleType.FitEnd: case ScaleType.FitStart: return AVLayerVideoGravityResizeAspect; default: case ScaleType.Center: case ScaleType.Fill: case ScaleType.AspectFill: return AVLayerVideoGravityResizeAspectFill; } } return AVLayerVideoGravityResizeAspectFill; } export function deviceHasCamera() { return NextLevel.shared.canCapturePhoto; } var ProcessRawVideoSampleBufferDelegateImpl = /** @class */ (function (_super) { __extends(ProcessRawVideoSampleBufferDelegateImpl, _super); function ProcessRawVideoSampleBufferDelegateImpl() { return _super !== null && _super.apply(this, arguments) || this; } ProcessRawVideoSampleBufferDelegateImpl.prototype.cameraViewRenderToCustomContextWithImageBufferOnQueue = function (cameraView, imageBuffer, queue) { }; ProcessRawVideoSampleBufferDelegateImpl.prototype.cameraViewWillProcessRawVideoSampleBufferOnQueue = function (cameraView, sampleBuffer, queue) { var _a, _b, _c; var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.get(); (_c = (_b = this._owner) === null || _b === void 0 ? void 0 : _b.get()) === null || _c === void 0 ? void 0 : _c.notify({ eventName: 'frame', object: owner, cameraView: cameraView, sampleBuffer: sampleBuffer, queue: queue }); }; ProcessRawVideoSampleBufferDelegateImpl.initWithOwner = function (owner) { var delegate = ProcessRawVideoSampleBufferDelegateImpl.new(); delegate._owner = new WeakRef(owner); return delegate; }; ProcessRawVideoSampleBufferDelegateImpl.ObjCProtocols = [ProcessRawVideoSampleBufferDelegate]; return ProcessRawVideoSampleBufferDelegateImpl; }(NSObject)); var NSCameraViewVideoDelegateImpl = /** @class */ (function (_super) { __extends(NSCameraViewVideoDelegateImpl, _super); function NSCameraViewVideoDelegateImpl() { return _super !== null && _super.apply(this, arguments) || this; } NSCameraViewVideoDelegateImpl.prototype.cameraViewDidCompletePhotoCaptureFromVideoFrame = function (cameraView, photoDict) { var _a, _b; (_b = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.get()) === null || _b === void 0 ? void 0 : _b.cameraViewDidCompletePhotoCaptureFromVideoFrame(photoDict); }; NSCameraViewVideoDelegateImpl.initWithOwner = function (owner) { var delegate = NSCameraViewVideoDelegateImpl.new(); delegate._owner = new WeakRef(owner); return delegate; }; NSCameraViewVideoDelegateImpl.ObjCProtocols = [NSCameraViewVideoDelegate]; return NSCameraViewVideoDelegateImpl; }(NSObject)); var NSCameraViewPhotoDelegateImpl = /** @class */ (function (_super) { __extends(NSCameraViewPhotoDelegateImpl, _super); function NSCameraViewPhotoDelegateImpl() { return _super !== null && _super.apply(this, arguments) || this; } NSCameraViewPhotoDelegateImpl.prototype.cameraViewDidCapturePhotoWithConfiguration = function (cameraView, photoConfiguration) { }; NSCameraViewPhotoDelegateImpl.prototype.cameraViewDidFinishProcessingPhotoPhotoDictPhotoConfiguration = function (cameraView, photo, photoDict, photoConfiguration) { var _a, _b; // TODO: move this to swift var size = photo.size; UIGraphicsBeginImageContextWithOptions(size, false, photo.scale); photo.drawInRect(CGRectMake(0, 0, size.width, size.height)); var resizedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); (_b = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.get()) === null || _b === void 0 ? void 0 : _b.cameraViewDidFinishProcessingPhotoPhotoDictPhotoConfiguration(resizedImage, photoDict); }; NSCameraViewPhotoDelegateImpl.initWithOwner = function (owner) { var delegate = NSCameraViewPhotoDelegateImpl.new(); delegate._owner = new WeakRef(owner); return delegate; }; NSCameraViewPhotoDelegateImpl.ObjCProtocols = [NSCameraViewPhotoDelegate]; return NSCameraViewPhotoDelegateImpl; }(NSObject)); var NSCameraViewDelegateImpl = /** @class */ (function (_super) { __extends(NSCameraViewDelegateImpl, _super); function NSCameraViewDelegateImpl() { return _super !== null && _super.apply(this, arguments) || this; } NSCameraViewDelegateImpl.prototype.sessionDidStart = function (cameraView) { var owner = this._owner.get(); if (owner) { owner.notify({ eventName: 'cameraOpen' }); } }; NSCameraViewDelegateImpl.prototype.sessionDidStop = function (cameraView) { var owner = this._owner.get(); if (owner) { owner.notify({ eventName: 'cameraClose' }); } }; NSCameraViewDelegateImpl.prototype.didUpdateVideoZoomFactor = function (zoom) { var owner = this._owner.get(); if (owner) { owner.notify({ eventName: 'zoom', zoom: zoom }); } }; NSCameraViewDelegateImpl.initWithOwner = function (owner) { var delegate = NSCameraViewDelegateImpl.new(); delegate._owner = new WeakRef(owner); return delegate; }; NSCameraViewDelegateImpl.ObjCProtocols = [NSCameraViewDelegate]; return NSCameraViewDelegateImpl; }(NSObject)); export const iosCaptureModeProperty = new Property({ name: 'iosCaptureMode', defaultValue: 1 }); export class CameraView extends CameraViewBase { constructor() { super(...arguments); this.videoCaptureListener = new Set(); this.photoCaptureListener = new Set(); this._frameChangeCount = 0; this.previewStarted = false; } cameraViewDidFinishProcessingPhotoPhotoDictPhotoConfiguration(photo, photoDict) { // const cgImage = photo.CGImageRepresentation(); // const orientation = photo.metadata.objectForKey(kCGImagePropertyOrientation); // const image = UIImage.imageWithCGImageScaleOrientation(cgImage, 1, orientation); this.photoCaptureListener.forEach((c) => c(photo, photoDict)); } cameraViewDidProcessPhotoCaptureWithPhotoConfiguration(photoDict) { } cameraViewDidCompletePhotoCaptureFromVideoFrame(photoDict) { this.videoCaptureListener.forEach((c) => c(photoDict)); } createNativeView() { return NSCameraView.alloc().initWithFrame(CGRectZero); } initNativeView() { super.initNativeView(); const nativeView = this.nativeViewProtected; nativeView.photoDelegate = this.photoDelegate = NSCameraViewPhotoDelegateImpl.initWithOwner(this); nativeView.videoDelegate = this.videoDelegate = NSCameraViewVideoDelegateImpl.initWithOwner(this); nativeView.delegate = this.delegate = NSCameraViewDelegateImpl.initWithOwner(this); } disposeNativeView() { this.stopPreview(); this.detachProcessor(); const nativeView = this.nativeViewProtected; nativeView.videoDelegate = this.videoDelegate = null; nativeView.photoDelegate = this.photoDelegate = null; nativeView.delegate = this.delegate = null; super.disposeNativeView(); } get processor() { return this._processor; } set processor(value) { this._processor = value; if (this.nativeViewProtected) { this.nativeViewProtected.processingDelegate = this._processor; } } get minZoom() { return this.nativeViewProtected?.minVideoZoomFactor; } get maxZoom() { return this.nativeViewProtected?.maxVideoZoomFactor; } get neutralZoom() { return this.nativeViewProtected?.neutralVideoZoomFactor; } addEventListener(arg, callback, thisArg) { super.addEventListener(arg, callback, thisArg); if (arg === CameraViewBase.FRAME_EVENT) { this._frameChangeCount++; this.createProcessor(); } } removeEventListener(arg, callback, thisArg) { super.removeEventListener(arg, callback, thisArg); if (arg === CameraViewBase.FRAME_EVENT) { this._frameChangeCount--; if (this._frameChangeCount === 0) { this.detachProcessor(); } } } createProcessor() { if (!this.processor) { this.processor = ProcessRawVideoSampleBufferDelegateImpl.initWithOwner(this); if (this.nativeViewProtected) { this.nativeViewProtected.processingDelegate = this.processor; } } } detachProcessor() { if (this.processor) { if (this.nativeViewProtected) { this.nativeViewProtected.processingDelegate = null; } this.processor = null; } } onLoaded() { super.onLoaded(); if (this.processor) { this.nativeViewProtected.processingDelegate = this.processor; } this.startPreview(); } onUnloaded() { this.stopPreview(); this.nativeViewProtected.processingDelegate = null; super.onUnloaded(); } startPreview() { const nativeView = this.nativeViewProtected; if (!nativeView || this.previewStarted || !this.readyToStartPreview) { return; } this.previewStarted = true; nativeView.startPreviewAndReturnError(); } stopPreview() { if (!this.previewStarted) { return; } this.previewStarted = false; this.nativeViewProtected?.stopPreview(); } focusAtPoint(x, y) { // NextLevel expects a point between 0,1 const width = this.getMeasuredWidth(); const height = this.getMeasuredHeight(); console.log('focusAtPoint', width, height, x, y); this.nativeViewProtected?.focusAtAdjustedPointOfInterest(CGPointMake(Utils.layout.toDevicePixels(x) / width, Utils.layout.toDevicePixels(y) / height)); } async takePicture(options = {}) { return new Promise((resolve, reject) => { try { // if (!this.nativeViewProtected.canCaptureVideo) { // return reject(new Error('this device cant capture photo: ' + this.nativeViewProtected.canCaptureVideo)); // } // const onPhoto = (photoDict: NSDictionary<any, any>) => { // this.videoCaptureListener.delete(onPhoto); // const photoData = photoDict.objectForKey('NextLevelPhotoJPEGKey'); // console.log('photoData', photoData, photoDict); // resolve({ image: new UIImage({ data: photoData }) }); // }; // this.videoCaptureListener.add(onPhoto); // console.log('capturePhotoFromVideo'); // this.nativeViewProtected?.capturePhotoFromVideo(); if (!this.nativeViewProtected.canCapturePhoto) { return reject(new Error('this device cant capture photo: ' + this.nativeViewProtected.canCapturePhoto)); } const onPhoto = (image, photoDict) => { resolve({ image }); }; this.photoCaptureListener.add(onPhoto); this.nativeViewProtected?.capturePhoto(JSON.stringify(options)); } catch (error) { reject(error); } }); } toggleCamera() { this.nativeViewProtected.toggleCamera(); } [iosCaptureModeProperty.setNative](value) { let intValue; if (typeof value === 'string') { switch (value) { case 'video': intValue = 0; break; case 'audio': intValue = 2; break; case 'videoWithoutAudio': intValue = 3; break; case 'videoPhotoWithoutAudio': intValue = 4; break; case 'movie': intValue = 5; break; case 'arKit': intValue = 6; break; case 'arKitWithoutAudio': intValue = 7; break; default: case 'photo': intValue = 1; break; } } else { intValue = value; } this.nativeViewProtected.captureMode = intValue; } [flashModeProperty.setNative](value) { const nativeView = this.nativeViewProtected; if (typeof value === 'string') { switch (value) { case 'off': nativeView.torchMode = 0 /* AVCaptureTorchMode.Off */; nativeView.flashMode = 0 /* AVCaptureFlashMode.Off */; break; case 'on': nativeView.torchMode = 0 /* AVCaptureTorchMode.Off */; nativeView.flashMode = 1 /* AVCaptureFlashMode.On */; break; case 'auto': nativeView.torchMode = 0 /* AVCaptureTorchMode.Off */; nativeView.flashMode = 2 /* AVCaptureFlashMode.Auto */; break; case 'torch': nativeView.flashMode = 0 /* AVCaptureFlashMode.Off */; nativeView.torchMode = 1 /* AVCaptureTorchMode.On */; break; } } else { nativeView.torchMode = 0 /* AVCaptureTorchMode.Off */; nativeView.flashMode = value; } } [autoFocusProperty.setNative](value) { if (typeof value === 'boolean') { this.nativeViewProtected.focusMode = value ? 2 /* AVCaptureFocusMode.ContinuousAutoFocus */ : 0 /* AVCaptureFocusMode.Locked */; } else { this.nativeViewProtected.focusMode = value; } } [stretchProperty.setNative](value) { this.nativeViewProtected.videoGravity = getScaleType(value); } [zoomProperty.setNative](value) { this.nativeViewProtected.videoZoomFactor = value; } [frontMirroredProperty.setNative](value) { this.nativeViewProtected.frontMirrored = value; } getAllAvailablePictureSizes() { // TODO: implement } } iosCaptureModeProperty.register(CameraView); //# sourceMappingURL=index.ios.js.map