From 4f55cb7e943848e875de03bb91a22335c7a41319 Mon Sep 17 00:00:00 2001 From: WcaleNieWolny Date: Sun, 17 Nov 2024 12:02:02 +0100 Subject: [PATCH 1/2] feat: getSupportedPictureSizes --- README.md | 14 ++++ .../camera/preview/CameraPreview.java | 67 ++++++++++++++++ ios/Plugin/Plugin.m | 1 + ios/Plugin/Plugin.swift | 79 +++++++++++++++++++ src/definitions.ts | 8 ++ 5 files changed, 169 insertions(+) diff --git a/README.md b/README.md index 6e4b9c66..2aabf3ca 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,7 @@ Documentation for the [uploader](https://github.com/Cap-go/capacitor-uploader) * [`captureSample(...)`](#capturesample) * [`getSupportedFlashModes()`](#getsupportedflashmodes) * [`getHorizontalFov()`](#gethorizontalfov) +* [`getSupportedPictureSizes()`](#getsupportedpicturesizes) * [`setFlashMode(...)`](#setflashmode) * [`flip()`](#flip) * [`setOpacity(...)`](#setopacity) @@ -279,6 +280,19 @@ Get horizontal field of view. -------------------- +### getSupportedPictureSizes() + +```typescript +getSupportedPictureSizes() => Promise<{ supportedPictureSizes: { facing: string; supportedPictureSizes: { width: number; height: number; }[]; }[]; }> +``` + +Gets the supported picture sizes for a given device. + +**Returns:** Promise<{ supportedPictureSizes: { facing: string; supportedPictureSizes: { width: number; height: number; }[]; }[]; }> + +-------------------- + + ### setFlashMode(...) ```typescript diff --git a/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java b/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java index 482b9f7d..58d1e9d8 100644 --- a/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +++ b/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java @@ -5,11 +5,18 @@ import android.app.FragmentManager; import android.app.FragmentTransaction; +import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.Color; +import android.graphics.ImageFormat; import android.graphics.Point; import android.hardware.Camera; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraManager; +import android.hardware.camera2.params.StreamConfigurationMap; import android.util.DisplayMetrics; +import android.util.Size; import android.util.TypedValue; import android.view.Display; import android.view.MotionEvent; @@ -17,6 +24,8 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import androidx.annotation.NonNull; + +import com.getcapacitor.JSArray; import com.getcapacitor.JSObject; import com.getcapacitor.Logger; import com.getcapacitor.PermissionState; @@ -27,6 +36,7 @@ import com.getcapacitor.annotation.Permission; import com.getcapacitor.annotation.PermissionCallback; import java.io.File; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import org.json.JSONArray; @@ -131,6 +141,63 @@ public void captureSample(PluginCall call) { } @PluginMethod + public void getSupportedPictureSizes(final PluginCall call) { + CameraManager cameraManager = (CameraManager) this.getContext().getSystemService(Context.CAMERA_SERVICE); + + JSArray ret = new JSArray(); + try { + String[] cameraIdList = cameraManager.getCameraIdList(); + for (String cameraId : cameraIdList) { + CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId); + + // Determine the facing of the camera + Integer lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING); + String facing = "Unknown"; + if (lensFacing != null) { + switch (lensFacing) { + case CameraCharacteristics.LENS_FACING_FRONT: + facing = "Front"; + break; + case CameraCharacteristics.LENS_FACING_BACK: + facing = "Back"; + break; + case CameraCharacteristics.LENS_FACING_EXTERNAL: + facing = "External"; + break; + } + } + + StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + if (map == null) { + continue; + } + + Size[] jpegSizes = map.getOutputSizes(ImageFormat.JPEG); + JSObject camera = new JSObject(); + camera.put("facing", facing); + JSArray supportedPictureSizes = new JSArray(); + if (jpegSizes != null) { + for (Size size : jpegSizes) { + JSObject sizeJson = new JSObject(); + sizeJson.put("width", size.getWidth()); + sizeJson.put("height", size.getHeight()); + supportedPictureSizes.put(sizeJson); + } + camera.put("supportedPictureSizes", supportedPictureSizes); + ret.put(camera); + } + } + JSObject finalRet = new JSObject(); + finalRet.put("supportedPictureSizes", ret); + call.resolve(finalRet); + } catch (CameraAccessException ex) { + Logger.error(getLogTag(), "Cannot call getSupportedPictureSizes", ex); + call.reject(String.format("Cannot call getSupportedPictureSizes. Error: %s", ex)); + } + } + + + @PluginMethod public void stop(final PluginCall call) { bridge .getActivity() diff --git a/ios/Plugin/Plugin.m b/ios/Plugin/Plugin.m index b8fb86ce..787ae813 100644 --- a/ios/Plugin/Plugin.m +++ b/ios/Plugin/Plugin.m @@ -14,4 +14,5 @@ CAP_PLUGIN_METHOD(setFlashMode, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(startRecordVideo, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(stopRecordVideo, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(getSupportedPictureSizes, CAPPluginReturnPromise); ) diff --git a/ios/Plugin/Plugin.swift b/ios/Plugin/Plugin.swift index 295969d7..0a33aa92 100644 --- a/ios/Plugin/Plugin.swift +++ b/ios/Plugin/Plugin.swift @@ -81,6 +81,85 @@ public class CameraPreview: CAPPlugin { cameraController.updateVideoOrientation() } + + struct CameraInfo { + let deviceID: String + let position: String + let pictureSizes: [CGSize] + } + + func getSupportedPictureSizes() -> [CameraInfo] { + var cameraInfos = [CameraInfo]() + + // Discover all available cameras + let deviceTypes: [AVCaptureDevice.DeviceType] = [ + .builtInWideAngleCamera, + .builtInTelephotoCamera, + .builtInUltraWideCamera, + .builtInTrueDepthCamera + ] + + let session = AVCaptureDevice.DiscoverySession( + deviceTypes: deviceTypes, + mediaType: .video, + position: .unspecified + ) + + let devices = session.devices + + for device in devices { + // Determine the position of the camera + var position = "Unknown" + switch device.position { + case .front: + position = "Front" + case .back: + position = "Back" + case .unspecified: + position = "Unspecified" + @unknown default: + position = "Unknown" + } + + var pictureSizes = [CGSize]() + + // Get supported formats + for format in device.formats { + let description = format.formatDescription + let dimensions = CMVideoFormatDescriptionGetDimensions(description) + let size = CGSize(width: CGFloat(dimensions.width), height: CGFloat(dimensions.height)) + if !pictureSizes.contains(size) { + pictureSizes.append(size) + } + } + + // Sort sizes in descending order (largest to smallest) + pictureSizes.sort { $0.width * $0.height > $1.width * $1.height } + + let cameraInfo = CameraInfo(deviceID: device.uniqueID, position: position, pictureSizes: pictureSizes) + cameraInfos.append(cameraInfo) + } + + return cameraInfos + } + + + @objc func getSupportedPictureSizes(_ call: CAPPluginCall) { + let cameraInfos = getSupportedPictureSizes() + call.resolve([ + "supportedPictureSizes": cameraInfos.map { + return [ + "facing": $0.position, + "supportedPictureSizes": $0.pictureSizes.map { size in + return [ + "width": String(describing: size.width), + "height": String(describing: size.height), + ] + } + ] + } + ]) + } @objc func start(_ call: CAPPluginCall) { self.cameraPosition = call.getString("position") ?? "rear" diff --git a/src/definitions.ts b/src/definitions.ts index 2bc5cfd2..8b23708e 100644 --- a/src/definitions.ts +++ b/src/definitions.ts @@ -120,6 +120,14 @@ export interface CameraPreviewPlugin { getHorizontalFov(): Promise<{ result: any; }>; + /** + * Gets the supported picture sizes for a given device. + * @returns {Promise} an Promise that resolves with the supported picture sizes for a given device + * @throws An error if the something goes wrong + */ + getSupportedPictureSizes(): Promise<{ + supportedPictureSizes: {facing: string, supportedPictureSizes: {width: number, height: number}[]}[] + }> /** * Set flash mode. * @param options the options to set the flash mode with From 19534359d88ee616c5d3348aade605982c5efe55 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 11:03:30 +0000 Subject: [PATCH 2/2] [autofix.ci] apply automated fixes --- .../camera/preview/CameraPreview.java | 24 ++++++++++++------- src/definitions.ts | 7 ++++-- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java b/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java index 58d1e9d8..cadeec95 100644 --- a/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +++ b/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java @@ -24,7 +24,6 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import androidx.annotation.NonNull; - import com.getcapacitor.JSArray; import com.getcapacitor.JSObject; import com.getcapacitor.Logger; @@ -142,16 +141,20 @@ public void captureSample(PluginCall call) { @PluginMethod public void getSupportedPictureSizes(final PluginCall call) { - CameraManager cameraManager = (CameraManager) this.getContext().getSystemService(Context.CAMERA_SERVICE); + CameraManager cameraManager = (CameraManager) this.getContext() + .getSystemService(Context.CAMERA_SERVICE); JSArray ret = new JSArray(); try { String[] cameraIdList = cameraManager.getCameraIdList(); for (String cameraId : cameraIdList) { - CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId); + CameraCharacteristics characteristics = + cameraManager.getCameraCharacteristics(cameraId); // Determine the facing of the camera - Integer lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING); + Integer lensFacing = characteristics.get( + CameraCharacteristics.LENS_FACING + ); String facing = "Unknown"; if (lensFacing != null) { switch (lensFacing) { @@ -167,7 +170,9 @@ public void getSupportedPictureSizes(final PluginCall call) { } } - StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + StreamConfigurationMap map = characteristics.get( + CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP + ); if (map == null) { continue; } @@ -190,14 +195,15 @@ public void getSupportedPictureSizes(final PluginCall call) { JSObject finalRet = new JSObject(); finalRet.put("supportedPictureSizes", ret); call.resolve(finalRet); - } catch (CameraAccessException ex) { + } catch (CameraAccessException ex) { Logger.error(getLogTag(), "Cannot call getSupportedPictureSizes", ex); - call.reject(String.format("Cannot call getSupportedPictureSizes. Error: %s", ex)); + call.reject( + String.format("Cannot call getSupportedPictureSizes. Error: %s", ex) + ); } } - - @PluginMethod + @PluginMethod public void stop(final PluginCall call) { bridge .getActivity() diff --git a/src/definitions.ts b/src/definitions.ts index 8b23708e..432e9c99 100644 --- a/src/definitions.ts +++ b/src/definitions.ts @@ -126,8 +126,11 @@ export interface CameraPreviewPlugin { * @throws An error if the something goes wrong */ getSupportedPictureSizes(): Promise<{ - supportedPictureSizes: {facing: string, supportedPictureSizes: {width: number, height: number}[]}[] - }> + supportedPictureSizes: { + facing: string; + supportedPictureSizes: { width: number; height: number }[]; + }[]; + }>; /** * Set flash mode. * @param options the options to set the flash mode with