Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions Sources/IONCameraLib/Interfaces/IONCAMRGalleryBehaviour.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -57,15 +58,17 @@ extension IONCAMRGalleryBehaviour {
allowMultipleSelection: Bool,
limit: Int = 0,
thumbnailAsData: Bool,
presentationStyle: IONCAMRPresentationStyle = .fullscreen
presentationStyle: IONCAMRPresentationStyle = .fullscreen,
targetSize: IONCAMRSize? = nil
)
-> UIViewController {
let photoLibraryService = IONCAMRPhotoLibraryService(
delegate: self,
metadataGetter: metadataGetter,
mediaTypeArray: mediaTypes,
thumbnailAsData: thumbnailAsData,
returnMetadata: returnMetadata
returnMetadata: returnMetadata,
targetSize: targetSize
)
let photoLibraryView = IONCAMRPhotoLibraryView(allowMultipleSelection: allowMultipleSelection, limit: limit)
.environmentObject(photoLibraryService)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)
}
Expand Down Expand Up @@ -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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the resize would be to the exact dimensions, but it seems that it does it an way that makes it such that it can switch up the dimensions. I think the capacitor example app doesn't show the thumbnail so it makes it hard to tell (related to my other comment), but this logic probably comes from the old cordova plugin / native library, but just checking if it's by design.

        // Figure out what our orientation is, and use that to form the rectangle
        let newSize = if widthRatio > heightRatio {
            CGSize(width: sourceImage.size.width * heightRatio, height: sourceImage.size.height * heightRatio)
        } else {
            CGSize(width: sourceImage.size.width * widthRatio, height: sourceImage.size.height * widthRatio)
        }

Because if it is, maybe we need to see what Android should do, and update the docs on what targetWidth / targetHeight are meant to be?

let quality = CGFloat(IONCAMRTakePhotoOptions.ThumbnailDefaultConfigurations.quality) / 100
guard let data = resized.jpegData(compressionQuality: quality)?.base64EncodedString()
else { throw IONCAMRError.imageNotFound }
finalImage = resized
imageData = data
Comment on lines +166 to +171

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if this should be applied to only the thumbnail or also the image URI being returned (i.e. save the image to a new URI, possibly cache, and return that instead)?

Also, targetWidth / targetHeight doesn't seem to get applied if we pass something in "editable". Possibly it goes through a different flow?

} 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)
Expand Down
17 changes: 14 additions & 3 deletions Sources/IONCameraLib/Models/IONCAMRGalleryOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -48,18 +52,25 @@ 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,
allowMultipleSelection: allowMultipleSelection,
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
}
}
Loading