Skip to content

Commit

Permalink
Merge pull request #137 from Cap-go/getSupportedPictureSizes
Browse files Browse the repository at this point in the history
feat: getSupportedPictureSizes
  • Loading branch information
WcaleNieWolny authored Nov 18, 2024
2 parents 41c9bab + 1953435 commit fe8560a
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 0 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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:** <code>Promise&lt;{ supportedPictureSizes: { facing: string; supportedPictureSizes: { width: number; height: number; }[]; }[]; }&gt;</code>
--------------------
### setFlashMode(...)
```typescript
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,26 @@

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;
import android.view.View;
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;
Expand All @@ -27,6 +35,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;
Expand Down Expand Up @@ -130,6 +139,70 @@ public void captureSample(PluginCall call) {
fragment.takeSnapshot(quality);
}

@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
Expand Down
1 change: 1 addition & 0 deletions ios/Plugin/Plugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@
CAP_PLUGIN_METHOD(setFlashMode, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(startRecordVideo, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(stopRecordVideo, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(getSupportedPictureSizes, CAPPluginReturnPromise);
)
79 changes: 79 additions & 0 deletions ios/Plugin/Plugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
11 changes: 11 additions & 0 deletions src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,17 @@ export interface CameraPreviewPlugin {
getHorizontalFov(): Promise<{
result: any;
}>;
/**
* Gets the supported picture sizes for a given device.
* @returns {Promise<any>} 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
Expand Down

0 comments on commit fe8560a

Please sign in to comment.