Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 1c00905

Browse files
authored
[camera_platform_interface] Add platform interface methods for setting auto exposure. (#3345)
* Added platform interface methods for setting auto exposure. * Added platform interface methods for setting auto exposure. * Remove workspace files
1 parent 3ec0d64 commit 1c00905

File tree

11 files changed

+494
-27
lines changed

11 files changed

+494
-27
lines changed

packages/camera/camera_platform_interface/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.2.0
2+
3+
- Added interface to support automatic exposure.
4+
15
## 1.1.0
26

37
- Added an optional `maxVideoDuration` parameter to the `startVideoRecording` method, which allows implementations to limit the duration of a video recording.

packages/camera/camera_platform_interface/lib/src/events/camera_event.dart

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import '../../camera_platform_interface.dart';
6+
57
/// Generic Event coming from the native side of Camera.
68
///
79
/// All [CameraEvent]s contain the `cameraId` that originated the event. This
@@ -45,6 +47,12 @@ class CameraInitializedEvent extends CameraEvent {
4547
/// The height of the preview in pixels.
4648
final double previewHeight;
4749

50+
/// The default exposure mode
51+
final ExposureMode exposureMode;
52+
53+
/// Whether setting exposure points is supported.
54+
final bool exposurePointSupported;
55+
4856
/// Build a CameraInitialized event triggered from the camera represented by
4957
/// `cameraId`.
5058
///
@@ -54,13 +62,17 @@ class CameraInitializedEvent extends CameraEvent {
5462
int cameraId,
5563
this.previewWidth,
5664
this.previewHeight,
65+
this.exposureMode,
66+
this.exposurePointSupported,
5767
) : super(cameraId);
5868

5969
/// Converts the supplied [Map] to an instance of the [CameraInitializedEvent]
6070
/// class.
6171
CameraInitializedEvent.fromJson(Map<String, dynamic> json)
6272
: previewWidth = json['previewWidth'],
6373
previewHeight = json['previewHeight'],
74+
exposureMode = deserializeExposureMode(json['exposureMode']),
75+
exposurePointSupported = json['exposurePointSupported'],
6476
super(json['cameraId']);
6577

6678
/// Converts the [CameraInitializedEvent] instance into a [Map] instance that
@@ -69,6 +81,8 @@ class CameraInitializedEvent extends CameraEvent {
6981
'cameraId': cameraId,
7082
'previewWidth': previewWidth,
7183
'previewHeight': previewHeight,
84+
'exposureMode': serializeExposureMode(exposureMode),
85+
'exposurePointSupported': exposurePointSupported,
7286
};
7387

7488
@override
@@ -78,11 +92,17 @@ class CameraInitializedEvent extends CameraEvent {
7892
other is CameraInitializedEvent &&
7993
runtimeType == other.runtimeType &&
8094
previewWidth == other.previewWidth &&
81-
previewHeight == other.previewHeight;
95+
previewHeight == other.previewHeight &&
96+
exposureMode == other.exposureMode &&
97+
exposurePointSupported == other.exposurePointSupported;
8298

8399
@override
84100
int get hashCode =>
85-
super.hashCode ^ previewWidth.hashCode ^ previewHeight.hashCode;
101+
super.hashCode ^
102+
previewWidth.hashCode ^
103+
previewHeight.hashCode ^
104+
exposureMode.hashCode ^
105+
exposurePointSupported.hashCode;
86106
}
87107

88108
/// An event fired when the resolution preset of the camera has changed.

packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// found in the LICENSE file.
44

55
import 'dart:async';
6+
import 'dart:math';
67

78
import 'package:camera_platform_interface/camera_platform_interface.dart';
89
import 'package:camera_platform_interface/src/utils/utils.dart';
@@ -189,6 +190,62 @@ class MethodChannelCamera extends CameraPlatform {
189190
},
190191
);
191192

193+
@override
194+
Future<void> setExposureMode(int cameraId, ExposureMode mode) =>
195+
_channel.invokeMethod<void>(
196+
'setExposureMode',
197+
<String, dynamic>{
198+
'cameraId': cameraId,
199+
'mode': serializeExposureMode(mode),
200+
},
201+
);
202+
203+
@override
204+
Future<void> setExposurePoint(int cameraId, Point<double> point) {
205+
assert(point == null || point.x >= 0 && point.x <= 1);
206+
assert(point == null || point.y >= 0 && point.y <= 1);
207+
return _channel.invokeMethod<void>(
208+
'setExposurePoint',
209+
<String, dynamic>{
210+
'cameraId': cameraId,
211+
'reset': point == null,
212+
'x': point?.x,
213+
'y': point?.y,
214+
},
215+
);
216+
}
217+
218+
@override
219+
Future<double> getMinExposureOffset(int cameraId) =>
220+
_channel.invokeMethod<double>(
221+
'getMinExposureOffset',
222+
<String, dynamic>{'cameraId': cameraId},
223+
);
224+
225+
@override
226+
Future<double> getMaxExposureOffset(int cameraId) =>
227+
_channel.invokeMethod<double>(
228+
'getMaxExposureOffset',
229+
<String, dynamic>{'cameraId': cameraId},
230+
);
231+
232+
@override
233+
Future<double> getExposureOffsetStepSize(int cameraId) =>
234+
_channel.invokeMethod<double>(
235+
'getExposureOffsetStepSize',
236+
<String, dynamic>{'cameraId': cameraId},
237+
);
238+
239+
@override
240+
Future<double> setExposureOffset(int cameraId, double offset) =>
241+
_channel.invokeMethod<double>(
242+
'setExposureOffset',
243+
<String, dynamic>{
244+
'cameraId': cameraId,
245+
'offset': offset,
246+
},
247+
);
248+
192249
@override
193250
Future<double> getMaxZoomLevel(int cameraId) => _channel.invokeMethod<double>(
194251
'getMaxZoomLevel',
@@ -269,6 +326,8 @@ class MethodChannelCamera extends CameraPlatform {
269326
cameraId,
270327
call.arguments['previewWidth'],
271328
call.arguments['previewHeight'],
329+
deserializeExposureMode(call.arguments['exposureMode']),
330+
call.arguments['exposurePointSupported'],
272331
));
273332
break;
274333
case 'resolution_changed':

packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
// found in the LICENSE file.
44

55
import 'dart:async';
6+
import 'dart:math';
67

78
import 'package:camera_platform_interface/camera_platform_interface.dart';
89
import 'package:camera_platform_interface/src/method_channel/method_channel_camera.dart';
10+
import 'package:camera_platform_interface/src/types/exposure_mode.dart';
911
import 'package:cross_file/cross_file.dart';
1012
import 'package:flutter/widgets.dart';
1113
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
@@ -116,6 +118,48 @@ abstract class CameraPlatform extends PlatformInterface {
116118
throw UnimplementedError('setFlashMode() is not implemented.');
117119
}
118120

121+
/// Sets the exposure mode for taking pictures.
122+
Future<void> setExposureMode(int cameraId, ExposureMode mode) {
123+
throw UnimplementedError('setExposureMode() is not implemented.');
124+
}
125+
126+
/// Sets the exposure point for automatically determining the exposure value.
127+
Future<void> setExposurePoint(int cameraId, Point<double> point) {
128+
throw UnimplementedError('setExposurePoint() is not implemented.');
129+
}
130+
131+
/// Gets the minimum supported exposure offset for the selected camera in EV units.
132+
Future<double> getMinExposureOffset(int cameraId) {
133+
throw UnimplementedError('getMinExposureOffset() is not implemented.');
134+
}
135+
136+
/// Gets the maximum supported exposure offset for the selected camera in EV units.
137+
Future<double> getMaxExposureOffset(int cameraId) {
138+
throw UnimplementedError('getMaxExposureOffset() is not implemented.');
139+
}
140+
141+
/// Gets the supported step size for exposure offset for the selected camera in EV units.
142+
///
143+
/// Returns 0 when the camera supports using a free value without stepping.
144+
Future<double> getExposureOffsetStepSize(int cameraId) {
145+
throw UnimplementedError('getMinExposureOffset() is not implemented.');
146+
}
147+
148+
/// Sets the exposure offset for the selected camera.
149+
///
150+
/// The supplied [offset] value should be in EV units. 1 EV unit represents a
151+
/// doubling in brightness. It should be between the minimum and maximum offsets
152+
/// obtained through `getMinExposureOffset` and `getMaxExposureOffset` respectively.
153+
/// Throws a `CameraException` when an illegal offset is supplied.
154+
///
155+
/// When the supplied [offset] value does not align with the step size obtained
156+
/// through `getExposureStepSize`, it will automatically be rounded to the nearest step.
157+
///
158+
/// Returns the (rounded) offset value that was set.
159+
Future<double> setExposureOffset(int cameraId, double offset) {
160+
throw UnimplementedError('setExposureOffset() is not implemented.');
161+
}
162+
119163
/// Gets the maximum supported zoom level for the selected camera.
120164
Future<double> getMaxZoomLevel(int cameraId) {
121165
throw UnimplementedError('getMaxZoomLevel() is not implemented.');
@@ -129,7 +173,7 @@ abstract class CameraPlatform extends PlatformInterface {
129173
/// Set the zoom level for the selected camera.
130174
///
131175
/// The supplied [zoom] value should be between 1.0 and the maximum supported
132-
/// zoom level returned by the `getMaxZoomLevel`. Throws an `CameraException`
176+
/// zoom level returned by the `getMaxZoomLevel`. Throws a `CameraException`
133177
/// when an illegal zoom level is supplied.
134178
Future<void> setZoomLevel(int cameraId, double zoom) {
135179
throw UnimplementedError('setZoomLevel() is not implemented.');
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2019 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
/// The possible exposure modes that can be set for a camera.
6+
enum ExposureMode {
7+
/// Automatically determine exposure settings.
8+
auto,
9+
10+
/// Lock the currently determined exposure settings.
11+
locked,
12+
}
13+
14+
/// Returns the exposure mode as a String.
15+
String serializeExposureMode(ExposureMode exposureMode) {
16+
switch (exposureMode) {
17+
case ExposureMode.locked:
18+
return 'locked';
19+
case ExposureMode.auto:
20+
return 'auto';
21+
default:
22+
throw ArgumentError('Unknown ExposureMode value');
23+
}
24+
}
25+
26+
/// Returns the exposure mode for a given String.
27+
ExposureMode deserializeExposureMode(String str) {
28+
switch (str) {
29+
case "locked":
30+
return ExposureMode.locked;
31+
case "auto":
32+
return ExposureMode.auto;
33+
default:
34+
throw ArgumentError('"$str" is not a valid ExposureMode value');
35+
}
36+
}

packages/camera/camera_platform_interface/lib/src/types/types.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export 'camera_description.dart';
66
export 'resolution_preset.dart';
77
export 'camera_exception.dart';
88
export 'flash_mode.dart';
9+
export 'exposure_mode.dart';

packages/camera/camera_platform_interface/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: A common platform interface for the camera plugin.
33
homepage: https://github.com/flutter/plugins/tree/master/packages/camera/camera_platform_interface
44
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
55
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
6-
version: 1.1.0
6+
version: 1.2.0
77

88
dependencies:
99
flutter:

packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,84 @@ void main() {
186186
);
187187
});
188188

189+
test(
190+
'Default implementation of setExposureMode() should throw unimplemented error',
191+
() {
192+
// Arrange
193+
final cameraPlatform = ExtendsCameraPlatform();
194+
195+
// Act & Assert
196+
expect(
197+
() => cameraPlatform.setExposureMode(1, null),
198+
throwsUnimplementedError,
199+
);
200+
});
201+
202+
test(
203+
'Default implementation of setExposurePoint() should throw unimplemented error',
204+
() {
205+
// Arrange
206+
final cameraPlatform = ExtendsCameraPlatform();
207+
208+
// Act & Assert
209+
expect(
210+
() => cameraPlatform.setExposurePoint(1, null),
211+
throwsUnimplementedError,
212+
);
213+
});
214+
215+
test(
216+
'Default implementation of getMinExposureOffset() should throw unimplemented error',
217+
() {
218+
// Arrange
219+
final cameraPlatform = ExtendsCameraPlatform();
220+
221+
// Act & Assert
222+
expect(
223+
() => cameraPlatform.getMinExposureOffset(1),
224+
throwsUnimplementedError,
225+
);
226+
});
227+
228+
test(
229+
'Default implementation of getMaxExposureOffset() should throw unimplemented error',
230+
() {
231+
// Arrange
232+
final cameraPlatform = ExtendsCameraPlatform();
233+
234+
// Act & Assert
235+
expect(
236+
() => cameraPlatform.getMaxExposureOffset(1),
237+
throwsUnimplementedError,
238+
);
239+
});
240+
241+
test(
242+
'Default implementation of getExposureOffsetStepSize() should throw unimplemented error',
243+
() {
244+
// Arrange
245+
final cameraPlatform = ExtendsCameraPlatform();
246+
247+
// Act & Assert
248+
expect(
249+
() => cameraPlatform.getExposureOffsetStepSize(1),
250+
throwsUnimplementedError,
251+
);
252+
});
253+
254+
test(
255+
'Default implementation of setExposureOffset() should throw unimplemented error',
256+
() {
257+
// Arrange
258+
final cameraPlatform = ExtendsCameraPlatform();
259+
260+
// Act & Assert
261+
expect(
262+
() => cameraPlatform.setExposureOffset(1, null),
263+
throwsUnimplementedError,
264+
);
265+
});
266+
189267
test(
190268
'Default implementation of startVideoRecording() should throw unimplemented error',
191269
() {

0 commit comments

Comments
 (0)