Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


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

* Adds `setJpegImageQuality` for controlling JPEG compression quality.

## 0.12.0+1

* Makes `Optional.of` constructor `const`.
Expand Down
5 changes: 5 additions & 0 deletions packages/camera/camera/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ dev_dependencies:

flutter:
uses-material-design: true
# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE.
# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins
dependency_overrides:
camera_android_camerax: {path: ../../../../packages/camera/camera_android_camerax}
camera_avfoundation: {path: ../../../../packages/camera/camera_avfoundation}
18 changes: 18 additions & 0 deletions packages/camera/camera/lib/src/camera_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,24 @@ class CameraController extends ValueNotifier<CameraValue> {
}
}

/// Sets the JPEG compression quality for still image capture.
///
/// The [quality] must be between 1 (lowest) and 100 (highest).
Future<void> setJpegImageQuality(int quality) async {
if (quality < 1 || quality > 100) {
throw ArgumentError.value(
quality,
'quality',
'Must be between 1 and 100.',
);
}
try {
await CameraPlatform.instance.setJpegImageQuality(_cameraId, quality);
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Check whether the camera platform supports image streaming.
bool supportsImageStreaming() =>
CameraPlatform.instance.supportsImageStreaming();
Expand Down
13 changes: 9 additions & 4 deletions packages/camera/camera/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing
Dart.
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
version: 0.12.0+1
version: 0.12.1

environment:
sdk: ^3.9.0
Expand All @@ -21,9 +21,9 @@ flutter:
default_package: camera_web

dependencies:
camera_android_camerax: ^0.7.0
camera_avfoundation: ^0.10.0
camera_platform_interface: ^2.12.0
camera_android_camerax: ^0.7.1
camera_avfoundation: ^0.10.1
camera_platform_interface: ^2.13.0
camera_web: ^0.3.3
flutter:
sdk: flutter
Expand All @@ -38,3 +38,8 @@ dev_dependencies:

topics:
- camera
# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE.
# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins
dependency_overrides:
camera_android_camerax: {path: ../../../packages/camera/camera_android_camerax}
camera_avfoundation: {path: ../../../packages/camera/camera_avfoundation}
3 changes: 3 additions & 0 deletions packages/camera/camera/test/camera_preview_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ class FakeController extends ValueNotifier<CameraValue>
Future<Iterable<VideoStabilizationMode>>
getSupportedVideoStabilizationModes() async => <VideoStabilizationMode>[];

@override
Future<void> setJpegImageQuality(int quality) async {}

@override
bool supportsImageStreaming() => true;
}
Expand Down
83 changes: 83 additions & 0 deletions packages/camera/camera/test/camera_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,83 @@ void main() {
},
);

test('setJpegImageQuality() calls CameraPlatform', () async {
final cameraController = CameraController(
const CameraDescription(
name: 'cam',
lensDirection: CameraLensDirection.back,
sensorOrientation: 90,
),
ResolutionPreset.max,
);
await cameraController.initialize();

await cameraController.setJpegImageQuality(50);

verify(
CameraPlatform.instance.setJpegImageQuality(cameraController.cameraId, 50),
).called(1);
});

test(
'setJpegImageQuality() throws CameraException on PlatformException',
() async {
final cameraController = CameraController(
const CameraDescription(
name: 'cam',
lensDirection: CameraLensDirection.back,
sensorOrientation: 90,
),
ResolutionPreset.max,
);
await cameraController.initialize();

when(
CameraPlatform.instance.setJpegImageQuality(
cameraController.cameraId,
50,
),
).thenThrow(
PlatformException(
code: 'TEST_ERROR',
message: 'This is a test error message',
),
);

expect(
cameraController.setJpegImageQuality(50),
throwsA(
isA<CameraException>().having(
(CameraException error) => error.description,
'TEST_ERROR',
'This is a test error message',
),
),
);
},
);

