Skip to content

Commit b13235a

Browse files
committed
fix(ios): correctly returned picture(rotation)
1 parent cf7ace0 commit b13235a

File tree

6 files changed

+187
-18
lines changed

6 files changed

+187
-18
lines changed

packages/ui-cameraview/platforms/ios/src/NSCameraView.swift

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ public class NSCameraView: UIView, NextLevelVideoDelegate, NextLevelPhotoDelegat
6767
self.nextLevel?.torchMode = NextLevelTorchMode(rawValue: newValue)!
6868
}
6969
}
70+
public var focusMode: Int {
71+
get {
72+
return (self.nextLevel?.focusMode ?? NextLevelFocusMode.autoFocus).rawValue
73+
}
74+
set {
75+
self.nextLevel?.focusMode = NextLevelFocusMode(rawValue: newValue)!
76+
}
77+
}
7078

7179
func commonInit() {
7280
self.autoresizingMask = [.flexibleWidth, .flexibleHeight]
@@ -100,7 +108,7 @@ public class NSCameraView: UIView, NextLevelVideoDelegate, NextLevelPhotoDelegat
100108

101109
// audio configuration
102110
// for now disable audio
103-
nextLevel.captureMode = NextLevelCaptureMode.videoWithoutAudio
111+
nextLevel.captureMode = NextLevelCaptureMode.photo
104112
// nextLevel.audioConfiguration.bitRate = 96000
105113
// nextLevel.disableAudioInputDevice()
106114
// metadata objects configuration
@@ -110,7 +118,9 @@ public class NSCameraView: UIView, NextLevelVideoDelegate, NextLevelPhotoDelegat
110118

111119
public func startPreview() throws {
112120
do {
121+
if (self.nextLevel?.session == nil) {
113122
try self.nextLevel?.start()
123+
}
114124
} catch {
115125
let nextLevelError = error as! NextLevelError
116126
// re throw the error with the description so that N can correctly show the error message
@@ -140,7 +150,7 @@ public class NSCameraView: UIView, NextLevelVideoDelegate, NextLevelPhotoDelegat
140150
}
141151
}
142152
public func capturePhoto() {
143-
if let nextLevel = self.nextLevel , self.canCapturePhoto {
153+
if let nextLevel = self.nextLevel , self.canCapturePhoto {
144154
if ( nextLevel.captureMode == NextLevelCaptureMode.photo) {
145155
nextLevel.capturePhoto()
146156
} else {
@@ -275,19 +285,64 @@ public class NSCameraView: UIView, NextLevelVideoDelegate, NextLevelPhotoDelegat
275285
public func nextLevel(_ nextLevel: NextLevel, output: AVCapturePhotoOutput, willBeginCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings, photoConfiguration: NextLevelPhotoConfiguration) {
276286

277287
}
278-
288+
var deviceOrientationOnCapture: UIDeviceOrientation?
279289
public func nextLevel(_ nextLevel: NextLevel, output: AVCapturePhotoOutput, willCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings, photoConfiguration: NextLevelPhotoConfiguration) {
290+
self.deviceOrientationOnCapture = UIDevice.current.orientation
280291
}
281292

282293
public func nextLevel(_ nextLevel: NextLevel, output: AVCapturePhotoOutput, didCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings, photoConfiguration: NextLevelPhotoConfiguration) {
283294
}
284295

285296
public func nextLevel(_ nextLevel: NextLevel, didFinishProcessingPhoto photo: AVCapturePhoto, photoDict: [String : Any], photoConfiguration: NextLevelPhotoConfiguration) {
286-
self.photoDelegate?.cameraView(self, didFinishProcessingPhoto: photo, photoDict: photoDict, photoConfiguration: NSCameraViewPhotoConfiguration(configuration: photoConfiguration))
297+
let photoMetadata = photo.metadata
298+
// Returns corresponting NSCFNumber. It seems to specify the origin of the image
299+
// print("Metadata orientation: ",photoMetadata["Orientation"])
300+
301+
// Returns corresponting NSCFNumber. It seems to specify the origin of the image
302+
print("Metadata orientation with key: ",photoMetadata[String(kCGImagePropertyOrientation)] as Any)
303+
304+
guard let imageData = photo.fileDataRepresentation() else {
305+
print("Error while generating image from photo capture data.");
306+
return
307+
}
308+
309+
guard let uiImage = UIImage(data: imageData) else {
310+
print("Unable to generate UIImage from image data.");
311+
return
312+
}
313+
314+
// generate a corresponding CGImage
315+
guard let cgImage = uiImage.cgImage else {
316+
print("Error generating CGImage")
317+
return
318+
}
319+
320+
guard let deviceOrientationOnCapture = self.deviceOrientationOnCapture else {
321+
print("Error retrieving orientation on capture")
322+
return
323+
}
324+
325+
var image = UIImage(cgImage: cgImage, scale: 1.0, orientation: deviceOrientationOnCapture.getUIImageOrientationFromDevice())
326+
327+
self.photoDelegate?.cameraView(self, didFinishProcessingPhoto: image, photoDict: photoDict, photoConfiguration: NSCameraViewPhotoConfiguration(configuration: photoConfiguration))
287328
}
288329

289330
public func nextLevelDidCompletePhotoCapture(_ nextLevel: NextLevel) {
290331

291332
}
292333

293334
}
335+
336+
extension UIDeviceOrientation {
337+
func getUIImageOrientationFromDevice() -> UIImage.Orientation {
338+
// return CGImagePropertyOrientation based on Device Orientation
339+
// This extented function has been determined based on experimentation with how an UIImage gets displayed.
340+
switch self {
341+
case UIDeviceOrientation.portrait, .faceUp: return UIImage.Orientation.right
342+
case UIDeviceOrientation.portraitUpsideDown, .faceDown: return UIImage.Orientation.left
343+
case UIDeviceOrientation.landscapeLeft: return UIImage.Orientation.up // this is the base orientation
344+
case UIDeviceOrientation.landscapeRight: return UIImage.Orientation.down
345+
case UIDeviceOrientation.unknown: return UIImage.Orientation.up
346+
}
347+
}
348+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
import UIKit
12
import Foundation
23
import AVFoundation
34

45
@objc(NSCameraViewPhotoDelegate)
56
public protocol NSCameraViewPhotoDelegate: AnyObject {
67
func cameraView(_ cameraView: NSCameraView, didCapturePhotoWithConfiguration photoConfiguration: NSCameraViewPhotoConfiguration)
7-
func cameraView(_ cameraView: NSCameraView, didFinishProcessingPhoto photo: AVCapturePhoto, photoDict: [String : Any]?, photoConfiguration: NSCameraViewPhotoConfiguration)
8+
func cameraView(_ cameraView: NSCameraView, didFinishProcessingPhoto photo: UIImage, photoDict: [String : Any]?, photoConfiguration: NSCameraViewPhotoConfiguration)
89
}

src/ui-cameraview/index.ios.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@ class NSCameraViewVideoDelegateImpl extends NSObject implements NSCameraViewVide
3535
@NativeClass
3636
class NSCameraViewPhotoDelegateImpl extends NSObject implements NSCameraViewPhotoDelegate {
3737
cameraViewDidCapturePhotoWithConfiguration(cameraView: NSCameraView, photoConfiguration: any): void {}
38-
cameraViewDidFinishProcessingPhotoPhotoDictPhotoConfiguration(
39-
cameraView: NSCameraView,
40-
photo: AVCapturePhoto,
41-
photoDict: NSDictionary<string, any>,
42-
photoConfiguration: NSCameraViewPhotoConfiguration
43-
) {
44-
this._owner?.get()?.cameraViewDidFinishProcessingPhotoPhotoDictPhotoConfiguration(photo, photoDict);
38+
cameraViewDidFinishProcessingPhotoPhotoDictPhotoConfiguration(cameraView: NSCameraView, photo: UIImage, photoDict: NSDictionary<string, any>, photoConfiguration: NSCameraViewPhotoConfiguration) {
39+
// TODO: move this to swift
40+
const size: CGSize = photo.size;
41+
UIGraphicsBeginImageContextWithOptions(size, false, photo.scale);
42+
photo.drawInRect(CGRectMake(0, 0, size.width, size.height));
43+
const resizedImage = UIGraphicsGetImageFromCurrentImageContext();
44+
UIGraphicsEndImageContext();
45+
this._owner?.get()?.cameraViewDidFinishProcessingPhotoPhotoDictPhotoConfiguration(resizedImage, photoDict);
4546
}
4647

4748
_owner: WeakRef<CameraView>;
@@ -55,11 +56,11 @@ class NSCameraViewPhotoDelegateImpl extends NSObject implements NSCameraViewPhot
5556
}
5657

5758
export class CameraView extends CameraViewBase {
58-
cameraViewDidFinishProcessingPhotoPhotoDictPhotoConfiguration(photo: AVCapturePhoto, photoDict: any) {
59-
const cgImage = photo.CGImageRepresentation();
60-
const orientation = photo.metadata.objectForKey(kCGImagePropertyOrientation);
61-
const image = UIImage.imageWithCGImageScaleOrientation(cgImage, 1, orientation);
62-
this.photoCaptureListener.forEach((c) => c(image, photoDict));
59+
cameraViewDidFinishProcessingPhotoPhotoDictPhotoConfiguration(photo: UIImage, photoDict: any) {
60+
// const cgImage = photo.CGImageRepresentation();
61+
// const orientation = photo.metadata.objectForKey(kCGImagePropertyOrientation);
62+
// const image = UIImage.imageWithCGImageScaleOrientation(cgImage, 1, orientation);
63+
this.photoCaptureListener.forEach((c) => c(photo, photoDict));
6364
}
6465
cameraViewDidProcessPhotoCaptureWithPhotoConfiguration(photoDict: any) {}
6566
videoCaptureListener = new Set<Function>();

src/ui-cameraview/references.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
/// <reference path="../../node_modules/@nativescript/types-ios/lib/ios/objc-x86_64/objc!ObjectiveC.d.ts" />
2+
/// <reference path="../../node_modules/@nativescript/types-ios/lib/ios/objc-x86_64/objc!Foundation.d.ts" />
3+
/// <reference path="../../node_modules/@nativescript/types-ios/lib/ios/objc-x86_64/objc!CoreFoundation.d.ts" />
14
/// <reference path="../../node_modules/@nativescript/types-ios/lib/ios/objc-x86_64/objc!AVFoundation.d.ts" />
25
/// <reference path="../../node_modules/@nativescript/types-ios/lib/ios/objc-x86_64/objc!ImageIO.d.ts" />
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
declare class NextLevel
2+
extends NSObject
3+
implements
4+
AVCaptureAudioDataOutputSampleBufferDelegate,
5+
AVCaptureFileOutputRecordingDelegate,
6+
AVCaptureMetadataOutputObjectsDelegate,
7+
AVCapturePhotoCaptureDelegate,
8+
AVCaptureVideoDataOutputSampleBufferDelegate
9+
{
10+
static alloc(): NextLevel; // inherited from NSObject
11+
12+
static new(): NextLevel; // inherited from NSObject
13+
14+
readonly debugDescription: string; // inherited from NSObjectProtocol
15+
16+
readonly description: string; // inherited from NSObjectProtocol
17+
18+
readonly hash: number; // inherited from NSObjectProtocol
19+
20+
readonly isProxy: boolean; // inherited from NSObjectProtocol
21+
22+
readonly superclass: typeof NSObject; // inherited from NSObjectProtocol
23+
24+
readonly; // inherited from NSObjectProtocol
25+
26+
captureOutputDidCapturePhotoForResolvedSettings(output: AVCapturePhotoOutput, resolvedSettings: AVCaptureResolvedPhotoSettings): void;
27+
28+
captureOutputDidDropSampleBufferFromConnection(output: AVCaptureOutput, sampleBuffer: any, connection: AVCaptureConnection): void;
29+
30+
captureOutputDidFinishCaptureForResolvedSettingsError(output: AVCapturePhotoOutput, resolvedSettings: AVCaptureResolvedPhotoSettings, error: NSError): void;
31+
32+
captureOutputDidFinishProcessingLivePhotoToMovieFileAtURLDurationPhotoDisplayTimeResolvedSettingsError(
33+
output: AVCapturePhotoOutput,
34+
outputFileURL: NSURL,
35+
duration: CMTime,
36+
photoDisplayTime: CMTime,
37+
resolvedSettings: AVCaptureResolvedPhotoSettings,
38+
error: NSError
39+
): void;
40+
41+
captureOutputDidFinishProcessingPhotoError(output: AVCapturePhotoOutput, photo: AVCapturePhoto, error: NSError): void;
42+
43+
captureOutputDidFinishProcessingPhotoSampleBufferPreviewPhotoSampleBufferResolvedSettingsBracketSettingsError(
44+
output: AVCapturePhotoOutput,
45+
photoSampleBuffer: any,
46+
previewPhotoSampleBuffer: any,
47+
resolvedSettings: AVCaptureResolvedPhotoSettings,
48+
bracketSettings: AVCaptureBracketedStillImageSettings,
49+
error: NSError
50+
): void;
51+
52+
captureOutputDidFinishProcessingRawPhotoSampleBufferPreviewPhotoSampleBufferResolvedSettingsBracketSettingsError(
53+
output: AVCapturePhotoOutput,
54+
rawSampleBuffer: any,
55+
previewPhotoSampleBuffer: any,
56+
resolvedSettings: AVCaptureResolvedPhotoSettings,
57+
bracketSettings: AVCaptureBracketedStillImageSettings,
58+
error: NSError
59+
): void;
60+
61+
captureOutputDidFinishRecordingLivePhotoMovieForEventualFileAtURLResolvedSettings(output: AVCapturePhotoOutput, outputFileURL: NSURL, resolvedSettings: AVCaptureResolvedPhotoSettings): void;
62+
63+
captureOutputDidFinishRecordingToOutputFileAtURLFromConnectionsError(
64+
output: AVCaptureFileOutput,
65+
outputFileURL: NSURL,
66+
connections: NSArray<AVCaptureConnection> | AVCaptureConnection[],
67+
error: NSError
68+
): void;
69+
70+
captureOutputDidOutputMetadataObjectsFromConnection(output: AVCaptureMetadataOutput, metadataObjects: NSArray<AVMetadataObject> | AVMetadataObject[], connection: AVCaptureConnection): void;
71+
72+
captureOutputDidOutputSampleBufferFromConnection(output: AVCaptureOutput, sampleBuffer: any, connection: AVCaptureConnection): void;
73+
74+
captureOutputDidStartRecordingToOutputFileAtURLFromConnections(output: AVCaptureFileOutput, fileURL: NSURL, connections: NSArray<AVCaptureConnection> | AVCaptureConnection[]): void;
75+
76+
captureOutputWillBeginCaptureForResolvedSettings(output: AVCapturePhotoOutput, resolvedSettings: AVCaptureResolvedPhotoSettings): void;
77+
78+
captureOutputWillCapturePhotoForResolvedSettings(output: AVCapturePhotoOutput, resolvedSettings: AVCaptureResolvedPhotoSettings): void;
79+
80+
class(): typeof NSObject;
81+
82+
conformsToProtocol(aProtocol: any /* Protocol */): boolean;
83+
84+
handleSessionInterruptionEnded(notification: NSNotification): void;
85+
86+
handleSessionWasInterrupted(notification: NSNotification): void;
87+
88+
isEqual(object: any): boolean;
89+
90+
isKindOfClass(aClass: typeof NSObject): boolean;
91+
92+
isMemberOfClass(aClass: typeof NSObject): boolean;
93+
94+
performSelector(aSelector: string): any;
95+
96+
performSelectorWithObject(aSelector: string, object: any): any;
97+
98+
performSelectorWithObjectWithObject(aSelector: string, object1: any, object2: any): any;
99+
100+
respondsToSelector(aSelector: string): boolean;
101+
102+
retainCount(): number;
103+
104+
self(): this;
105+
}
106+
107+
declare let NextLevelVersionNumber: number;
108+
109+
declare let NextLevelVersionString: interop.Reference<number>;

src/ui-cameraview/typings/ios.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ interface NSCameraViewPhotoDelegate {
7171

7272
cameraViewDidFinishProcessingPhotoPhotoDictPhotoConfiguration(
7373
cameraView: NSCameraView,
74-
photo: AVCapturePhoto,
74+
photo: UIImage,
7575
photoDict: NSDictionary<string, any>,
7676
photoConfiguration: NSCameraViewPhotoConfiguration
7777
): void;

0 commit comments

Comments
 (0)