-
Notifications
You must be signed in to change notification settings - Fork 0
/
IImagePicker.swift
190 lines (168 loc) · 7.26 KB
/
IImagePicker.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// swiftlint:disable all
// IIImagePicker.swift
#if os(iOS)
import UIKit
import MobileCoreServices
#endif
import AVFoundation
public typealias IImagePickerDelegate = UIImagePickerControllerDelegate & UINavigationControllerDelegate
public final class IImagePicker: NSObject {
private var picker: UIImagePickerController?
private var tune: Tuning!
public var onPickImage: ((IResource, IImagePicker)->())?,
onCancel: (()->())?,
onError: (()->())?,
onPickVideoURL: ((URL, IImagePicker)->())?
// MARK:- Inits
public override init() {
super.init()
picker = UIImagePickerController()
picker?.delegate = self
picker?.allowsEditing = true
}
/// TODO:- picking image
public func pick(with tuning: Tuning) -> Void {
self.tune = tuning
guard tune.screen != nil else { fatalError("screen must have value.") }
picker?.mediaTypes = [tune.type == .picture ? kUTTypeImage as String : kUTTypeMovie as String]
switch tune.mode {
case .default:
openFromDefaultMode()
case .custom(let choice):
switch choice {
case .camera: openCamera()
case .library: openPhotoLibrary()
}
}
}
}
// MARK:- Private functions
private extension IImagePicker {
func openFromDefaultMode() {
let alert = UIAlertController(title: tune.alertTitle ?? "", message: tune.alertMessage ?? "", preferredStyle: .alert)
alert.view.tintColor = tune.tintColor
alert.addAction(UIAlertAction(title: tune.cancelTitle, style: .cancel, handler: { [weak self] _ in
print(#function, "tell user something in `onCancel` block because he cancel picking")
self?.onCancel?()
self?.onCancel = .none
}))
alert.addAction(UIAlertAction(title: tune.cameraTitle, style: .default, handler: { [weak self] _ in
self?.openCamera()
}))
alert.addAction(UIAlertAction(title: tune.libraryTitle, style: .default, handler: { [weak self] _ in
self?.openPhotoLibrary()
}))
tune.screen?.present(alert, animated: true)
}
func openPhotoLibrary() {
guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else {
print(#function, "tell user something in `onError` block because photoLibrary not available")
onError?()
onError = .none
return
}
picker?.sourceType = .photoLibrary
guard let picker = picker else {
print(#function, "use `onError` block because IImagePicker is null")
onError?()
onError = .none
return
}
tune.screen?.present(picker, animated: true)
}
func openCamera() {
guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
print(#function, "tell user something in `onError` block because camera not available")
onError?()
onError = .none
return
}
picker?.sourceType = .camera
guard let picker = picker else {
print(#function, "use `onError` block because IImagePicker is null")
onError?()
onError = .none
return
}
tune.screen?.present(picker, animated: true)
}
}
// MARK:- Public functions
public extension IImagePicker {
// TODO: resize image dimensions
func resize(this image: UIImage,
by size: CGSize,
_ isOpaque: Bool = false,
_ scale: CGFloat = UIScreen.main.scale) -> UIImage? {
print(#function, "old size: \(image.size)")
let horizontalRatio = size.width / image.size.width
let verticalRatio = size.height / image.size.height
let ratio = max(horizontalRatio, verticalRatio)
let newSize = CGSize(width: image.size.width * ratio, height: image.size.height * ratio)
print(#function, "new size: \(newSize)")
if #available(iOS 10.0, *) {
let renderFormat = UIGraphicsImageRendererFormat.default()
renderFormat.opaque = isOpaque
renderFormat.scale = scale
let renderer = UIGraphicsImageRenderer(size: newSize, format: renderFormat)
return renderer.image { _ in
image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
}
} else {
UIGraphicsBeginImageContextWithOptions(newSize, isOpaque, scale)
image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
}
// TODO: reduce image quality
func reduce(this image: UIImage, to quality: CGFloat, _ scale: CGFloat = UIScreen.main.scale) -> UIImage? {
print(#function, "size before reduce image: \(image.jpegData(compressionQuality: 1) ?? .init())")
guard let imageData = image.jpegData(compressionQuality: quality) else { return .none }
print(#function, "size after reduce image: \(imageData)")
return UIImage(data: imageData, scale: scale)
}
// TODO: Take cover photo
func getThumbnailImage(for url: URL) -> UIImage? {
let asset = AVAsset.init(url: url)
let imageGenerator = AVAssetImageGenerator.init(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
guard let cgImage = try? imageGenerator.copyCGImage(at: CMTimeMakeWithSeconds(1, preferredTimescale: 1), actualTime: .none) else { return .none }
return UIImage.init(cgImage: cgImage)
}
}
// MARK:- Image Picker Delegate functions
extension IImagePicker: IImagePickerDelegate {
public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print(#function, "tell user something in `onCancel` block because he cancel picking")
picker.dismiss(animated: true, completion: onCancel)
}
public func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
if let videoURL = info[.mediaURL] as? URL {
onPickVideoURL?(videoURL, self)
onPickVideoURL = .none
} else {
var pickedImage = tune.placeholderImage
if let editedImage = info[.editedImage] as? UIImage {
pickedImage = editedImage
} else if let originalPhoto = info[.originalImage] as? UIImage {
pickedImage = originalPhoto
}
var url: URL?
var name: String = NSUUID().uuidString
var ext: String = "jpeg"
if #available(iOS 11.0, *) {
url = info[.imageURL] as? URL
name = url?.lastPathComponent ?? "IMAGE_\(NSUUID().uuidString)"
ext = url?.pathExtension ?? "jpeg"
}
let resource = IResource(name: name, extension: ext, image: pickedImage, url: url)
print(#function, "user picking image you can find it in `onPickImage` block")
onPickImage?(resource, self)
onPickImage = .none
}
picker.dismiss(animated: true)
}
}