diff --git a/Sources/IONCameraLib/Interfaces/IONCAMRGalleryBehaviour.swift b/Sources/IONCameraLib/Interfaces/IONCAMRGalleryBehaviour.swift index 3add4b0..580e3d5 100644 --- a/Sources/IONCameraLib/Interfaces/IONCAMRGalleryBehaviour.swift +++ b/Sources/IONCameraLib/Interfaces/IONCAMRGalleryBehaviour.swift @@ -43,7 +43,8 @@ final class IONCAMRGalleryBehaviour: NSObject, IONCAMRGalleryDelegate { allowMultipleSelection: options.allowMultipleSelection, limit: options.limit, thumbnailAsData: options.thumbnailAsData, - presentationStyle: options.presentationStyle + presentationStyle: options.presentationStyle, + targetSize: options.size ) handler(viewController) @@ -57,7 +58,8 @@ extension IONCAMRGalleryBehaviour { allowMultipleSelection: Bool, limit: Int = 0, thumbnailAsData: Bool, - presentationStyle: IONCAMRPresentationStyle = .fullscreen + presentationStyle: IONCAMRPresentationStyle = .fullscreen, + targetSize: IONCAMRSize? = nil ) -> UIViewController { let photoLibraryService = IONCAMRPhotoLibraryService( @@ -65,7 +67,8 @@ extension IONCAMRGalleryBehaviour { metadataGetter: metadataGetter, mediaTypeArray: mediaTypes, thumbnailAsData: thumbnailAsData, - returnMetadata: returnMetadata + returnMetadata: returnMetadata, + targetSize: targetSize ) let photoLibraryView = IONCAMRPhotoLibraryView(allowMultipleSelection: allowMultipleSelection, limit: limit) .environmentObject(photoLibraryService) diff --git a/Sources/IONCameraLib/Interfaces/PhotoLibrary/IONCAMRPhotoLibraryService.swift b/Sources/IONCameraLib/Interfaces/PhotoLibrary/IONCAMRPhotoLibraryService.swift index 3e1a1be..af717f5 100644 --- a/Sources/IONCameraLib/Interfaces/PhotoLibrary/IONCAMRPhotoLibraryService.swift +++ b/Sources/IONCameraLib/Interfaces/PhotoLibrary/IONCAMRPhotoLibraryService.swift @@ -18,6 +18,7 @@ class IONCAMRPhotoLibraryService: NSObject, ObservableObject { private let mediaTypeArray: [PHAssetMediaType] private let thumbnailAsData: Bool private let returnMetadata: Bool + private let targetSize: IONCAMRSize? /// The manager that will fetch and cache photos for us var imageCachingManager = PHCachingImageManager() @@ -31,13 +32,15 @@ class IONCAMRPhotoLibraryService: NSObject, ObservableObject { metadataGetter: IONCAMRMetadataGetterDelegate, mediaTypeArray: [PHAssetMediaType], thumbnailAsData: Bool, - returnMetadata: Bool + returnMetadata: Bool, + targetSize: IONCAMRSize? = nil ) { self.delegate = delegate self.metadataGetter = metadataGetter self.mediaTypeArray = mediaTypeArray self.thumbnailAsData = thumbnailAsData self.returnMetadata = returnMetadata + self.targetSize = targetSize super.init() PHPhotoLibrary.shared().register(self) } @@ -154,13 +157,28 @@ extension IONCAMRPhotoLibraryService { private func fetchImage(from asset: PHAsset) async throws -> IONCAMRMediaResult { guard let image = try await fetchImage(byLocalIdentifier: asset.localIdentifier), - let imageData = image.pictureThumbnailData(), let imageURL = try await fetchImageURL(for: asset) else { throw IONCAMRError.imageNotFound } + let finalImage: UIImage + let imageData: String + if let size = targetSize { + let resized = image.resizeTo(CGSize(size: size)) ?? image + let quality = CGFloat(IONCAMRTakePhotoOptions.ThumbnailDefaultConfigurations.quality) / 100 + guard let data = resized.jpegData(compressionQuality: quality)?.base64EncodedString() + else { throw IONCAMRError.imageNotFound } + finalImage = resized + imageData = data + } else { + guard let data = image.pictureThumbnailData() + else { throw IONCAMRError.imageNotFound } + finalImage = image + imageData = data + } + var metadata: IONCAMRMetadata? if returnMetadata { - metadata = try? metadataGetter.getImageMetadata(from: image, and: imageURL) + metadata = try? metadataGetter.getImageMetadata(from: finalImage, and: imageURL) } return IONCAMRMediaResult(pictureWith: imageURL.absoluteString, imageData, and: metadata) diff --git a/Sources/IONCameraLib/Models/IONCAMRGalleryOptions.swift b/Sources/IONCameraLib/Models/IONCAMRGalleryOptions.swift index 4bf47e1..58a537f 100644 --- a/Sources/IONCameraLib/Models/IONCAMRGalleryOptions.swift +++ b/Sources/IONCameraLib/Models/IONCAMRGalleryOptions.swift @@ -13,6 +13,8 @@ public class IONCAMRGalleryOptions: IONCAMREditMediaTypeOptionsDelegate, Decodab public let limit: Int /// Presentation style to use when showing the gallery interface. Default is `.fullscreen`. public let presentationStyle: IONCAMRPresentationStyle + /// Target dimensions for the returned image. Both targetWidth and targetHeight must be provided; if only one is given, this is ignored. + public let size: IONCAMRSize? init( mediaType: IONCAMRMediaType, @@ -21,7 +23,8 @@ public class IONCAMRGalleryOptions: IONCAMREditMediaTypeOptionsDelegate, Decodab andThumbnailAsData: Bool, returnMetadata: Bool, limit: Int = 0, - presentationStyle: IONCAMRPresentationStyle = .fullscreen + presentationStyle: IONCAMRPresentationStyle = .fullscreen, + size: IONCAMRSize? = nil ) { self.mediaType = mediaType self.allowEdit = allowEdit @@ -30,6 +33,7 @@ public class IONCAMRGalleryOptions: IONCAMREditMediaTypeOptionsDelegate, Decodab self.returnMetadata = returnMetadata self.limit = limit self.presentationStyle = presentationStyle + self.size = size } public required convenience init(from decoder: Decoder) throws { @@ -48,6 +52,12 @@ public class IONCAMRGalleryOptions: IONCAMREditMediaTypeOptionsDelegate, Decodab let returnMetadata = try container.decodeIfPresent(Bool.self, forKey: .includeMetadata) ?? false let limit = try container.decodeIfPresent(Int.self, forKey: .limit) ?? 0 let presentationStyle = try container.decodeIfPresent(IONCAMRPresentationStyle.self, forKey: .presentationStyle) ?? .fullscreen + let width = try container.decodeIfPresent(Int.self, forKey: .targetWidth) + let height = try container.decodeIfPresent(Int.self, forKey: .targetHeight) + var size: IONCAMRSize? + if let width, let height { + size = try? IONCAMRSize(width: width, height: height) + } self.init( mediaType: mediaType, allowEdit: allowEdit, @@ -55,11 +65,12 @@ public class IONCAMRGalleryOptions: IONCAMREditMediaTypeOptionsDelegate, Decodab andThumbnailAsData: thumbnailAsData, returnMetadata: returnMetadata, limit: limit, - presentationStyle: presentationStyle + presentationStyle: presentationStyle, + size: size ) } private enum CodingKeys: String, CodingKey { - case mediaType, editable, allowMultipleSelection, thumbnailAsData, includeMetadata, limit, presentationStyle + case mediaType, editable, allowMultipleSelection, thumbnailAsData, includeMetadata, limit, presentationStyle, targetWidth, targetHeight } }