@capgo/camera-preview 8.9.0 → 8.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1448,6 +1448,19 @@ extension CameraController {
1448
1448
  photoOutput.capturePhoto(with: settings, delegate: self)
1449
1449
  }
1450
1450
 
1451
+ /// Horizontally mirrors image pixels (selfie-style). Prefer this over orientation-only flips.
1452
+ func mirrorImageHorizontally(_ image: UIImage) -> UIImage {
1453
+ let base = image.fixedOrientation() ?? image
1454
+ let format = UIGraphicsImageRendererFormat.default()
1455
+ format.scale = base.scale
1456
+ format.opaque = false
1457
+ return UIGraphicsImageRenderer(size: base.size, format: format).image { ctx in
1458
+ ctx.cgContext.translateBy(x: base.size.width, y: 0)
1459
+ ctx.cgContext.scaleBy(x: -1, y: 1)
1460
+ base.draw(in: CGRect(origin: .zero, size: base.size))
1461
+ }
1462
+ }
1463
+
1451
1464
  /// Draws timestamp and/or location pills at the top-right. Pass nil to skip either line.
1452
1465
  func drawTimestampAndLocation(on image: UIImage, when: String?, where whereStr: String?) -> UIImage {
1453
1466
  let base = image.fixedOrientation() ?? image
@@ -2191,7 +2204,6 @@ extension CameraController {
2191
2204
  }
2192
2205
  }
2193
2206
 
2194
-
2195
2207
  private func cancelPendingFocusExposureRestore() {
2196
2208
  self.focusExposureRestoreGeneration &+= 1
2197
2209
  self.focusExposureRestoreTimeoutWorkItem?.cancel()
@@ -2945,7 +2957,7 @@ extension CameraController {
2945
2957
  }
2946
2958
  }
2947
2959
 
