From 89675f2aa28417b1d1bb5447147a8c25237dc27e Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Thu, 15 Jul 2021 10:16:09 +0200 Subject: [PATCH 1/3] Fix coordinate rotation for setting focus- and exposure points on iOS --- packages/camera/camera/CHANGELOG.md | 4 ++ .../ios/RunnerTests/CameraExposureTests.m | 57 +++++++++++++++++++ .../ios/RunnerTests/CameraFocusTests.m | 25 +++++++- .../example/ios/RunnerTests/CameraUtilTests.m | 54 ++++++++++++++++++ .../camera/camera/ios/Classes/CameraPlugin.m | 37 +++++++++++- packages/camera/camera/pubspec.yaml | 2 +- 6 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m create mode 100644 packages/camera/camera/example/ios/RunnerTests/CameraUtilTests.m diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 1f30104218e3..43fe276b3a0c 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.8.1+5 + +* Fixed setFocusPoint and setExposurePoint coordinates only being correct in a single orientation on iOS. + ## 0.8.1+4 * Silenced warnings that may occur during build when using a very diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m new file mode 100644 index 000000000000..bf02b3b1fdb7 --- /dev/null +++ b/packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m @@ -0,0 +1,57 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@import camera; +@import XCTest; +@import AVFoundation; +#import + +@interface FLTCam : NSObject + +- (void)setExposurePointWithResult:(FlutterResult)result x:(double)x y:(double)y; +@end + +@interface CameraExposureTests : XCTestCase +@property(readonly, nonatomic) FLTCam *camera; +@property(readonly, nonatomic) id mockDevice; +@property(readonly, nonatomic) id mockUIDevice; +@end + +@implementation CameraExposureTests + +- (void)setUp { + _camera = [[FLTCam alloc] init]; + _mockDevice = OCMClassMock([AVCaptureDevice class]); + _mockUIDevice = OCMPartialMock([UIDevice currentDevice]); +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the + // class. + [_mockDevice stopMocking]; + [_mockUIDevice stopMocking]; +} + +- (void)testSetExpsourePointWithResult_SetsExposurePointOfInterest { + // UI is currently in landscape left orientation + OCMStub([(UIDevice *)_mockUIDevice orientation]).andReturn(UIDeviceOrientationLandscapeLeft); + // Exposure point of interest is supported + OCMStub([_mockDevice isExposurePointOfInterestSupported]).andReturn(true); + // Set mock device as the current capture device + [_camera setValue:_mockDevice forKey:@"captureDevice"]; + + // Run test + [_camera + setExposurePointWithResult:^void(id _Nullable result) { + } + x:1 + y:1]; + + // Verify the focus point of interest has been set + OCMVerify([_mockDevice setExposurePointOfInterest:CGPointMake(1, 1)]); +} + +@end diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m index 5d93bdf70332..7cf6f573551e 100644 --- a/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m +++ b/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m @@ -19,12 +19,13 @@ @interface FLTCam : NSObject + +@interface FLTCam : NSObject + +- (CGPoint)getCGPointForCoordsWithOrientation:(UIDeviceOrientation)orientation + x:(double)x + y:(double)y; + +@end + +@interface CameraUtilTests : XCTestCase +@property(readonly, nonatomic) FLTCam *camera; + +@end + +@implementation CameraUtilTests + +- (void)setUp { + _camera = [[FLTCam alloc] init]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the + // class. +} + +- (void)testGetCGPointForCoordsWithOrientation_ShouldRotateCoords { + CGPoint point; + point = [_camera getCGPointForCoordsWithOrientation:UIDeviceOrientationLandscapeLeft x:1 y:1]; + XCTAssertTrue(CGPointEqualToPoint(point, CGPointMake(1, 1)), + @"Resulting coordinates are invalid."); + point = [_camera getCGPointForCoordsWithOrientation:UIDeviceOrientationPortrait x:0 y:1]; + XCTAssertTrue(CGPointEqualToPoint(point, CGPointMake(1, 1)), + @"Resulting coordinates are invalid."); + point = [_camera getCGPointForCoordsWithOrientation:UIDeviceOrientationLandscapeRight x:0 y:0]; + XCTAssertTrue(CGPointEqualToPoint(point, CGPointMake(1, 1)), + @"Resulting coordinates are invalid."); + point = [_camera getCGPointForCoordsWithOrientation:UIDeviceOrientationPortraitUpsideDown + x:1 + y:0]; + XCTAssertTrue(CGPointEqualToPoint(point, CGPointMake(1, 1)), + @"Resulting coordinates are invalid."); +} + +@end diff --git a/packages/camera/camera/ios/Classes/CameraPlugin.m b/packages/camera/camera/ios/Classes/CameraPlugin.m index ebd5366ba78d..d88eb45945fe 100644 --- a/packages/camera/camera/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera/ios/Classes/CameraPlugin.m @@ -1030,6 +1030,31 @@ - (void)applyFocusMode:(FocusMode)focusMode onDevice:(AVCaptureDevice *)captureD [captureDevice unlockForConfiguration]; } +- (CGPoint)getCGPointForCoordsWithOrientation:(UIDeviceOrientation)orientation + x:(double)x + y:(double)y { + double oldX = x, oldY = y; + switch (orientation) { + case UIDeviceOrientationPortrait: // 90 ccw + y = 1 - oldX; + x = oldY; + break; + case UIDeviceOrientationPortraitUpsideDown: // 90 cw + x = 1 - oldY; + y = oldX; + break; + case UIDeviceOrientationLandscapeRight: // 180 + x = 1 - x; + y = 1 - y; + break; + case UIDeviceOrientationLandscapeLeft: + default: + // No rotation required + break; + } + return CGPointMake(x, y); +} + - (void)setExposurePointWithResult:(FlutterResult)result x:(double)x y:(double)y { if (!_captureDevice.isExposurePointOfInterestSupported) { result([FlutterError errorWithCode:@"setExposurePointFailed" @@ -1037,8 +1062,11 @@ - (void)setExposurePointWithResult:(FlutterResult)result x:(double)x y:(double)y details:nil]); return; } + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; [_captureDevice lockForConfiguration:nil]; - [_captureDevice setExposurePointOfInterest:CGPointMake(y, 1 - x)]; + [_captureDevice setExposurePointOfInterest:[self getCGPointForCoordsWithOrientation:orientation + x:x + y:y]]; [_captureDevice unlockForConfiguration]; // Retrigger auto exposure [self applyExposureMode]; @@ -1052,11 +1080,16 @@ - (void)setFocusPointWithResult:(FlutterResult)result x:(double)x y:(double)y { details:nil]); return; } + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; [_captureDevice lockForConfiguration:nil]; - [_captureDevice setFocusPointOfInterest:CGPointMake(y, 1 - x)]; + + [_captureDevice setFocusPointOfInterest:[self getCGPointForCoordsWithOrientation:orientation + x:x + y:y]]; [_captureDevice unlockForConfiguration]; // Retrigger auto focus [self applyFocusMode]; + result(nil); } diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 789910e2c79b..78eb49a999a2 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter plugin for getting information about and controlling the and streaming image buffers to dart. repository: https://github.com/flutter/plugins/tree/master/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.8.1+4 +version: 0.8.1+5 environment: sdk: ">=2.12.0 <3.0.0" From 09a3f6adbe3a02e3b30f84ccd1919468587f5bbd Mon Sep 17 00:00:00 2001 From: Bodhi Mulders Date: Fri, 16 Jul 2021 10:11:03 +0200 Subject: [PATCH 2/3] Update packages/camera/camera/CHANGELOG.md Co-authored-by: Maurits van Beusekom --- packages/camera/camera/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 43fe276b3a0c..236cf96f027a 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.8.1+5 -* Fixed setFocusPoint and setExposurePoint coordinates only being correct in a single orientation on iOS. +* Make sure the `setFocusPoint` and `setExposurePoint` coordinates work correctly in all orientations on iOS (instead of only in portrait mode). ## 0.8.1+4 From 56ea3ac6689fddc3213862ebd6ac0ba5098a2896 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 16 Jul 2021 10:13:25 +0200 Subject: [PATCH 3/3] Fix PR feedback --- .../camera/example/ios/RunnerTests/CameraExposureTests.m | 2 -- .../camera/camera/example/ios/RunnerTests/CameraFocusTests.m | 2 -- .../camera/camera/example/ios/RunnerTests/CameraUtilTests.m | 5 ----- 3 files changed, 9 deletions(-) diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m index bf02b3b1fdb7..ee43d3f155f4 100644 --- a/packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m +++ b/packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m @@ -29,8 +29,6 @@ - (void)setUp { } - (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the - // class. [_mockDevice stopMocking]; [_mockUIDevice stopMocking]; } diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m index 7cf6f573551e..27537e7ebdac 100644 --- a/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m +++ b/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m @@ -37,8 +37,6 @@ - (void)setUp { } - (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the - // class. [_mockDevice stopMocking]; [_mockUIDevice stopMocking]; } diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraUtilTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraUtilTests.m index e57cbf78a84f..380f6e93de58 100644 --- a/packages/camera/camera/example/ios/RunnerTests/CameraUtilTests.m +++ b/packages/camera/camera/example/ios/RunnerTests/CameraUtilTests.m @@ -28,11 +28,6 @@ - (void)setUp { _camera = [[FLTCam alloc] init]; } -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the - // class. -} - - (void)testGetCGPointForCoordsWithOrientation_ShouldRotateCoords { CGPoint point; point = [_camera getCGPointForCoordsWithOrientation:UIDeviceOrientationLandscapeLeft x:1 y:1];