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

[camera_platform_interface] Add platform interface methods for setting auto exposure. #3345

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/camera/camera_platform_interface/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.2.0

- Added interface to support automatic exposure.

## 1.1.0

- Added an optional `maxVideoDuration` parameter to the `startVideoRecording` method, which allows implementations to limit the duration of a video recording.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import '../../camera_platform_interface.dart';

/// Generic Event coming from the native side of Camera.
///
/// All [CameraEvent]s contain the `cameraId` that originated the event. This
Expand Down Expand Up @@ -45,6 +47,12 @@ class CameraInitializedEvent extends CameraEvent {
/// The height of the preview in pixels.
final double previewHeight;

/// The default exposure mode
final ExposureMode exposureMode;

/// Whether setting exposure points is supported.
final bool exposurePointSupported;

/// Build a CameraInitialized event triggered from the camera represented by
/// `cameraId`.
///
Expand All @@ -54,13 +62,17 @@ class CameraInitializedEvent extends CameraEvent {
int cameraId,
this.previewWidth,
this.previewHeight,
this.exposureMode,
this.exposurePointSupported,
) : super(cameraId);

/// Converts the supplied [Map] to an instance of the [CameraInitializedEvent]
/// class.
CameraInitializedEvent.fromJson(Map<String, dynamic> json)
: previewWidth = json['previewWidth'],
previewHeight = json['previewHeight'],
exposureMode = deserializeExposureMode(json['exposureMode']),
exposurePointSupported = json['exposurePointSupported'],
super(json['cameraId']);

/// Converts the [CameraInitializedEvent] instance into a [Map] instance that
Expand All @@ -69,6 +81,8 @@ class CameraInitializedEvent extends CameraEvent {
'cameraId': cameraId,
'previewWidth': previewWidth,
'previewHeight': previewHeight,
'exposureMode': serializeExposureMode(exposureMode),
'exposurePointSupported': exposurePointSupported,
};

@override
Expand All @@ -78,11 +92,17 @@ class CameraInitializedEvent extends CameraEvent {
other is CameraInitializedEvent &&
runtimeType == other.runtimeType &&
previewWidth == other.previewWidth &&
previewHeight == other.previewHeight;
previewHeight == other.previewHeight &&
exposureMode == other.exposureMode &&
exposurePointSupported == other.exposurePointSupported;

@override
int get hashCode =>
super.hashCode ^ previewWidth.hashCode ^ previewHeight.hashCode;
super.hashCode ^
previewWidth.hashCode ^
previewHeight.hashCode ^
exposureMode.hashCode ^
exposurePointSupported.hashCode;
}

/// An event fired when the resolution preset of the camera has changed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

import 'dart:async';
import 'dart:math';

import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:camera_platform_interface/src/utils/utils.dart';
Expand Down Expand Up @@ -189,6 +190,62 @@ class MethodChannelCamera extends CameraPlatform {
},
);

@override
Future<void> setExposureMode(int cameraId, ExposureMode mode) =>
_channel.invokeMethod<void>(
'setExposureMode',
<String, dynamic>{
'cameraId': cameraId,
'mode': serializeExposureMode(mode),
},
);

@override
Future<void> setExposurePoint(int cameraId, Point<double> point) {
assert(point == null || point.x >= 0 && point.x <= 1);
assert(point == null || point.y >= 0 && point.y <= 1);
return _channel.invokeMethod<void>(
'setExposurePoint',
<String, dynamic>{
'cameraId': cameraId,
'reset': point == null,
'x': point?.x,
'y': point?.y,
},
);
}

@override
Future<double> getMinExposureOffset(int cameraId) =>
_channel.invokeMethod<double>(
'getMinExposureOffset',
<String, dynamic>{'cameraId': cameraId},
);

@override
Future<double> getMaxExposureOffset(int cameraId) =>
_channel.invokeMethod<double>(
'getMaxExposureOffset',
<String, dynamic>{'cameraId': cameraId},
);

@override
Future<double> getExposureOffsetStepSize(int cameraId) =>
_channel.invokeMethod<double>(
'getExposureOffsetStepSize',
<String, dynamic>{'cameraId': cameraId},
);

@override
Future<double> setExposureOffset(int cameraId, double offset) =>
_channel.invokeMethod<double>(
'setExposureOffset',
<String, dynamic>{
'cameraId': cameraId,
'offset': offset,
},
);

@override
Future<double> getMaxZoomLevel(int cameraId) => _channel.invokeMethod<double>(
'getMaxZoomLevel',
Expand Down Expand Up @@ -269,6 +326,8 @@ class MethodChannelCamera extends CameraPlatform {
cameraId,
call.arguments['previewWidth'],
call.arguments['previewHeight'],
deserializeExposureMode(call.arguments['exposureMode']),
call.arguments['exposurePointSupported'],
));
break;
case 'resolution_changed':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
// found in the LICENSE file.

import 'dart:async';
import 'dart:math';

import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:camera_platform_interface/src/method_channel/method_channel_camera.dart';
import 'package:camera_platform_interface/src/types/exposure_mode.dart';
import 'package:cross_file/cross_file.dart';
import 'package:flutter/widgets.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
Expand Down Expand Up @@ -116,6 +118,48 @@ abstract class CameraPlatform extends PlatformInterface {
throw UnimplementedError('setFlashMode() is not implemented.');
}

/// Sets the exposure mode for taking pictures.
Future<void> setExposureMode(int cameraId, ExposureMode mode) {
throw UnimplementedError('setExposureMode() is not implemented.');
}