2948
- func captureVideo(maxDuration: Float? = nil, maxFileSize: Int? = nil, allowHapticsAndSystemSoundsDuringRecording: Bool = false) throws {
2960
+ func captureVideo(maxDuration: Float? = nil, maxFileSize: Int? = nil, allowHapticsAndSystemSoundsDuringRecording: Bool = false, mirrorFrontCamera: Bool = false) throws {
2949
2961
  guard let captureSession = self.captureSession, captureSession.isRunning else {
2950
2962
  throw CameraControllerError.captureSessionIsMissing
2951
2963
  }
@@ -2997,8 +3009,8 @@ extension CameraController {
2997
3009
  // Goes off accelerometer now
2998
3010
  self.setVideoOrientation(self.getPhysicalOrientation(), on: connection)
2999
3011
 
3000
- // Front camera: mirror the recorded video so it looks natural (selfie style).
3001
- if self.currentCameraPosition == .front, connection.isVideoMirroringSupported {
3012
+ // Opt-in: mirror front-camera recordings so the file matches selfie preview.
3013
+ if mirrorFrontCamera, self.currentCameraPosition == .front, connection.isVideoMirroringSupported {
3002
3014
  connection.isVideoMirrored = true
3003
3015
  } else {
3004
3016
  connection.isVideoMirrored = false
@@ -35,7 +35,7 @@ extension UIWindow {
35
35
  */
36
36
  @objc(CameraPreview)
37
37
  public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelegate {
38
- private let pluginVersion: String = "8.9.0"
38
+ private let pluginVersion: String = "8.11.0"
39
39
  public let identifier = "CameraPreviewPlugin"
40
40
  public let jsName = "CameraPreview"
41
41
  public let pluginMethods: [CAPPluginMethod] = [
@@ -1265,10 +1265,11 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
1265
1265
  let width = call.getInt("width")
1266
1266
  let height = call.getInt("height")
1267
1267
  let photoQualityPrioritization = call.getString("photoQualityPrioritization", "speed")
1268
+ let mirrorFrontCamera = call.getBool("mirrorFrontCamera", false) ?? false
1268
1269
 
1269
1270
  print("[CameraPreview] Raw parameter values - width: \(String(describing: width)), height: \(String(describing: height))")
1270
1271
 
1271
- print("[CameraPreview] Capture params - quality: \(quality), saveToGallery: \(saveToGallery), withExifLocation: \(withExifLocation ?? false), embedTimestamp: \(embedTimestamp), embedLocation: \(effectiveEmbedLocation) (requested=\(embedLocationRequested)), width: \(width ?? -1), height: \(height ?? -1)")
1272
+ print("[CameraPreview] Capture params - quality: \(quality), saveToGallery: \(saveToGallery), withExifLocation: \(withExifLocation ?? false), embedTimestamp: \(embedTimestamp), embedLocation: \(effectiveEmbedLocation) (requested=\(embedLocationRequested)), width: \(width ?? -1), height: \(height ?? -1), mirrorFrontCamera: \(mirrorFrontCamera)")
1272
1273
  print("[CameraPreview] Current location: \(self.currentLocation?.description ?? "nil")")
1273
1274
  // Safely read frame from main thread for logging
1274
1275
  let (previewWidth, previewHeight): (CGFloat, CGFloat) = {
@@ -1303,9 +1304,21 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
1303
1304
  return
1304
1305
  }
1305
1306
 
1306
- guard let image = image,
1307
- let imageDataWithExif = self.createImageDataWithExif(
1308
- from: image,
1307
+ guard let capturedImage = image else {
1308
+ print("[CameraPreview] Failed to create image data with EXIF")
1309
+ call.reject("Failed to create image data with EXIF")
1310
+ return
1311
+ }
1312
+
1313
+ let imageToEncode: UIImage
1314
+ if mirrorFrontCamera, self.cameraPosition == "front" {
1315
+ imageToEncode = self.cameraController.mirrorImageHorizontally(capturedImage)
1316
+ } else {
1317
+ imageToEncode = capturedImage
1318
+ }
1319
+
1320
+ guard let imageDataWithExif = self.createImageDataWithExif(
1321
+ from: imageToEncode,
1309
1322
  quality: Int(quality),
1310
1323
  location: withExifLocation ? self.currentLocation : nil,
1311
1324
  heading: withExifLocation ? self.currentHeading : nil,
@@ -1520,6 +1533,7 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
1520
1533
 
1521
1534
  @objc func captureSample(_ call: CAPPluginCall) {
1522
1535
  let quality: Int = call.getInt("quality") ?? 85
1536
+ let mirrorFrontCamera = call.getBool("mirrorFrontCamera", false) ?? false
1523
1537
 
1524
1538
  self.cameraController.captureSample { image, error in
1525
1539
  guard let image = image else {
@@ -1528,13 +1542,11 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
1528
1542
  return
1529
1543
  }
1530
1544
 
1531
- let imageData: Data?
1532
- if self.cameraPosition == "front" {
1533
- let flippedImage = image.withHorizontallyFlippedOrientation()
1534
- imageData = flippedImage.jpegData(compressionQuality: CGFloat(quality)/100)
1535
- } else {
1536
- imageData = image.jpegData(compressionQuality: CGFloat(quality)/100)
1545
+ var outputImage = image
1546
+ if mirrorFrontCamera, self.cameraPosition == "front" {
1547
+ outputImage = self.cameraController.mirrorImageHorizontally(image)
1537
1548
  }
1549
+ let imageData = outputImage.jpegData(compressionQuality: CGFloat(quality)/100)
1538
1550
 
1539
1551
  if self.storeToFile == false {
1540
1552
  guard let imageBase64 = imageData?.base64EncodedString() else {
@@ -1718,10 +1730,12 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
1718
1730
  try self.cameraController.setVideoFrameRate(frameRate)
1719
1731
  }
1720
1732
  let allowHapticsAndSystemSoundsDuringRecording = call.getBool("allowHapticsAndSystemSoundsDuringRecording") ?? false
1733
+ let mirrorFrontCamera = call.getBool("mirrorFrontCamera") ?? false
1721
1734
  try self.cameraController.captureVideo(
1722
1735
  maxDuration: maxDuration,
1723
1736
  maxFileSize: maxFileSize,
1724
- allowHapticsAndSystemSoundsDuringRecording: allowHapticsAndSystemSoundsDuringRecording
1737
+ allowHapticsAndSystemSoundsDuringRecording: allowHapticsAndSystemSoundsDuringRecording,
1738
+ mirrorFrontCamera: mirrorFrontCamera
1725
1739
  )
1726
1740
  call.resolve()
1727
1741
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/camera-preview",
3
- "version": "8.9.0",
3
+ "version": "8.11.0",
4
4
  "description": "Camera preview",
5
5
  "license": "MPL-2.0",
6
6
  "repository": {