test('setJpegImageQuality() throws ArgumentError for invalid values', () async {
final cameraController = CameraController(
const CameraDescription(
name: 'cam',
lensDirection: CameraLensDirection.back,
sensorOrientation: 90,
),
ResolutionPreset.max,
);
await cameraController.initialize();

expect(
() => cameraController.setJpegImageQuality(0),
throwsA(isA<ArgumentError>()),
);
expect(
() => cameraController.setJpegImageQuality(101),
throwsA(isA<ArgumentError>()),
);
});

test('setExposureMode() calls $CameraPlatform', () async {
final cameraController = CameraController(
const CameraDescription(
Expand Down Expand Up @@ -4152,6 +4229,12 @@ class MockCameraPlatform extends Mock
) async => super.noSuchMethod(
Invocation.method(#setVideoStabilizationMode, <Object?>[cameraId, mode]),
);

@override
Future<void> setJpegImageQuality(int? cameraId, int? quality) async =>
super.noSuchMethod(
Invocation.method(#setJpegImageQuality, <Object?>[cameraId, quality]),
);
}

class MockCameraDescription extends CameraDescription {
Expand Down
4 changes: 4 additions & 0 deletions packages/camera/camera_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.10.11

* Adds `setJpegImageQuality` for controlling JPEG compression quality.

## 0.10.10+16

* Updates build files from Groovy to Kotlin.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import io.flutter.plugins.camera.features.flash.FlashMode;
import io.flutter.plugins.camera.features.focuspoint.FocusPointFeature;
import io.flutter.plugins.camera.features.fpsrange.FpsRangeFeature;
import io.flutter.plugins.camera.features.jpegquality.JpegQualityFeature;
import io.flutter.plugins.camera.features.resolution.ResolutionFeature;
import io.flutter.plugins.camera.features.resolution.ResolutionPreset;
import io.flutter.plugins.camera.features.sensororientation.DeviceOrientationManager;
Expand Down Expand Up @@ -1416,6 +1417,20 @@ public void setDescriptionWhileRecording(CameraProperties properties) {
}
}

/**
* Sets the JPEG compression quality for still image capture.
*
* @param quality JPEG quality value between 1 and 100.
*/
public void setJpegImageQuality(@NonNull Long quality) {
JpegQualityFeature jpegQualityFeature = cameraFeatures.getJpegQuality();
if (jpegQualityFeature == null) {
jpegQualityFeature = cameraFeatureFactory.createJpegQualityFeature(cameraProperties);
cameraFeatures.setJpegQuality(jpegQualityFeature);
}
jpegQualityFeature.setValue(quality.intValue());
}

public void dispose() {
Log.i(TAG, "dispose");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,11 @@ public void setDescriptionWhileRecording(@NonNull String cameraName) {
}
}

@Override
public void setJpegImageQuality(@NonNull Long quality) {
camera.setJpegImageQuality(quality);
}

@Override
public void dispose() {
if (camera != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,9 @@ void create(
*/
void setDescriptionWhileRecording(@NonNull String description);

/** Sets the JPEG compression quality for still image capture. */
void setJpegImageQuality(@NonNull Long quality);

/** The codec used by CameraApi. */
static @NonNull MessageCodec<Object> getCodec() {
return PigeonCodec.INSTANCE;
Expand Down Expand Up @@ -1809,6 +1812,31 @@ public void error(Throwable error) {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.camera_android.CameraApi.setJpegImageQuality"
+ messageChannelSuffix,
getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<>();
ArrayList<Object> args = (ArrayList<Object>) message;
Long qualityArg = (Long) args.get(0);
try {
api.setJpegImageQuality(qualityArg);
wrapped.add(0, null);
} catch (Throwable exception) {
wrapped = wrapError(exception);
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import io.flutter.plugins.camera.features.flash.FlashFeature;
import io.flutter.plugins.camera.features.focuspoint.FocusPointFeature;
import io.flutter.plugins.camera.features.fpsrange.FpsRangeFeature;
import io.flutter.plugins.camera.features.jpegquality.JpegQualityFeature;
import io.flutter.plugins.camera.features.noisereduction.NoiseReductionFeature;
import io.flutter.plugins.camera.features.resolution.ResolutionFeature;
import io.flutter.plugins.camera.features.resolution.ResolutionPreset;
Expand Down Expand Up @@ -157,4 +158,14 @@ ExposurePointFeature createExposurePointFeature(
*/
@NonNull
NoiseReductionFeature createNoiseReductionFeature(@NonNull CameraProperties cameraProperties);

/**
* Creates a new instance of the JPEG quality feature.
*
* @param cameraProperties instance of the CameraProperties class containing information about the
* cameras features.
* @return newly created instance of the JpegQualityFeature class.
*/
@NonNull
JpegQualityFeature createJpegQualityFeature(@NonNull CameraProperties cameraProperties);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import io.flutter.plugins.camera.features.flash.FlashFeature;
import io.flutter.plugins.camera.features.focuspoint.FocusPointFeature;
import io.flutter.plugins.camera.features.fpsrange.FpsRangeFeature;
import io.flutter.plugins.camera.features.jpegquality.JpegQualityFeature;
import io.flutter.plugins.camera.features.noisereduction.NoiseReductionFeature;
import io.flutter.plugins.camera.features.resolution.ResolutionFeature;
import io.flutter.plugins.camera.features.resolution.ResolutionPreset;
Expand Down Expand Up @@ -105,4 +106,10 @@ public NoiseReductionFeature createNoiseReductionFeature(
@NonNull CameraProperties cameraProperties) {
return new NoiseReductionFeature(cameraProperties);
}

@NonNull
@Override
public JpegQualityFeature createJpegQualityFeature(@NonNull CameraProperties cameraProperties) {
return new JpegQualityFeature(cameraProperties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import android.app.Activity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.plugins.camera.CameraProperties;
import io.flutter.plugins.camera.DartMessenger;
import io.flutter.plugins.camera.features.autofocus.AutoFocusFeature;
Expand All @@ -15,6 +16,7 @@
import io.flutter.plugins.camera.features.flash.FlashFeature;
import io.flutter.plugins.camera.features.focuspoint.FocusPointFeature;
import io.flutter.plugins.camera.features.fpsrange.FpsRangeFeature;
import io.flutter.plugins.camera.features.jpegquality.JpegQualityFeature;
import io.flutter.plugins.camera.features.noisereduction.NoiseReductionFeature;
import io.flutter.plugins.camera.features.resolution.ResolutionFeature;
import io.flutter.plugins.camera.features.resolution.ResolutionPreset;
Expand All @@ -41,6 +43,7 @@ public class CameraFeatures {
private static final String REGION_BOUNDARIES = "REGION_BOUNDARIES";
private static final String RESOLUTION = "RESOLUTION";
private static final String SENSOR_ORIENTATION = "SENSOR_ORIENTATION";
private static final String JPEG_QUALITY = "JPEG_QUALITY";
private static final String ZOOM_LEVEL = "ZOOM_LEVEL";

@NonNull
Expand Down Expand Up @@ -297,4 +300,23 @@ public ZoomLevelFeature getZoomLevel() {
public void setZoomLevel(@NonNull ZoomLevelFeature zoomLevel) {
this.featureMap.put(ZOOM_LEVEL, zoomLevel);
}

/**
* Gets the JPEG quality feature if it has been set.
*
* @return the JPEG quality feature, or null if not set.
*/
@Nullable
public JpegQualityFeature getJpegQuality() {
return (JpegQualityFeature) featureMap.get(JPEG_QUALITY);
}

/**
* Sets the instance of the JPEG quality feature.
*
* @param jpegQuality the {@link JpegQualityFeature} instance to set.
*/
public void setJpegQuality(@NonNull JpegQualityFeature jpegQuality) {
this.featureMap.put(JPEG_QUALITY, jpegQuality);
}
}
Loading