[camera_platform_interface] Added imageFormatGroup to initialize (#3364)

* Added imageFormatGroup to initialize

* Apply suggestions from code review

Co-authored-by: Maurits van Beusekom <maurits@vnbskm.nl>

* Added period to sentence

* Moved ImageFormatGroup to platform_interface; Added extension to convert ImageFormatGroup to name; Changed int to ImageFormatGroup for initializeCamera

* Fixed test

* Separated Android and iOS in name extension

* Clarified returns on name extension

* Export image_format_group.dart in types.dart

* Changed enum values to lowercase

* Added ImageFormatGroup test

* Fixed formatting

* Removed target platform switch.

* Fixed formatting

Co-authored-by: Maurits van Beusekom <maurits@vnbskm.nl>
diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md
index 8e31605..d264d6c 100644
--- a/packages/camera/camera_platform_interface/CHANGELOG.md
+++ b/packages/camera/camera_platform_interface/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.3.0
+
+- Introduces an option to set the image format when initializing.
+
 ## 1.2.0
 
 - Added interface to support automatic exposure.
diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart
index 6a73031..0ccc599 100644
--- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart
+++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart
@@ -6,6 +6,7 @@
 import 'dart:math';
 
 import 'package:camera_platform_interface/camera_platform_interface.dart';
+import 'package:camera_platform_interface/src/types/image_format_group.dart';
 import 'package:camera_platform_interface/src/utils/utils.dart';
 import 'package:cross_file/cross_file.dart';
 import 'package:flutter/services.dart';
@@ -76,7 +77,8 @@
   }
 
   @override
