@capgo/camera-preview 7.4.0-beta.1 → 7.4.0-beta.10

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.
Files changed (31) hide show
  1. package/README.md +195 -31
  2. package/android/.gradle/8.14.2/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.14.2/checksums/md5-checksums.bin +0 -0
  4. package/android/.gradle/8.14.2/checksums/sha1-checksums.bin +0 -0
  5. package/android/.gradle/8.14.2/executionHistory/executionHistory.bin +0 -0
  6. package/android/.gradle/8.14.2/executionHistory/executionHistory.lock +0 -0
  7. package/android/.gradle/8.14.2/fileHashes/fileHashes.bin +0 -0
  8. package/android/.gradle/8.14.2/fileHashes/fileHashes.lock +0 -0
  9. package/android/.gradle/8.14.2/fileHashes/resourceHashesCache.bin +0 -0
  10. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  11. package/android/.gradle/file-system.probe +0 -0
  12. package/android/build.gradle +3 -1
  13. package/android/src/main/AndroidManifest.xml +5 -3
  14. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +282 -45
  15. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraXView.java +902 -102
  16. package/android/src/main/java/com/ahm/capacitor/camera/preview/GridOverlayView.java +82 -0
  17. package/android/src/main/java/com/ahm/capacitor/camera/preview/model/CameraSessionConfiguration.java +19 -5
  18. package/dist/docs.json +235 -6
  19. package/dist/esm/definitions.d.ts +119 -3
  20. package/dist/esm/definitions.js.map +1 -1
  21. package/dist/esm/web.d.ts +47 -3
  22. package/dist/esm/web.js +262 -78
  23. package/dist/esm/web.js.map +1 -1
  24. package/dist/plugin.cjs.js +258 -78
  25. package/dist/plugin.cjs.js.map +1 -1
  26. package/dist/plugin.js +258 -78
  27. package/dist/plugin.js.map +1 -1
  28. package/ios/Sources/CapgoCameraPreview/CameraController.swift +245 -28
  29. package/ios/Sources/CapgoCameraPreview/GridOverlayView.swift +65 -0
  30. package/ios/Sources/CapgoCameraPreview/Plugin.swift +657 -90
  31. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["export var DeviceType;\n(function (DeviceType) {\n DeviceType[\"ULTRA_WIDE\"] = \"ultraWide\";\n DeviceType[\"WIDE_ANGLE\"] = \"wideAngle\";\n DeviceType[\"TELEPHOTO\"] = \"telephoto\";\n DeviceType[\"TRUE_DEPTH\"] = \"trueDepth\";\n DeviceType[\"DUAL\"] = \"dual\";\n DeviceType[\"DUAL_WIDE\"] = \"dualWide\";\n DeviceType[\"TRIPLE\"] = \"triple\";\n})(DeviceType || (DeviceType = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from \"@capacitor/core\";\nconst CameraPreview = registerPlugin(\"CameraPreview\", {\n web: () => import(\"./web\").then((m) => new m.CameraPreviewWeb()),\n});\nexport * from \"./definitions\";\nexport { CameraPreview };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nimport { DeviceType } from \"./definitions\";\nexport class CameraPreviewWeb extends WebPlugin {\n constructor() {\n super();\n /**\n * track which camera is used based on start options\n * used in capture\n */\n this.isBackCamera = false;\n this.currentDeviceId = null;\n }\n async getSupportedPictureSizes() {\n throw new Error(\"getSupportedPictureSizes not supported under the web platform\");\n }\n async start(options) {\n var _a;\n await navigator.mediaDevices\n .getUserMedia({\n audio: !options.disableAudio,\n video: true,\n })\n .then((stream) => {\n // Stop any existing stream so we can request media with different constraints based on user input\n stream.getTracks().forEach((track) => track.stop());\n })\n .catch((error) => {\n Promise.reject(error);\n });\n const video = document.getElementById(\"video\");\n const parent = document.getElementById((options === null || options === void 0 ? void 0 : options.parent) || \"\");\n if (!video) {\n const videoElement = document.createElement(\"video\");\n videoElement.id = \"video\";\n videoElement.setAttribute(\"class\", (options === null || options === void 0 ? void 0 : options.className) || \"\");\n // Don't flip video feed if camera is rear facing\n if (options.position !== \"rear\") {\n videoElement.setAttribute(\"style\", \"-webkit-transform: scaleX(-1); transform: scaleX(-1);\");\n }\n const userAgent = navigator.userAgent.toLowerCase();\n const isSafari = userAgent.includes(\"safari\") && !userAgent.includes(\"chrome\");\n // Safari on iOS needs to have the autoplay, muted and playsinline attributes set for video.play() to be successful\n // Without these attributes videoElement.play() will throw a NotAllowedError\n // https://developer.apple.com/documentation/webkit/delivering_video_content_for_safari\n if (isSafari) {\n videoElement.setAttribute(\"autoplay\", \"true\");\n videoElement.setAttribute(\"muted\", \"true\");\n videoElement.setAttribute(\"playsinline\", \"true\");\n }\n parent === null || parent === void 0 ? void 0 : parent.appendChild(videoElement);\n if ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia) {\n const constraints = {\n video: {\n width: { ideal: options.width },\n height: { ideal: options.height },\n },\n };\n if (options.deviceId) {\n constraints.video.deviceId = { exact: options.deviceId };\n this.currentDeviceId = options.deviceId;\n // Try to determine camera position from device\n const devices = await navigator.mediaDevices.enumerateDevices();\n const device = devices.find(d => d.deviceId === options.deviceId);\n this.isBackCamera = (device === null || device === void 0 ? void 0 : device.label.toLowerCase().includes('back')) || (device === null || device === void 0 ? void 0 : device.label.toLowerCase().includes('rear')) || false;\n }\n else if (options.position === \"rear\") {\n constraints.video.facingMode = \"environment\";\n this.isBackCamera = true;\n }\n else {\n this.isBackCamera = false;\n }\n const self = this;\n await navigator.mediaDevices.getUserMedia(constraints).then((stream) => {\n if (document.getElementById(\"video\")) {\n // video.src = window.URL.createObjectURL(stream);\n videoElement.srcObject = stream;\n videoElement.play();\n Promise.resolve({});\n }\n else {\n self.stopStream(stream);\n Promise.reject(new Error(\"camera already stopped\"));\n }\n }, (err) => {\n Promise.reject(new Error(err));\n });\n }\n }\n else {\n Promise.reject(new Error(\"camera already started\"));\n }\n }\n stopStream(stream) {\n if (stream) {\n const tracks = stream.getTracks();\n for (const track of tracks)\n track.stop();\n }\n }\n async stop() {\n const video = document.getElementById(\"video\");\n if (video) {\n video.pause();\n this.stopStream(video.srcObject);\n video.remove();\n }\n }\n async capture(options) {\n return new Promise((resolve, reject) => {\n const video = document.getElementById(\"video\");\n if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {\n reject(new Error(\"camera is not running\"));\n return;\n }\n // video.width = video.offsetWidth;\n let base64EncodedImage;\n if (video && video.videoWidth > 0 && video.videoHeight > 0) {\n const canvas = document.createElement(\"canvas\");\n const context = canvas.getContext(\"2d\");\n canvas.width = video.videoWidth;\n canvas.height = video.videoHeight;\n // flip horizontally back camera isn't used\n if (!this.isBackCamera) {\n context === null || context === void 0 ? void 0 : context.translate(video.videoWidth, 0);\n context === null || context === void 0 ? void 0 : context.scale(-1, 1);\n }\n context === null || context === void 0 ? void 0 : context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);\n if ((options.format || \"jpeg\") === \"jpeg\") {\n base64EncodedImage = canvas\n .toDataURL(\"image/jpeg\", (options.quality || 85) / 100.0)\n .replace(\"data:image/jpeg;base64,\", \"\");\n }\n else {\n base64EncodedImage = canvas\n .toDataURL(\"image/png\")\n .replace(\"data:image/png;base64,\", \"\");\n }\n }\n resolve({\n value: base64EncodedImage,\n });\n });\n }\n async captureSample(_options) {\n return this.capture(_options);\n }\n async stopRecordVideo() {\n throw new Error(\"stopRecordVideo not supported under the web platform\");\n }\n async startRecordVideo(_options) {\n console.log(\"startRecordVideo\", _options);\n throw new Error(\"startRecordVideo not supported under the web platform\");\n }\n async getSupportedFlashModes() {\n throw new Error(\"getSupportedFlashModes not supported under the web platform\");\n }\n async getHorizontalFov() {\n throw new Error(\"getHorizontalFov not supported under the web platform\");\n }\n async setFlashMode(_options) {\n throw new Error(`setFlashMode not supported under the web platform${_options}`);\n }\n async flip() {\n const video = document.getElementById(\"video\");\n if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {\n throw new Error(\"camera is not running\");\n }\n // Stop current stream\n this.stopStream(video.srcObject);\n // Toggle camera position\n this.isBackCamera = !this.isBackCamera;\n // Get new constraints\n const constraints = {\n video: {\n facingMode: this.isBackCamera ? \"environment\" : \"user\",\n width: { ideal: video.videoWidth || 640 },\n height: { ideal: video.videoHeight || 480 },\n },\n };\n try {\n const stream = await navigator.mediaDevices.getUserMedia(constraints);\n video.srcObject = stream;\n // Update current device ID from the new stream\n const videoTrack = stream.getVideoTracks()[0];\n if (videoTrack) {\n this.currentDeviceId = videoTrack.getSettings().deviceId || null;\n }\n // Update video transform based on camera\n if (this.isBackCamera) {\n video.style.transform = \"none\";\n video.style.webkitTransform = \"none\";\n }\n else {\n video.style.transform = \"scaleX(-1)\";\n video.style.webkitTransform = \"scaleX(-1)\";\n }\n await video.play();\n }\n catch (error) {\n throw new Error(`Failed to flip camera: ${error}`);\n }\n }\n async setOpacity(_options) {\n const video = document.getElementById(\"video\");\n if (!!video && !!_options.opacity)\n video.style.setProperty(\"opacity\", _options.opacity.toString());\n }\n async isRunning() {\n const video = document.getElementById(\"video\");\n return { isRunning: !!video && !!video.srcObject };\n }\n async getAvailableDevices() {\n var _a;\n if (!((_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.enumerateDevices)) {\n throw new Error(\"getAvailableDevices not supported under the web platform\");\n }\n const devices = await navigator.mediaDevices.enumerateDevices();\n const videoDevices = devices.filter(device => device.kind === 'videoinput');\n // Group devices by position (front/back)\n const frontDevices = [];\n const backDevices = [];\n videoDevices.forEach((device, index) => {\n const label = device.label || `Camera ${index + 1}`;\n const labelLower = label.toLowerCase();\n // Determine device type based on label\n let deviceType = DeviceType.WIDE_ANGLE;\n let baseZoomRatio = 1.0;\n if (labelLower.includes('ultra') || labelLower.includes('0.5')) {\n deviceType = DeviceType.ULTRA_WIDE;\n baseZoomRatio = 0.5;\n }\n else if (labelLower.includes('telephoto') || labelLower.includes('tele') || labelLower.includes('2x') || labelLower.includes('3x')) {\n deviceType = DeviceType.TELEPHOTO;\n baseZoomRatio = 2.0;\n }\n else if (labelLower.includes('depth') || labelLower.includes('truedepth')) {\n deviceType = DeviceType.TRUE_DEPTH;\n baseZoomRatio = 1.0;\n }\n const lensInfo = {\n deviceId: device.deviceId,\n label,\n deviceType,\n focalLength: 4.25,\n baseZoomRatio,\n minZoom: 1.0,\n maxZoom: 1.0\n };\n // Determine position and add to appropriate array\n if (labelLower.includes('back') || labelLower.includes('rear')) {\n backDevices.push(lensInfo);\n }\n else {\n frontDevices.push(lensInfo);\n }\n });\n const result = [];\n if (frontDevices.length > 0) {\n result.push({\n deviceId: frontDevices[0].deviceId,\n label: \"Front Camera\",\n position: \"front\",\n lenses: frontDevices,\n isLogical: false,\n minZoom: Math.min(...frontDevices.map(d => d.minZoom)),\n maxZoom: Math.max(...frontDevices.map(d => d.maxZoom))\n });\n }\n if (backDevices.length > 0) {\n result.push({\n deviceId: backDevices[0].deviceId,\n label: \"Back Camera\",\n position: \"rear\",\n lenses: backDevices,\n isLogical: false,\n minZoom: Math.min(...backDevices.map(d => d.minZoom)),\n maxZoom: Math.max(...backDevices.map(d => d.maxZoom))\n });\n }\n return { devices: result };\n }\n async getZoom() {\n const video = document.getElementById(\"video\");\n if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {\n throw new Error(\"camera is not running\");\n }\n const stream = video.srcObject;\n const videoTrack = stream.getVideoTracks()[0];\n if (!videoTrack) {\n throw new Error(\"no video track found\");\n }\n const capabilities = videoTrack.getCapabilities();\n const settings = videoTrack.getSettings();\n if (!capabilities.zoom) {\n throw new Error(\"zoom not supported by this device\");\n }\n // Get current device info to determine lens type\n let deviceType = DeviceType.WIDE_ANGLE;\n let baseZoomRatio = 1.0;\n if (this.currentDeviceId) {\n const devices = await navigator.mediaDevices.enumerateDevices();\n const device = devices.find(d => d.deviceId === this.currentDeviceId);\n if (device) {\n const labelLower = device.label.toLowerCase();\n if (labelLower.includes('ultra') || labelLower.includes('0.5')) {\n deviceType = DeviceType.ULTRA_WIDE;\n baseZoomRatio = 0.5;\n }\n else if (labelLower.includes('telephoto') || labelLower.includes('tele') || labelLower.includes('2x') || labelLower.includes('3x')) {\n deviceType = DeviceType.TELEPHOTO;\n baseZoomRatio = 2.0;\n }\n else if (labelLower.includes('depth') || labelLower.includes('truedepth')) {\n deviceType = DeviceType.TRUE_DEPTH;\n baseZoomRatio = 1.0;\n }\n }\n }\n const currentZoom = settings.zoom || 1;\n const lensInfo = {\n focalLength: 4.25,\n deviceType,\n baseZoomRatio,\n digitalZoom: currentZoom / baseZoomRatio\n };\n return {\n min: capabilities.zoom.min || 1,\n max: capabilities.zoom.max || 1,\n current: currentZoom,\n lens: lensInfo,\n };\n }\n async setZoom(options) {\n const video = document.getElementById(\"video\");\n if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {\n throw new Error(\"camera is not running\");\n }\n const stream = video.srcObject;\n const videoTrack = stream.getVideoTracks()[0];\n if (!videoTrack) {\n throw new Error(\"no video track found\");\n }\n const capabilities = videoTrack.getCapabilities();\n if (!capabilities.zoom) {\n throw new Error(\"zoom not supported by this device\");\n }\n const zoomLevel = Math.max(capabilities.zoom.min || 1, Math.min(capabilities.zoom.max || 1, options.level));\n try {\n await videoTrack.applyConstraints({\n advanced: [{ zoom: zoomLevel }]\n });\n }\n catch (error) {\n throw new Error(`Failed to set zoom: ${error}`);\n }\n }\n async getFlashMode() {\n throw new Error(\"getFlashMode not supported under the web platform\");\n }\n async getDeviceId() {\n return { deviceId: this.currentDeviceId || \"\" };\n }\n async setDeviceId(options) {\n const video = document.getElementById(\"video\");\n if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {\n throw new Error(\"camera is not running\");\n }\n // Stop current stream\n this.stopStream(video.srcObject);\n // Update current device ID\n this.currentDeviceId = options.deviceId;\n // Get new constraints with specific device ID\n const constraints = {\n video: {\n deviceId: { exact: options.deviceId },\n width: { ideal: video.videoWidth || 640 },\n height: { ideal: video.videoHeight || 480 },\n },\n };\n try {\n // Try to determine camera position from device\n const devices = await navigator.mediaDevices.enumerateDevices();\n const device = devices.find(d => d.deviceId === options.deviceId);\n this.isBackCamera = (device === null || device === void 0 ? void 0 : device.label.toLowerCase().includes('back')) || (device === null || device === void 0 ? void 0 : device.label.toLowerCase().includes('rear')) || false;\n const stream = await navigator.mediaDevices.getUserMedia(constraints);\n video.srcObject = stream;\n // Update video transform based on camera\n if (this.isBackCamera) {\n video.style.transform = \"none\";\n video.style.webkitTransform = \"none\";\n }\n else {\n video.style.transform = \"scaleX(-1)\";\n video.style.webkitTransform = \"scaleX(-1)\";\n }\n await video.play();\n }\n catch (error) {\n throw new Error(`Failed to swap to device ${options.deviceId}: ${error}`);\n }\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["DeviceType","registerPlugin","WebPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["export var DeviceType;\n(function (DeviceType) {\n DeviceType[\"ULTRA_WIDE\"] = \"ultraWide\";\n DeviceType[\"WIDE_ANGLE\"] = \"wideAngle\";\n DeviceType[\"TELEPHOTO\"] = \"telephoto\";\n DeviceType[\"TRUE_DEPTH\"] = \"trueDepth\";\n DeviceType[\"DUAL\"] = \"dual\";\n DeviceType[\"DUAL_WIDE\"] = \"dualWide\";\n DeviceType[\"TRIPLE\"] = \"triple\";\n})(DeviceType || (DeviceType = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from \"@capacitor/core\";\nconst CameraPreview = registerPlugin(\"CameraPreview\", {\n web: () => import(\"./web\").then((m) => new m.CameraPreviewWeb()),\n});\nexport * from \"./definitions\";\nexport { CameraPreview };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nimport { DeviceType } from \"./definitions\";\nconst DEFAULT_VIDEO_ID = \"capgo_video\";\nexport class CameraPreviewWeb extends WebPlugin {\n constructor() {\n super();\n /**\n * track which camera is used based on start options\n * used in capture\n */\n this.isBackCamera = false;\n this.currentDeviceId = null;\n this.videoElement = null;\n this.isStarted = false;\n }\n async getSupportedPictureSizes() {\n throw new Error(\"getSupportedPictureSizes not supported under the web platform\");\n }\n async start(options) {\n if (options.aspectRatio && (options.width || options.height)) {\n throw new Error(\"Cannot set both aspectRatio and size (width/height). Use setPreviewSize after start.\");\n }\n if (this.isStarted) {\n throw new Error(\"camera already started\");\n }\n this.isBackCamera = true;\n this.isStarted = false;\n const parent = document.getElementById((options === null || options === void 0 ? void 0 : options.parent) || \"\");\n const gridMode = (options === null || options === void 0 ? void 0 : options.gridMode) || \"none\";\n if (options.position) {\n this.isBackCamera = options.position === \"rear\";\n }\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (video) {\n video.remove();\n }\n const container = options.parent ? document.getElementById(options.parent) : document.body;\n if (!container) {\n throw new Error(\"container not found\");\n }\n this.videoElement = document.createElement(\"video\");\n this.videoElement.id = DEFAULT_VIDEO_ID;\n this.videoElement.className = options.className || \"\";\n this.videoElement.playsInline = true;\n this.videoElement.muted = true;\n this.videoElement.autoplay = true;\n container.appendChild(this.videoElement);\n if (options.toBack) {\n this.videoElement.style.zIndex = \"-1\";\n }\n if (options.width) {\n this.videoElement.width = options.width;\n }\n if (options.height) {\n this.videoElement.height = options.height;\n }\n if (options.x) {\n this.videoElement.style.left = `${options.x}px`;\n }\n // Create and add grid overlay if needed\n if (gridMode !== \"none\") {\n const gridOverlay = this.createGridOverlay(gridMode);\n gridOverlay.id = \"camera-grid-overlay\";\n parent === null || parent === void 0 ? void 0 : parent.appendChild(gridOverlay);\n }\n if (options.y) {\n this.videoElement.style.top = `${options.y}px`;\n }\n if (options.aspectRatio) {\n const [widthRatio, heightRatio] = options.aspectRatio.split(':').map(Number);\n const ratio = widthRatio / heightRatio;\n if (options.width) {\n this.videoElement.height = options.width / ratio;\n }\n else if (options.height) {\n this.videoElement.width = options.height * ratio;\n }\n }\n else {\n this.videoElement.style.objectFit = 'cover';\n }\n const constraints = {\n video: {\n width: { ideal: this.videoElement.width || 640 },\n height: { ideal: this.videoElement.height || window.innerHeight },\n facingMode: this.isBackCamera ? \"environment\" : \"user\",\n },\n };\n const stream = await navigator.mediaDevices.getUserMedia(constraints);\n if (!stream) {\n throw new Error(\"could not acquire stream\");\n }\n if (!this.videoElement) {\n throw new Error(\"video element not found\");\n }\n this.videoElement.srcObject = stream;\n if (!this.isBackCamera) {\n this.videoElement.style.transform = \"scaleX(-1)\";\n }\n this.isStarted = true;\n return {\n width: this.videoElement.width,\n height: this.videoElement.height,\n x: this.videoElement.getBoundingClientRect().x,\n y: this.videoElement.getBoundingClientRect().y,\n };\n }\n stopStream(stream) {\n if (stream) {\n const tracks = stream.getTracks();\n for (const track of tracks)\n track.stop();\n }\n }\n async stop() {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (video) {\n video.pause();\n this.stopStream(video.srcObject);\n video.remove();\n this.isStarted = false;\n }\n // Remove grid overlay if it exists\n const gridOverlay = document.getElementById(\"camera-grid-overlay\");\n gridOverlay === null || gridOverlay === void 0 ? void 0 : gridOverlay.remove();\n }\n async capture(options) {\n return new Promise((resolve, reject) => {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {\n reject(new Error(\"camera is not running\"));\n return;\n }\n // video.width = video.offsetWidth;\n let base64EncodedImage;\n if (video && video.videoWidth > 0 && video.videoHeight > 0) {\n const canvas = document.createElement(\"canvas\");\n const context = canvas.getContext(\"2d\");\n canvas.width = video.videoWidth;\n canvas.height = video.videoHeight;\n // flip horizontally back camera isn't used\n if (!this.isBackCamera) {\n context === null || context === void 0 ? void 0 : context.translate(video.videoWidth, 0);\n context === null || context === void 0 ? void 0 : context.scale(-1, 1);\n }\n context === null || context === void 0 ? void 0 : context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);\n if (options.saveToGallery) {\n // saveToGallery is not supported on web\n }\n if (options.withExifLocation) {\n // withExifLocation is not supported on web\n }\n if ((options.format || \"jpeg\") === \"jpeg\") {\n base64EncodedImage = canvas\n .toDataURL(\"image/jpeg\", (options.quality || 85) / 100.0)\n .replace(\"data:image/jpeg;base64,\", \"\");\n }\n else {\n base64EncodedImage = canvas\n .toDataURL(\"image/png\")\n .replace(\"data:image/png;base64,\", \"\");\n }\n }\n resolve({\n value: base64EncodedImage,\n exif: {},\n });\n });\n }\n async captureSample(_options) {\n return this.capture(_options);\n }\n async stopRecordVideo() {\n throw new Error(\"stopRecordVideo not supported under the web platform\");\n }\n async startRecordVideo(_options) {\n console.log(\"startRecordVideo\", _options);\n throw new Error(\"startRecordVideo not supported under the web platform\");\n }\n async getSupportedFlashModes() {\n throw new Error(\"getSupportedFlashModes not supported under the web platform\");\n }\n async getHorizontalFov() {\n throw new Error(\"getHorizontalFov not supported under the web platform\");\n }\n async setFlashMode(_options) {\n throw new Error(`setFlashMode not supported under the web platform${_options}`);\n }\n async flip() {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {\n throw new Error(\"camera is not running\");\n }\n // Stop current stream\n this.stopStream(video.srcObject);\n // Toggle camera position\n this.isBackCamera = !this.isBackCamera;\n // Get new constraints\n const constraints = {\n video: {\n facingMode: this.isBackCamera ? \"environment\" : \"user\",\n width: { ideal: video.videoWidth || 640 },\n height: { ideal: video.videoHeight || 480 },\n },\n };\n try {\n const stream = await navigator.mediaDevices.getUserMedia(constraints);\n video.srcObject = stream;\n // Update current device ID from the new stream\n const videoTrack = stream.getVideoTracks()[0];\n if (videoTrack) {\n this.currentDeviceId = videoTrack.getSettings().deviceId || null;\n }\n // Update video transform based on camera\n if (this.isBackCamera) {\n video.style.transform = \"none\";\n video.style.webkitTransform = \"none\";\n }\n else {\n video.style.transform = \"scaleX(-1)\";\n video.style.webkitTransform = \"scaleX(-1)\";\n }\n await video.play();\n }\n catch (error) {\n throw new Error(`Failed to flip camera: ${error}`);\n }\n }\n async setOpacity(_options) {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (!!video && !!_options.opacity)\n video.style.setProperty(\"opacity\", _options.opacity.toString());\n }\n async isRunning() {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n return { isRunning: !!video && !!video.srcObject };\n }\n async getAvailableDevices() {\n var _a;\n if (!((_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.enumerateDevices)) {\n throw new Error(\"getAvailableDevices not supported under the web platform\");\n }\n const devices = await navigator.mediaDevices.enumerateDevices();\n const videoDevices = devices.filter(device => device.kind === 'videoinput');\n // Group devices by position (front/back)\n const frontDevices = [];\n const backDevices = [];\n videoDevices.forEach((device, index) => {\n const label = device.label || `Camera ${index + 1}`;\n const labelLower = label.toLowerCase();\n // Determine device type based on label\n let deviceType = DeviceType.WIDE_ANGLE;\n let baseZoomRatio = 1.0;\n if (labelLower.includes('ultra') || labelLower.includes('0.5')) {\n deviceType = DeviceType.ULTRA_WIDE;\n baseZoomRatio = 0.5;\n }\n else if (labelLower.includes('telephoto') || labelLower.includes('tele') || labelLower.includes('2x') || labelLower.includes('3x')) {\n deviceType = DeviceType.TELEPHOTO;\n baseZoomRatio = 2.0;\n }\n else if (labelLower.includes('depth') || labelLower.includes('truedepth')) {\n deviceType = DeviceType.TRUE_DEPTH;\n baseZoomRatio = 1.0;\n }\n const lensInfo = {\n deviceId: device.deviceId,\n label,\n deviceType,\n focalLength: 4.25,\n baseZoomRatio,\n minZoom: 1.0,\n maxZoom: 1.0\n };\n // Determine position and add to appropriate array\n if (labelLower.includes('back') || labelLower.includes('rear')) {\n backDevices.push(lensInfo);\n }\n else {\n frontDevices.push(lensInfo);\n }\n });\n const result = [];\n if (frontDevices.length > 0) {\n result.push({\n deviceId: frontDevices[0].deviceId,\n label: \"Front Camera\",\n position: \"front\",\n lenses: frontDevices,\n isLogical: false,\n minZoom: Math.min(...frontDevices.map(d => d.minZoom)),\n maxZoom: Math.max(...frontDevices.map(d => d.maxZoom))\n });\n }\n if (backDevices.length > 0) {\n result.push({\n deviceId: backDevices[0].deviceId,\n label: \"Back Camera\",\n position: \"rear\",\n lenses: backDevices,\n isLogical: false,\n minZoom: Math.min(...backDevices.map(d => d.minZoom)),\n maxZoom: Math.max(...backDevices.map(d => d.maxZoom))\n });\n }\n return { devices: result };\n }\n async getZoom() {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {\n throw new Error(\"camera is not running\");\n }\n const stream = video.srcObject;\n const videoTrack = stream.getVideoTracks()[0];\n if (!videoTrack) {\n throw new Error(\"no video track found\");\n }\n const capabilities = videoTrack.getCapabilities();\n const settings = videoTrack.getSettings();\n if (!capabilities.zoom) {\n throw new Error(\"zoom not supported by this device\");\n }\n // Get current device info to determine lens type\n let deviceType = DeviceType.WIDE_ANGLE;\n let baseZoomRatio = 1.0;\n if (this.currentDeviceId) {\n const devices = await navigator.mediaDevices.enumerateDevices();\n const device = devices.find(d => d.deviceId === this.currentDeviceId);\n if (device) {\n const labelLower = device.label.toLowerCase();\n if (labelLower.includes('ultra') || labelLower.includes('0.5')) {\n deviceType = DeviceType.ULTRA_WIDE;\n baseZoomRatio = 0.5;\n }\n else if (labelLower.includes('telephoto') || labelLower.includes('tele') || labelLower.includes('2x') || labelLower.includes('3x')) {\n deviceType = DeviceType.TELEPHOTO;\n baseZoomRatio = 2.0;\n }\n else if (labelLower.includes('depth') || labelLower.includes('truedepth')) {\n deviceType = DeviceType.TRUE_DEPTH;\n baseZoomRatio = 1.0;\n }\n }\n }\n const currentZoom = settings.zoom || 1;\n const lensInfo = {\n focalLength: 4.25,\n deviceType,\n baseZoomRatio,\n digitalZoom: currentZoom / baseZoomRatio\n };\n return {\n min: capabilities.zoom.min || 1,\n max: capabilities.zoom.max || 1,\n current: currentZoom,\n lens: lensInfo,\n };\n }\n async setZoom(options) {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {\n throw new Error(\"camera is not running\");\n }\n const stream = video.srcObject;\n const videoTrack = stream.getVideoTracks()[0];\n if (!videoTrack) {\n throw new Error(\"no video track found\");\n }\n const capabilities = videoTrack.getCapabilities();\n if (!capabilities.zoom) {\n throw new Error(\"zoom not supported by this device\");\n }\n const zoomLevel = Math.max(capabilities.zoom.min || 1, Math.min(capabilities.zoom.max || 1, options.level));\n try {\n await videoTrack.applyConstraints({\n advanced: [{ zoom: zoomLevel }]\n });\n }\n catch (error) {\n throw new Error(`Failed to set zoom: ${error}`);\n }\n }\n async getFlashMode() {\n throw new Error(\"getFlashMode not supported under the web platform\");\n }\n async getDeviceId() {\n return { deviceId: this.currentDeviceId || \"\" };\n }\n async setDeviceId(options) {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {\n throw new Error(\"camera is not running\");\n }\n // Stop current stream\n this.stopStream(video.srcObject);\n // Update current device ID\n this.currentDeviceId = options.deviceId;\n // Get new constraints with specific device ID\n const constraints = {\n video: {\n deviceId: { exact: options.deviceId },\n width: { ideal: video.videoWidth || 640 },\n height: { ideal: video.videoHeight || 480 },\n },\n };\n try {\n // Try to determine camera position from device\n const devices = await navigator.mediaDevices.enumerateDevices();\n const device = devices.find(d => d.deviceId === options.deviceId);\n this.isBackCamera = (device === null || device === void 0 ? void 0 : device.label.toLowerCase().includes('back')) || (device === null || device === void 0 ? void 0 : device.label.toLowerCase().includes('rear')) || false;\n const stream = await navigator.mediaDevices.getUserMedia(constraints);\n video.srcObject = stream;\n // Update video transform based on camera\n if (this.isBackCamera) {\n video.style.transform = \"none\";\n video.style.webkitTransform = \"none\";\n }\n else {\n video.style.transform = \"scaleX(-1)\";\n video.style.webkitTransform = \"scaleX(-1)\";\n }\n await video.play();\n }\n catch (error) {\n throw new Error(`Failed to swap to device ${options.deviceId}: ${error}`);\n }\n }\n async getAspectRatio() {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (!video) {\n throw new Error(\"camera is not running\");\n }\n const width = video.offsetWidth;\n const height = video.offsetHeight;\n if (width && height) {\n const ratio = width / height;\n // Check for portrait camera ratios: 4:3 -> 3:4, 16:9 -> 9:16\n if (Math.abs(ratio - (3 / 4)) < 0.01) {\n return { aspectRatio: '4:3' };\n }\n if (Math.abs(ratio - (9 / 16)) < 0.01) {\n return { aspectRatio: '16:9' };\n }\n }\n // Default to 4:3 if no specific aspect ratio is matched\n return { aspectRatio: '4:3' };\n }\n async setAspectRatio(options) {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (!video) {\n throw new Error(\"camera is not running\");\n }\n if (options.aspectRatio) {\n const [widthRatio, heightRatio] = options.aspectRatio.split(':').map(Number);\n // For camera, use portrait orientation: 4:3 becomes 3:4, 16:9 becomes 9:16\n const ratio = heightRatio / widthRatio;\n // Get current position and size\n const rect = video.getBoundingClientRect();\n const currentWidth = rect.width;\n const currentHeight = rect.height;\n const currentRatio = currentWidth / currentHeight;\n let newWidth;\n let newHeight;\n if (currentRatio > ratio) {\n // Width is larger, fit by height and center horizontally\n newWidth = currentHeight * ratio;\n newHeight = currentHeight;\n }\n else {\n // Height is larger, fit by width and center vertically\n newWidth = currentWidth;\n newHeight = currentWidth / ratio;\n }\n // Calculate position\n let x, y;\n if (options.x !== undefined && options.y !== undefined) {\n // Use provided coordinates, ensuring they stay within screen boundaries\n x = Math.max(0, Math.min(options.x, window.innerWidth - newWidth));\n y = Math.max(0, Math.min(options.y, window.innerHeight - newHeight));\n }\n else {\n // Auto-center the view\n x = (window.innerWidth - newWidth) / 2;\n y = (window.innerHeight - newHeight) / 2;\n }\n video.style.width = `${newWidth}px`;\n video.style.height = `${newHeight}px`;\n video.style.left = `${x}px`;\n video.style.top = `${y}px`;\n video.style.position = 'absolute';\n return {\n width: Math.round(newWidth),\n height: Math.round(newHeight),\n x: Math.round(x),\n y: Math.round(y)\n };\n }\n else {\n video.style.objectFit = 'cover';\n const rect = video.getBoundingClientRect();\n return {\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n x: Math.round(rect.left),\n y: Math.round(rect.top)\n };\n }\n }\n createGridOverlay(gridMode) {\n const overlay = document.createElement(\"div\");\n overlay.style.position = \"absolute\";\n overlay.style.top = \"0\";\n overlay.style.left = \"0\";\n overlay.style.width = \"100%\";\n overlay.style.height = \"100%\";\n overlay.style.pointerEvents = \"none\";\n overlay.style.zIndex = \"10\";\n const divisions = gridMode === \"3x3\" ? 3 : 4;\n // Create SVG for grid lines\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.style.width = \"100%\";\n svg.style.height = \"100%\";\n svg.style.position = \"absolute\";\n svg.style.top = \"0\";\n svg.style.left = \"0\";\n // Create grid lines\n for (let i = 1; i < divisions; i++) {\n // Vertical lines\n const verticalLine = document.createElementNS(\"http://www.w3.org/2000/svg\", \"line\");\n verticalLine.setAttribute(\"x1\", `${(i / divisions) * 100}%`);\n verticalLine.setAttribute(\"y1\", \"0%\");\n verticalLine.setAttribute(\"x2\", `${(i / divisions) * 100}%`);\n verticalLine.setAttribute(\"y2\", \"100%\");\n verticalLine.setAttribute(\"stroke\", \"rgba(255, 255, 255, 0.5)\");\n verticalLine.setAttribute(\"stroke-width\", \"1\");\n svg.appendChild(verticalLine);\n // Horizontal lines\n const horizontalLine = document.createElementNS(\"http://www.w3.org/2000/svg\", \"line\");\n horizontalLine.setAttribute(\"x1\", \"0%\");\n horizontalLine.setAttribute(\"y1\", `${(i / divisions) * 100}%`);\n horizontalLine.setAttribute(\"x2\", \"100%\");\n horizontalLine.setAttribute(\"y2\", `${(i / divisions) * 100}%`);\n horizontalLine.setAttribute(\"stroke\", \"rgba(255, 255, 255, 0.5)\");\n horizontalLine.setAttribute(\"stroke-width\", \"1\");\n svg.appendChild(horizontalLine);\n }\n overlay.appendChild(svg);\n return overlay;\n }\n async setGridMode(options) {\n // Web implementation of grid mode would need to be implemented\n // For now, just resolve as a no-op\n console.warn(`Grid mode '${options.gridMode}' is not yet implemented for web platform`);\n }\n async getGridMode() {\n // Web implementation - default to none\n return { gridMode: 'none' };\n }\n async getPreviewSize() {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (!video) {\n throw new Error(\"camera is not running\");\n }\n return {\n x: video.offsetLeft,\n y: video.offsetTop,\n width: video.width,\n height: video.height\n };\n }\n async setPreviewSize(options) {\n const video = document.getElementById(DEFAULT_VIDEO_ID);\n if (!video) {\n throw new Error(\"camera is not running\");\n }\n video.style.left = `${options.x}px`;\n video.style.top = `${options.y}px`;\n video.width = options.width;\n video.height = options.height;\n return {\n width: options.width,\n height: options.height,\n x: options.x,\n y: options.y\n };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["DeviceType","registerPlugin","WebPlugin"],"mappings":"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"}
@@ -8,6 +8,7 @@
8
8
 
9
9
  import AVFoundation
10
10
  import UIKit
11
+ import CoreLocation
11
12
 
12
13
  class CameraController: NSObject {
13
14
  var captureSession: AVCaptureSession?
@@ -26,6 +27,7 @@ class CameraController: NSObject {
26
27
  var fileVideoOutput: AVCaptureMovieFileOutput?
27
28
 
28
29
  var previewLayer: AVCaptureVideoPreviewLayer?
30
+ var gridOverlayView: GridOverlayView?
29
31
 
30
32
  var flashMode = AVCaptureDevice.FlashMode.off
31
33
  var photoCaptureCompletionBlock: ((UIImage?, Error?) -> Void)?
@@ -38,6 +40,8 @@ class CameraController: NSObject {
38
40
  var audioInput: AVCaptureDeviceInput?
39
41
 
40
42
  var zoomFactor: CGFloat = 1.0
43
+ private var lastZoomUpdateTime: TimeInterval = 0
44
+ private let zoomUpdateThrottle: TimeInterval = 1.0 / 60.0 // 60 FPS max
41
45
 
42
46
  var videoFileURL: URL?
43
47
  private let saneMaxZoomFactor: CGFloat = 25.5
@@ -50,12 +54,59 @@ class CameraController: NSObject {
50
54
  }
51
55
 
52
56
  extension CameraController {
53
- func prepare(cameraPosition: String, deviceId: String? = nil, disableAudio: Bool, cameraMode: Bool, completionHandler: @escaping (Error?) -> Void) {
57
+ func prepareBasicSession() {
58
+ // Only prepare if we don't already have a session
59
+ guard self.captureSession == nil else { return }
60
+
61
+ print("[CameraPreview] Preparing basic camera session in background")
62
+
63
+ // Create basic capture session
64
+ self.captureSession = AVCaptureSession()
65
+
66
+ // Configure basic devices without full preparation
67
+ let deviceTypes: [AVCaptureDevice.DeviceType] = [
68
+ .builtInWideAngleCamera,
69
+ .builtInUltraWideCamera,
70
+ .builtInTelephotoCamera,
71
+ .builtInDualCamera,
72
+ .builtInDualWideCamera,
73
+ .builtInTripleCamera,
74
+ .builtInTrueDepthCamera
75
+ ]
76
+
77
+ let session = AVCaptureDevice.DiscoverySession(deviceTypes: deviceTypes, mediaType: AVMediaType.video, position: .unspecified)
78
+ let cameras = session.devices.compactMap { $0 }
79
+
80
+ // Find best cameras
81
+ let rearVirtualDevices = cameras.filter { $0.position == .back && $0.isVirtualDevice }
82
+ let bestRearVirtualDevice = rearVirtualDevices.max { $0.constituentDevices.count < $1.constituentDevices.count }
83
+
84
+ self.frontCamera = cameras.first(where: { $0.position == .front })
85
+
86
+ if let bestCamera = bestRearVirtualDevice {
87
+ self.rearCamera = bestCamera
88
+ } else if let firstRearCamera = cameras.first(where: { $0.position == .back }) {
89
+ self.rearCamera = firstRearCamera
90
+ }
91
+
92
+ print("[CameraPreview] Basic session prepared with \(cameras.count) devices")
93
+ }
94
+
95
+ func prepare(cameraPosition: String, deviceId: String? = nil, disableAudio: Bool, cameraMode: Bool, aspectRatio: String? = nil, completionHandler: @escaping (Error?) -> Void) {
54
96
  func createCaptureSession() {
55
- self.captureSession = AVCaptureSession()
97
+ // Use existing session if available from background preparation
98
+ if self.captureSession == nil {
99
+ self.captureSession = AVCaptureSession()
100
+ }
56
101
  }
57
102
 
58
103
  func configureCaptureDevices() throws {
104
+ // Skip device discovery if cameras are already found during background preparation
105
+ if self.frontCamera != nil || self.rearCamera != nil {
106
+ print("[CameraPreview] Using pre-discovered cameras")
107
+ return
108
+ }
109
+
59
110
  // Expanded device types to support more camera configurations
60
111
  let deviceTypes: [AVCaptureDevice.DeviceType] = [
61
112
  .builtInWideAngleCamera,
@@ -203,11 +254,65 @@ extension CameraController {
203
254
  func configurePhotoOutput(cameraMode: Bool) throws {
204
255
  guard let captureSession = self.captureSession else { throw CameraControllerError.captureSessionIsMissing }
205
256
 
206
- // TODO: check if that really useful
207
- if !cameraMode && self.highResolutionOutput && captureSession.canSetSessionPreset(.photo) {
208
- captureSession.sessionPreset = .photo
209
- } else if cameraMode && self.highResolutionOutput && captureSession.canSetSessionPreset(.high) {
210
- captureSession.sessionPreset = .high
257
+ // Configure session preset for high-quality preview
258
+ // Prioritize higher quality presets for better preview resolution
259
+ var targetPreset: AVCaptureSession.Preset = .high // Default to high quality
260
+
261
+ if let aspectRatio = aspectRatio {
262
+ switch aspectRatio {
263
+ case "16:9":
264
+ // Use highest available HD preset for 16:9 aspect ratio
265
+ if captureSession.canSetSessionPreset(.hd4K3840x2160) {
266
+ targetPreset = .hd4K3840x2160
267
+ } else if captureSession.canSetSessionPreset(.hd1920x1080) {
268
+ targetPreset = .hd1920x1080
269
+ } else if captureSession.canSetSessionPreset(.hd1280x720) {
270
+ targetPreset = .hd1280x720
271
+ } else {
272
+ targetPreset = .high
273
+ }
274
+ case "4:3":
275
+ // Use photo preset for 4:3 aspect ratio (highest quality)
276
+ if captureSession.canSetSessionPreset(.photo) {
277
+ targetPreset = .photo
278
+ } else if captureSession.canSetSessionPreset(.high) {
279
+ targetPreset = .high
280
+ } else {
281
+ targetPreset = .medium
282
+ }
283
+ default:
284
+ // Default to highest available quality
285
+ if captureSession.canSetSessionPreset(.photo) {
286
+ targetPreset = .photo
287
+ } else if captureSession.canSetSessionPreset(.high) {
288
+ targetPreset = .high
289
+ } else {
290
+ targetPreset = .medium
291
+ }
292
+ }
293
+ } else {
294
+ // Default to highest available quality when no aspect ratio specified
295
+ if captureSession.canSetSessionPreset(.photo) {
296
+ targetPreset = .photo
297
+ } else if captureSession.canSetSessionPreset(.high) {
298
+ targetPreset = .high
299
+ } else {
300
+ targetPreset = .medium
301
+ }
302
+ }
303
+
304
+ // Apply the determined preset
305
+ if captureSession.canSetSessionPreset(targetPreset) {
306
+ captureSession.sessionPreset = targetPreset
307
+ print("[CameraPreview] Set session preset to \(targetPreset) for aspect ratio: \(aspectRatio ?? "default")")
308
+ } else {
309
+ // Fallback to high quality preset if the target preset is not supported
310
+ print("[CameraPreview] Target preset \(targetPreset) not supported, falling back to .high")
311
+ if captureSession.canSetSessionPreset(.high) {
312
+ captureSession.sessionPreset = .high
313
+ } else if captureSession.canSetSessionPreset(.medium) {
314
+ captureSession.sessionPreset = .medium
315
+ }
211
316
  }
212
317
 
213
318
  self.photoOutput = AVCapturePhotoOutput()
@@ -266,15 +371,51 @@ extension CameraController {
266
371
  func displayPreview(on view: UIView) throws {
267
372
  guard let captureSession = self.captureSession, captureSession.isRunning else { throw CameraControllerError.captureSessionIsMissing }
268
373
 
374
+ print("[CameraPreview] displayPreview called with view frame: \(view.frame)")
375
+
269
376
  self.previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
270
377
  self.previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
271
378
 
379
+ // Optimize preview layer for better quality
380
+ self.previewLayer?.connection?.videoOrientation = .portrait
381
+ self.previewLayer?.isOpaque = true
382
+
383
+ // Enable high-quality rendering
384
+ if #available(iOS 13.0, *) {
385
+ self.previewLayer?.videoGravity = .resizeAspectFill
386
+ }
387
+
272
388
  view.layer.insertSublayer(self.previewLayer!, at: 0)
273
- self.previewLayer?.frame = view.frame
389
+
390
+ // Disable animation for frame update
391
+ CATransaction.begin()
392
+ CATransaction.setDisableActions(true)
393
+ self.previewLayer?.frame = view.bounds
394
+ CATransaction.commit()
395
+
396
+ print("[CameraPreview] Set preview layer frame to view bounds: \(view.bounds)")
397
+ print("[CameraPreview] Session preset: \(captureSession.sessionPreset.rawValue)")
274
398
 
275
399
  updateVideoOrientation()
276
400
  }
277
401
 
402
+ func addGridOverlay(to view: UIView, gridMode: String) {
403
+ removeGridOverlay()
404
+
405
+ // Disable animation for grid overlay creation and positioning
406
+ CATransaction.begin()
407
+ CATransaction.setDisableActions(true)
408
+ gridOverlayView = GridOverlayView(frame: view.bounds)
409
+ gridOverlayView?.gridMode = gridMode
410
+ view.addSubview(gridOverlayView!)
411
+ CATransaction.commit()
412
+ }
413
+
414
+ func removeGridOverlay() {
415
+ gridOverlayView?.removeFromSuperview()
416
+ gridOverlayView = nil
417
+ }
418
+
278
419
  func setupGestures(target: UIView, enableZoom: Bool) {
279
420
  setupTapGesture(target: target, selector: #selector(handleTap(_:)), delegate: self)
280
421
  if enableZoom {
@@ -291,6 +432,10 @@ extension CameraController {
291
432
  func setupPinchGesture(target: UIView, selector: Selector, delegate: UIGestureRecognizerDelegate?) {
292
433
  let pinchGesture = UIPinchGestureRecognizer(target: self, action: selector)
293
434
  pinchGesture.delegate = delegate
435
+ // Optimize gesture recognition for better performance
436
+ pinchGesture.delaysTouchesBegan = false
437
+ pinchGesture.delaysTouchesEnded = false
438
+ pinchGesture.cancelsTouchesInView = false
294
439
  target.addGestureRecognizer(pinchGesture)
295
440
  }
296
441
 
@@ -427,15 +572,75 @@ extension CameraController {
427
572
  }
428
573
  }
429
574
 
430
- func captureImage(completion: @escaping (UIImage?, Error?) -> Void) {
431
- guard let captureSession = captureSession, captureSession.isRunning else { completion(nil, CameraControllerError.captureSessionIsMissing); return }
575
+ func captureImage(width: Int?, height: Int?, quality: Float, gpsLocation: CLLocation?, completion: @escaping (UIImage?, Error?) -> Void) {
576
+ guard let photoOutput = self.photoOutput else {
577
+ completion(nil, NSError(domain: "Camera", code: 0, userInfo: [NSLocalizedDescriptionKey: "Photo output is not available"]))
578
+ return
579
+ }
580
+
432
581
  let settings = AVCapturePhotoSettings()
433
582
 
434
- settings.flashMode = self.flashMode
435
- settings.isHighResolutionPhotoEnabled = self.highResolutionOutput
583
+ self.photoCaptureCompletionBlock = { (image, error) in
584
+ if let error = error {
585
+ completion(nil, error)
586
+ return
587
+ }
588
+
589
+ guard let image = image else {
590
+ completion(nil, NSError(domain: "Camera", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to capture image"]))
591
+ return
592
+ }
593
+
594
+ if let location = gpsLocation {
595
+ self.addGPSMetadata(to: image, location: location)
596
+ }
597
+
598
+ if let width = width, let height = height {
599
+ let resizedImage = self.resizeImage(image: image, to: CGSize(width: width, height: height))
600
+ completion(resizedImage, nil)
601
+ } else {
602
+ completion(image, nil)
603
+ }
604
+ }
605
+
606
+ photoOutput.capturePhoto(with: settings, delegate: self)
607
+ }
608
+
609
+ func addGPSMetadata(to image: UIImage, location: CLLocation) {
610
+ guard let jpegData = image.jpegData(compressionQuality: 1.0),
611
+ let source = CGImageSourceCreateWithData(jpegData as CFData, nil),
612
+ let uti = CGImageSourceGetType(source) else { return }
613
+
614
+ var metadata = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [String: Any] ?? [:]
615
+
616
+ let formatter = DateFormatter()
617
+ formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
618
+ formatter.timeZone = TimeZone(abbreviation: "UTC")
619
+
620
+ let gpsDict: [String: Any] = [
621
+ kCGImagePropertyGPSLatitude as String: abs(location.coordinate.latitude),
622
+ kCGImagePropertyGPSLatitudeRef as String: location.coordinate.latitude >= 0 ? "N" : "S",
623
+ kCGImagePropertyGPSLongitude as String: abs(location.coordinate.longitude),
624
+ kCGImagePropertyGPSLongitudeRef as String: location.coordinate.longitude >= 0 ? "E" : "W",
625
+ kCGImagePropertyGPSTimeStamp as String: formatter.string(from: location.timestamp),
626
+ kCGImagePropertyGPSAltitude as String: location.altitude,
627
+ kCGImagePropertyGPSAltitudeRef as String: location.altitude >= 0 ? 0 : 1
628
+ ]
629
+
630
+ metadata[kCGImagePropertyGPSDictionary as String] = gpsDict
631
+
632
+ let destData = NSMutableData()
633
+ guard let destination = CGImageDestinationCreateWithData(destData, uti, 1, nil) else { return }
634
+ CGImageDestinationAddImageFromSource(destination, source, 0, metadata as CFDictionary)
635
+ CGImageDestinationFinalize(destination)
636
+ }
436
637
 
437
- self.photoOutput?.capturePhoto(with: settings, delegate: self)
438
- self.photoCaptureCompletionBlock = completion
638
+ func resizeImage(image: UIImage, to size: CGSize) -> UIImage? {
639
+ let renderer = UIGraphicsImageRenderer(size: size)
640
+ let resizedImage = renderer.image { (context) in
641
+ image.draw(in: CGRect(origin: .zero, size: size))
642
+ }
643
+ return resizedImage
439
644
  }
440
645
 
441
646
  func captureSample(completion: @escaping (UIImage?, Error?) -> Void) {
@@ -633,7 +838,8 @@ extension CameraController {
633
838
  try device.lockForConfiguration()
634
839
 
635
840
  if ramp {
636
- device.ramp(toVideoZoomFactor: zoomLevel, withRate: 1.0)
841
+ // Use a very fast ramp rate for immediate response
842
+ device.ramp(toVideoZoomFactor: zoomLevel, withRate: 8.0)
637
843
  } else {
638
844
  device.videoZoomFactor = zoomLevel
639
845
  }
@@ -677,7 +883,7 @@ extension CameraController {
677
883
 
678
884
  return device.uniqueID
679
885
  }
680
-
886
+
681
887
  func getCurrentLensInfo() throws -> (focalLength: Float, deviceType: String, baseZoomRatio: Float) {
682
888
  var currentCamera: AVCaptureDevice?
683
889
  switch currentCameraPosition {
@@ -933,31 +1139,42 @@ extension CameraController: UIGestureRecognizerDelegate {
933
1139
  }
934
1140
  }
935
1141
 
936
- @objc
1142
+ @objc
937
1143
  private func handlePinch(_ pinch: UIPinchGestureRecognizer) {
938
1144
  guard let device = self.currentCameraPosition == .rear ? rearCamera : frontCamera else { return }
939
1145
 
940
1146
  let effectiveMaxZoom = min(device.maxAvailableVideoZoomFactor, self.saneMaxZoomFactor)
941
1147
  func minMaxZoom(_ factor: CGFloat) -> CGFloat { return max(device.minAvailableVideoZoomFactor, min(factor, effectiveMaxZoom)) }
942
1148
 
943
- func update(scale factor: CGFloat) {
1149
+ switch pinch.state {
1150
+ case .began:
1151
+ // Store the initial zoom factor when pinch begins
1152
+ zoomFactor = device.videoZoomFactor
1153
+
1154
+ case .changed:
1155
+ // Throttle zoom updates to prevent excessive CPU usage
1156
+ let currentTime = CACurrentMediaTime()
1157
+ guard currentTime - lastZoomUpdateTime >= zoomUpdateThrottle else { return }
1158
+ lastZoomUpdateTime = currentTime
1159
+
1160
+ // Calculate new zoom factor based on pinch scale
1161
+ let newScaleFactor = minMaxZoom(pinch.scale * zoomFactor)
1162
+
1163
+ // Use ramping for smooth zoom transitions during pinch
1164
+ // This provides much smoother performance than direct setting
944
1165
  do {
945
1166
  try device.lockForConfiguration()
946
- defer { device.unlockForConfiguration() }
947
-
948
- device.videoZoomFactor = factor
1167
+ // Use a very fast ramp rate for immediate response
1168
+ device.ramp(toVideoZoomFactor: newScaleFactor, withRate: 5.0)
1169
+ device.unlockForConfiguration()
949
1170
  } catch {
950
- debugPrint(error)
1171
+ debugPrint("Failed to set zoom: \(error)")
951
1172
  }
952
- }
953
1173
 
954
- switch pinch.state {
955
- case .began: fallthrough
956
- case .changed:
957
- let newScaleFactor = minMaxZoom(pinch.scale * zoomFactor)
958
- update(scale: newScaleFactor)
959
1174
  case .ended:
1175
+ // Update our internal zoom factor tracking
960
1176
  zoomFactor = device.videoZoomFactor
1177
+
961
1178
  default: break
962
1179
  }
963
1180
  }
@@ -0,0 +1,65 @@
1
+ import UIKit
2
+
3
+ class GridOverlayView: UIView {
4
+
5
+ var gridMode: String = "none" {
6
+ didSet {
7
+ isHidden = gridMode == "none"
8
+ setNeedsDisplay()
9
+ }
10
+ }
11
+
12
+ override init(frame: CGRect) {
13
+ super.init(frame: frame)
14
+ setup()
15
+ }
16
+
17
+ required init?(coder: NSCoder) {
18
+ super.init(coder: coder)
19
+ setup()
20
+ }
21
+
22
+ private func setup() {
23
+ backgroundColor = UIColor.clear
24
+ isUserInteractionEnabled = false
25
+ isHidden = true
26
+ }
27
+
28
+ override func draw(_ rect: CGRect) {
29
+ guard let context = UIGraphicsGetCurrentContext() else { return }
30
+
31
+ if gridMode == "none" {
32
+ return
33
+ }
34
+
35
+ context.setStrokeColor(UIColor.white.withAlphaComponent(0.5).cgColor)
36
+ context.setLineWidth(1.0)
37
+
38
+ if gridMode == "3x3" {
39
+ drawGrid(context: context, rect: rect, divisions: 3)
40
+ } else if gridMode == "4x4" {
41
+ drawGrid(context: context, rect: rect, divisions: 4)
42
+ }
43
+ }
44
+
45
+ private func drawGrid(context: CGContext, rect: CGRect, divisions: Int) {
46
+ let stepX = rect.width / CGFloat(divisions)
47
+ let stepY = rect.height / CGFloat(divisions)
48
+
49
+ // Draw vertical lines
50
+ for i in 1..<divisions {
51
+ let x = CGFloat(i) * stepX
52
+ context.move(to: CGPoint(x: x, y: 0))
53
+ context.addLine(to: CGPoint(x: x, y: rect.height))
54
+ }
55
+
56
+ // Draw horizontal lines
57
+ for i in 1..<divisions {
58
+ let y = CGFloat(i) * stepY
59
+ context.move(to: CGPoint(x: 0, y: y))
60
+ context.addLine(to: CGPoint(x: rect.width, y: y))
61
+ }
62
+
63
+ context.strokePath()
64
+ }
65
+ }