In this guide, you’ll learn how to access the still photos produced by the IMGLY Camera when it’s used as a standalone capture surface. This covers single-camera and dual-camera captures in the .photo and .mixed capture types.
What You’ll Learn#
- How to receive photos by configuring the camera’s
captureType. - How to read the
onDismissresult and extract the captured photos. - How single-camera and dual-camera sessions populate
Photo.images. - How to persist the temporary photo files for later use.
Camera Permission#
Capturing photos requires camera access. iOS terminates the app on first use of the camera unless your Info.plist declares a usage description, so add the NSCameraUsageDescription key with a short explanation shown in the system permission prompt:
<key>NSCameraUsageDescription</key><string>We need access to your camera to capture photos.</string>The IMGLY Camera presents the system permission request the first time it opens; your app only needs to supply this description string.
Capture Photos#
Photos are delivered only when the camera captures stills, so set the captureType to .photo (photos only) or .mixed (a user-toggleable photo/video mode) on a CameraConfiguration. See the Mobile Camera Configuration guide for the full set of options, and the Integrate Mobile Camera guide for presenting the camera in your app.
let settings = EngineSettings(license: "<your license key>")let photoConfig = CameraConfiguration(captureType: .photo)
Camera(settings, config: photoConfig) { result in // Read the captured photos from `result` here.}Read the Result#
The Camera’s onDismiss closure returns a Result<CameraResult, CameraError>. A non-reaction session delivers CameraResult.capture([Capture]), where each Capture is either a .photo(Photo) or a .video(Recording). There’s a [Capture].videos helper for pulling out recordings; photos have no equivalent helper, so filter them with compactMap:
Camera(settings, config: photoConfig) { result in switch result { case let .success(.capture(captures)): let photos = captures.compactMap { capture in if case let .photo(photo) = capture { return photo } return nil }
for photo in photos { for image in photo.images { let url = image.url // JPEG file in the temporary directory let rect = image.rect // Position within the camera's 1080×1920 canvas print(url, rect) } }
case .success(.reaction): break // Reaction sessions return videos — see the Access Recordings guide.
case let .failure(error): print(error.localizedDescription) }}Each Photo exposes its captured images in photo.images. Every Photo.Image carries the file url of the saved JPEG and a rect describing where the image sat within the camera’s 1080×1920 canvas.
Single and Dual Camera Photos#
The number of entries in photo.images depends on the camera mode:
- Single camera captures one image, so
photo.imageshas a single element whoserectcovers the full canvas. - Dual camera captures two stacked images — one per lens — so
photo.imageshas two elements, each with its ownrectmarking the section of the layout it came from.
Use each image’s rect to recreate the dual-camera layout in your own editing flow. For the layout modes that dual capture produces, see the Dual Camera guide.
Persist the Photos#
The url on each Photo.Image points at a file in the app’s temporary directory. Treat these URLs as transient: copy or move them to an app-managed location, such as the documents directory, before relying on them later.
func persistPhoto(at sourceURL: URL, fileName: String) throws -> URL { let documentsURL = try FileManager.default.url( for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true ) let destinationURL = documentsURL.appendingPathComponent(fileName)
if FileManager.default.fileExists(atPath: destinationURL.path) { try FileManager.default.removeItem(at: destinationURL) }
try FileManager.default.copyItem(at: sourceURL, to: destinationURL) // Use `moveItem(at:to:)` instead if you don't need the original temp file. return destinationURL}Handle Failures#
The .failure case carries a CameraError. Two of its cases apply to a photo session:
.cancelled— the user dismissed the camera without capturing. Handle this silently; don’t show an error..permissionsMissing— the user denied camera access. Guide them to enable it in Settings.
Switch over the error to handle them; .failedToLoadVideo only occurs in reaction sessions:
switch error {case .cancelled: break // Dismiss the camera UI without an error.case .permissionsMissing: break // Prompt the user to grant camera access.case .failedToLoadVideo: break // Reaction sessions only.}Next Steps#
Captured photos are JPEG files, so they load directly into the engine’s image APIs once you’ve persisted them. From here you can:
- Take Photo — Learn how to capture a photo with the Mobile Camera.
- Import Local Asset — Insert a captured photo into a scene from a local file.
- From Photo Roll — Let users pick existing photos from their library inside the editor.
- Access Recordings — Handle the videos and reactions returned by the same camera session.