-  Future<void> initializeCamera(int cameraId) {
+  Future<void> initializeCamera(int cameraId,
+      {ImageFormatGroup imageFormatGroup}) {
     _channels.putIfAbsent(cameraId, () {
       final channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId');
       channel.setMethodCallHandler(
@@ -94,6 +96,7 @@
       'initialize',
       <String, dynamic>{
         'cameraId': cameraId,
+        'imageFormatGroup': imageFormatGroup.name(),
       },
     );
 
diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart
index c7a6032..d95d957 100644
--- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart
+++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart
@@ -8,6 +8,7 @@
 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:camera_platform_interface/src/types/image_format_group.dart';
 import 'package:cross_file/cross_file.dart';
 import 'package:flutter/widgets.dart';
 import 'package:plugin_platform_interface/plugin_platform_interface.dart';
@@ -54,7 +55,12 @@
   }
 
   /// Initializes the camera on the device.
-  Future<void> initializeCamera(int cameraId) {
+  ///
+  /// [imageFormatGroup] is used to specify the image formatting used.
+  /// On Android this defaults to ImageFormat.YUV_420_888 and applies only to the imageStream.
+  /// On iOS this defaults to kCVPixelFormatType_32BGRA.
+  Future<void> initializeCamera(int cameraId,
+      {ImageFormatGroup imageFormatGroup}) {
     throw UnimplementedError('initializeCamera() is not implemented.');
   }
 
diff --git a/packages/camera/camera_platform_interface/lib/src/types/image_format_group.dart b/packages/camera/camera_platform_interface/lib/src/types/image_format_group.dart
new file mode 100644
index 0000000..3d2c018
--- /dev/null
+++ b/packages/camera/camera_platform_interface/lib/src/types/image_format_group.dart
@@ -0,0 +1,50 @@
+/// Group of image formats that are comparable across Android and iOS platforms.
+enum ImageFormatGroup {
+  /// The image format does not fit into any specific group.
+  unknown,
+
+  /// Multi-plane YUV 420 format.
+  ///
+  /// This format is a generic YCbCr format, capable of describing any 4:2:0
+  /// chroma-subsampled planar or semiplanar buffer (but not fully interleaved),
+  /// with 8 bits per color sample.
+  ///
+  /// On Android, this is `android.graphics.ImageFormat.YUV_420_888`. See
+  /// https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888
+  ///
+  /// On iOS, this is `kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange`. See
+  /// https://developer.apple.com/documentation/corevideo/1563591-pixel_format_identifiers/kcvpixelformattype_420ypcbcr8biplanarvideorange?language=objc
+  yuv420,
+
+  /// 32-bit BGRA.
+  ///
+  /// On iOS, this is `kCVPixelFormatType_32BGRA`. See
+  /// https://developer.apple.com/documentation/corevideo/1563591-pixel_format_identifiers/kcvpixelformattype_32bgra?language=objc
+  bgra8888,
+
+  /// 32-big RGB image encoded into JPEG bytes.
+  ///
+  /// On Android, this is `android.graphics.ImageFormat.JPEG`. See
+  /// https://developer.android.com/reference/android/graphics/ImageFormat#JPEG
+  jpeg,
+}
+
+/// Extension on [ImageFormatGroup] to stringify the enum
+extension ImageFormatGroupName on ImageFormatGroup {
+  /// returns a String value for [ImageFormatGroup]
+  /// returns 'unknown' if platform is not supported
+  /// or if [ImageFormatGroup] is not supported for the platform
+  String name() {
+    switch (this) {
+      case ImageFormatGroup.bgra8888:
+        return 'bgra8888';
+      case ImageFormatGroup.yuv420:
+        return 'yuv420';
+      case ImageFormatGroup.jpeg:
+        return 'jpeg';
+      case ImageFormatGroup.unknown:
+      default:
+        return 'unknown';
+    }
+  }
+}
diff --git a/packages/camera/camera_platform_interface/lib/src/types/types.dart b/packages/camera/camera_platform_interface/lib/src/types/types.dart
index bab430e..eaadc5c 100644
--- a/packages/camera/camera_platform_interface/lib/src/types/types.dart
+++ b/packages/camera/camera_platform_interface/lib/src/types/types.dart
@@ -6,4 +6,5 @@
 export 'resolution_preset.dart';
 export 'camera_exception.dart';
 export 'flash_mode.dart';
+export 'image_format_group.dart';
 export 'exposure_mode.dart';
diff --git a/packages/camera/camera_platform_interface/pubspec.yaml b/packages/camera/camera_platform_interface/pubspec.yaml
index b8301d2..7a4fa49 100644
--- a/packages/camera/camera_platform_interface/pubspec.yaml
+++ b/packages/camera/camera_platform_interface/pubspec.yaml
@@ -3,7 +3,7 @@
 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.2.0
+version: 1.3.0
 
 dependencies:
   flutter:
@@ -21,5 +21,5 @@
   pedantic: ^1.8.0
 
 environment:
-  sdk: ">=2.1.0 <3.0.0"
+  sdk: ">=2.7.0 <3.0.0"
   flutter: ">=1.22.0"
diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart
index b916513..e8136fb 100644
--- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart
+++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart
@@ -25,7 +25,10 @@
         MethodChannelMock cameraMockChannel = MethodChannelMock(
             channelName: 'plugins.flutter.io/camera',
             methods: {
-              'create': {'cameraId': 1}
+              'create': {
+                'cameraId': 1,
+                'imageFormatGroup': 'unknown',
+              }
             });
         final camera = MethodChannelCamera();
 
@@ -108,7 +111,10 @@
         MethodChannelMock cameraMockChannel = MethodChannelMock(
             channelName: 'plugins.flutter.io/camera',
             methods: {
-              'create': {'cameraId': 1},
+              'create': {
+                'cameraId': 1,
+                'imageFormatGroup': 'unknown',
+              },
               'initialize': null
             });
         final camera = MethodChannelCamera();
@@ -136,6 +142,7 @@
             'initialize',
             arguments: {
               'cameraId': 1,
+              'imageFormatGroup': 'unknown',
             },
           ),
         ]);
diff --git a/packages/camera/camera_platform_interface/test/types/image_group_test.dart b/packages/camera/camera_platform_interface/test/types/image_group_test.dart
new file mode 100644
index 0000000..c49b2f0
--- /dev/null
+++ b/packages/camera/camera_platform_interface/test/types/image_group_test.dart
@@ -0,0 +1,13 @@
+import 'package:camera_platform_interface/src/types/types.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+  group('$ImageFormatGroup tests', () {
+    test('ImageFormatGroupName extension returns correct values', () {
+      expect(ImageFormatGroup.bgra8888.name(), 'bgra8888');
+      expect(ImageFormatGroup.yuv420.name(), 'yuv420');
+      expect(ImageFormatGroup.jpeg.name(), 'jpeg');
+      expect(ImageFormatGroup.unknown.name(), 'unknown');
+    });
+  });
+}