/// Sets the exposure point for automatically determining the exposure value.
Future<void> setExposurePoint(int cameraId, Point<double> point) {
throw UnimplementedError('setExposurePoint() is not implemented.');
}

/// Gets the minimum supported exposure offset for the selected camera in EV units.
Future<double> getMinExposureOffset(int cameraId) {
throw UnimplementedError('getMinExposureOffset() is not implemented.');
}

/// Gets the maximum supported exposure offset for the selected camera in EV units.
Future<double> getMaxExposureOffset(int cameraId) {
throw UnimplementedError('getMaxExposureOffset() is not implemented.');
}

/// Gets the supported step size for exposure offset for the selected camera in EV units.
///
/// Returns 0 when the camera supports using a free value without stepping.
Future<double> getExposureOffsetStepSize(int cameraId) {
throw UnimplementedError('getMinExposureOffset() is not implemented.');
}

/// Sets the exposure offset for the selected camera.
///
/// The supplied [offset] value should be in EV units. 1 EV unit represents a
/// doubling in brightness. It should be between the minimum and maximum offsets
/// obtained through `getMinExposureOffset` and `getMaxExposureOffset` respectively.
/// Throws a `CameraException` when an illegal offset is supplied.
///
/// When the supplied [offset] value does not align with the step size obtained
/// through `getExposureStepSize`, it will automatically be rounded to the nearest step.
///
/// Returns the (rounded) offset value that was set.
Future<double> setExposureOffset(int cameraId, double offset) {
throw UnimplementedError('setExposureOffset() is not implemented.');
}

/// Gets the maximum supported zoom level for the selected camera.
Future<double> getMaxZoomLevel(int cameraId) {
throw UnimplementedError('getMaxZoomLevel() is not implemented.');
Expand All @@ -129,7 +173,7 @@ abstract class CameraPlatform extends PlatformInterface {
/// Set the zoom level for the selected camera.
///
/// The supplied [zoom] value should be between 1.0 and the maximum supported
/// zoom level returned by the `getMaxZoomLevel`. Throws an `CameraException`
/// zoom level returned by the `getMaxZoomLevel`. Throws a `CameraException`
/// when an illegal zoom level is supplied.
Future<void> setZoomLevel(int cameraId, double zoom) {
throw UnimplementedError('setZoomLevel() is not implemented.');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// The possible exposure modes that can be set for a camera.
enum ExposureMode {
/// Automatically determine exposure settings.
auto,

/// Lock the currently determined exposure settings.
locked,
}

/// Returns the exposure mode as a String.
String serializeExposureMode(ExposureMode exposureMode) {
switch (exposureMode) {
case ExposureMode.locked:
return 'locked';
case ExposureMode.auto:
return 'auto';
default:
throw ArgumentError('Unknown ExposureMode value');
}
}

/// Returns the exposure mode for a given String.
ExposureMode deserializeExposureMode(String str) {
switch (str) {
case "locked":
return ExposureMode.locked;
case "auto":
return ExposureMode.auto;
default:
throw ArgumentError('"$str" is not a valid ExposureMode value');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export 'camera_description.dart';
export 'resolution_preset.dart';
export 'camera_exception.dart';
export 'flash_mode.dart';
export 'exposure_mode.dart';
2 changes: 1 addition & 1 deletion packages/camera/camera_platform_interface/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: A common platform interface for the camera plugin.
homepage: https://github.com/flutter/plugins/tree/master/packages/camera/camera_platform_interface
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
version: 1.1.0
version: 1.2.0

dependencies:
flutter:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,84 @@ void main() {
);
});

test(
'Default implementation of setExposureMode() should throw unimplemented error',
() {
// Arrange
final cameraPlatform = ExtendsCameraPlatform();

// Act & Assert
expect(
() => cameraPlatform.setExposureMode(1, null),
throwsUnimplementedError,
);
});

test(
'Default implementation of setExposurePoint() should throw unimplemented error',
() {
// Arrange
final cameraPlatform = ExtendsCameraPlatform();

// Act & Assert
expect(
() => cameraPlatform.setExposurePoint(1, null),
throwsUnimplementedError,
);
});

test(
'Default implementation of getMinExposureOffset() should throw unimplemented error',
() {
// Arrange
final cameraPlatform = ExtendsCameraPlatform();

// Act & Assert
expect(
() => cameraPlatform.getMinExposureOffset(1),
throwsUnimplementedError,
);
});

test(
'Default implementation of getMaxExposureOffset() should throw unimplemented error',
() {
// Arrange
final cameraPlatform = ExtendsCameraPlatform();

// Act & Assert
expect(
() => cameraPlatform.getMaxExposureOffset(1),
throwsUnimplementedError,
);
});

test(
'Default implementation of getExposureOffsetStepSize() should throw unimplemented error',
() {
// Arrange
final cameraPlatform = ExtendsCameraPlatform();

// Act & Assert
expect(
() => cameraPlatform.getExposureOffsetStepSize(1),
throwsUnimplementedError,
);
});

test(
'Default implementation of setExposureOffset() should throw unimplemented error',
() {
// Arrange
final cameraPlatform = ExtendsCameraPlatform();

// Act & Assert
expect(
() => cameraPlatform.setExposureOffset(1, null),
throwsUnimplementedError,
);
});

test(
'Default implementation of startVideoRecording() should throw unimplemented error',
() {
Expand Down