initial
This commit is contained in:
44
Pods/ZLPhotoBrowser/Sources/Extensions/Array+ZLPhotoBrowser.swift
generated
Normal file
44
Pods/ZLPhotoBrowser/Sources/Extensions/Array+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Array+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2020/10/9.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import Photos
|
||||
import UIKit
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base == [PHAsset] {
|
||||
func removeDuplicate() -> [PHAsset] {
|
||||
return base.enumerated().filter { index, value -> Bool in
|
||||
base.firstIndex(of: value) == index
|
||||
}.map { $0.element }
|
||||
}
|
||||
}
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base == [ZLResultModel] {
|
||||
func removeDuplicate() -> [ZLResultModel] {
|
||||
return base.enumerated().filter { index, value -> Bool in
|
||||
base.firstIndex(of: value) == index
|
||||
}.map { $0.element }
|
||||
}
|
||||
}
|
||||
33
Pods/ZLPhotoBrowser/Sources/Extensions/Bool+ZLPhotoBrowser.swift
generated
Normal file
33
Pods/ZLPhotoBrowser/Sources/Extensions/Bool+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Bool+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by ruby109 on 2020/11/3.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import Foundation
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base == Bool {
|
||||
var intValue: Int {
|
||||
base ? 1 : 0
|
||||
}
|
||||
}
|
||||
106
Pods/ZLPhotoBrowser/Sources/Extensions/Bundle+ZLPhotoBrowser.swift
generated
Normal file
106
Pods/ZLPhotoBrowser/Sources/Extensions/Bundle+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// Bundle+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2020/8/12.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import Foundation
|
||||
|
||||
private class BundleFinder {}
|
||||
|
||||
extension Bundle {
|
||||
private static var bundle: Bundle?
|
||||
|
||||
static var normalModule: Bundle? = {
|
||||
let bundleName = "ZLPhotoBrowser"
|
||||
|
||||
var candidates = [
|
||||
// Bundle should be present here when the package is linked into an App.
|
||||
Bundle.main.resourceURL,
|
||||
|
||||
// Bundle should be present here when the package is linked into a framework.
|
||||
Bundle(for: ZLPhotoPreviewSheet.self).resourceURL,
|
||||
|
||||
// For command-line tools.
|
||||
Bundle.main.bundleURL,
|
||||
]
|
||||
|
||||
#if SWIFT_PACKAGE
|
||||
// For SWIFT_PACKAGE.
|
||||
candidates.append(Bundle.module.bundleURL)
|
||||
#endif
|
||||
|
||||
for candidate in candidates {
|
||||
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
|
||||
if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
|
||||
return bundle
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
static var spmModule: Bundle? = {
|
||||
let bundleName = "ZLPhotoBrowser_ZLPhotoBrowser"
|
||||
|
||||
let candidates = [
|
||||
// Bundle should be present here when the package is linked into an App.
|
||||
Bundle.main.resourceURL,
|
||||
|
||||
// Bundle should be present here when the package is linked into a framework.
|
||||
Bundle(for: BundleFinder.self).resourceURL,
|
||||
|
||||
// For command-line tools.
|
||||
Bundle.main.bundleURL,
|
||||
]
|
||||
|
||||
for candidate in candidates {
|
||||
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
|
||||
if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
|
||||
return bundle
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
static var zlPhotoBrowserBundle: Bundle? {
|
||||
return normalModule ?? spmModule
|
||||
}
|
||||
|
||||
class func resetLanguage() {
|
||||
bundle = nil
|
||||
}
|
||||
|
||||
class func zlLocalizedString(_ key: String) -> String {
|
||||
if bundle == nil {
|
||||
guard let path = Bundle.zlPhotoBrowserBundle?.path(forResource: ZLCustomLanguageDeploy.language.key, ofType: "lproj") else {
|
||||
return ""
|
||||
}
|
||||
bundle = Bundle(path: path)
|
||||
}
|
||||
|
||||
let value = bundle?.localizedString(forKey: key, value: nil, table: nil)
|
||||
return Bundle.main.localizedString(forKey: key, value: value, table: nil)
|
||||
}
|
||||
}
|
||||
33
Pods/ZLPhotoBrowser/Sources/Extensions/CGFloat+ZLPhotoBrowser.swift
generated
Normal file
33
Pods/ZLPhotoBrowser/Sources/Extensions/CGFloat+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// CGFloat+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2020/11/10.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base == CGFloat {
|
||||
var toPi: CGFloat {
|
||||
return base / 180 * .pi
|
||||
}
|
||||
}
|
||||
47
Pods/ZLPhotoBrowser/Sources/Extensions/Cell+ZLPhotoBrowser.swift
generated
Normal file
47
Pods/ZLPhotoBrowser/Sources/Extensions/Cell+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Cell+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2020/8/13.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base: UICollectionViewCell {
|
||||
static var identifier: String {
|
||||
NSStringFromClass(Base.self)
|
||||
}
|
||||
|
||||
static func register(_ collectionView: UICollectionView) {
|
||||
collectionView.register(Base.self, forCellWithReuseIdentifier: identifier)
|
||||
}
|
||||
}
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base: UITableViewCell {
|
||||
static var identifier: String {
|
||||
NSStringFromClass(Base.self)
|
||||
}
|
||||
|
||||
static func register(_ tableView: UITableView) {
|
||||
tableView.register(Base.self, forCellReuseIdentifier: identifier)
|
||||
}
|
||||
}
|
||||
44
Pods/ZLPhotoBrowser/Sources/Extensions/NSError+ZLPhotoBrowser.swift
generated
Normal file
44
Pods/ZLPhotoBrowser/Sources/Extensions/NSError+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// NSError+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2022/8/3.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import Foundation
|
||||
|
||||
extension NSError {
|
||||
convenience init(message: String) {
|
||||
let userInfo = [NSLocalizedDescriptionKey: message]
|
||||
self.init(domain: "com.ZLPhotoBrowser.error", code: -1, userInfo: userInfo)
|
||||
}
|
||||
}
|
||||
|
||||
extension NSError {
|
||||
static let videoMergeError = NSError(message: "video merge failed")
|
||||
|
||||
static let videoExportTypeError = NSError(message: "The mediaType of asset must be video")
|
||||
|
||||
static let videoExportError = NSError(message: "Video export failed")
|
||||
|
||||
static let assetSaveError = NSError(message: "Asset save failed")
|
||||
}
|
||||
53
Pods/ZLPhotoBrowser/Sources/Extensions/PHAsset+ZLPhotoBrowser.swift
generated
Normal file
53
Pods/ZLPhotoBrowser/Sources/Extensions/PHAsset+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// PHAsset+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2020/12/16.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import Photos
|
||||
import MobileCoreServices
|
||||
|
||||
public extension ZLPhotoBrowserWrapper where Base: PHAsset {
|
||||
var isInCloud: Bool {
|
||||
guard let resource = resource else {
|
||||
return false
|
||||
}
|
||||
return !(resource.value(forKey: "locallyAvailable") as? Bool ?? true)
|
||||
}
|
||||
|
||||
var isGif: Bool {
|
||||
guard let filename = filename else {
|
||||
return false
|
||||
}
|
||||
|
||||
return filename.hasSuffix("GIF")
|
||||
}
|
||||
|
||||
var filename: String? {
|
||||
base.value(forKey: "filename") as? String
|
||||
}
|
||||
|
||||
var resource: PHAssetResource? {
|
||||
PHAssetResource.assetResources(for: base).first
|
||||
}
|
||||
}
|
||||
43
Pods/ZLPhotoBrowser/Sources/Extensions/String+ZLPhotoBrowser.swift
generated
Normal file
43
Pods/ZLPhotoBrowser/Sources/Extensions/String+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// String+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2020/8/18.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base == String {
|
||||
func boundingRect(font: UIFont, limitSize: CGSize) -> CGSize {
|
||||
let style = NSMutableParagraphStyle()
|
||||
style.lineBreakMode = .byCharWrapping
|
||||
|
||||
let att = [NSAttributedString.Key.font: font, NSAttributedString.Key.paragraphStyle: style]
|
||||
|
||||
let attContent = NSMutableAttributedString(string: base, attributes: att)
|
||||
|
||||
let size = attContent.boundingRect(with: limitSize, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).size
|
||||
|
||||
return CGSize(width: ceil(size.width), height: ceil(size.height))
|
||||
}
|
||||
}
|
||||
263
Pods/ZLPhotoBrowser/Sources/Extensions/UIColor+ZLPhotoBrowser.swift
generated
Normal file
263
Pods/ZLPhotoBrowser/Sources/Extensions/UIColor+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,263 @@
|
||||
//
|
||||
// UIColor+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2020/8/18.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base: UIColor {
|
||||
static var navBarColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().navBarColor
|
||||
}
|
||||
|
||||
static var navBarColorOfPreviewVC: UIColor {
|
||||
ZLPhotoUIConfiguration.default().navBarColorOfPreviewVC
|
||||
}
|
||||
|
||||
/// 相册列表界面导航标题颜色
|
||||
static var navTitleColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().navTitleColor
|
||||
}
|
||||
|
||||
/// 预览大图界面导航标题颜色
|
||||
static var navTitleColorOfPreviewVC: UIColor {
|
||||
ZLPhotoUIConfiguration.default().navTitleColorOfPreviewVC
|
||||
}
|
||||
|
||||
/// 框架样式为 embedAlbumList 时,title view 背景色
|
||||
static var navEmbedTitleViewBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().navEmbedTitleViewBgColor
|
||||
}
|
||||
|
||||
/// 预览选择模式下 上方透明背景色
|
||||
static var previewBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().sheetTranslucentColor
|
||||
}
|
||||
|
||||
/// 预览选择模式下 拍照/相册/取消 的背景颜色
|
||||
static var previewBtnBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().sheetBtnBgColor
|
||||
}
|
||||
|
||||
/// 预览选择模式下 拍照/相册/取消 的字体颜色
|
||||
static var previewBtnTitleColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().sheetBtnTitleColor
|
||||
}
|
||||
|
||||
/// 预览选择模式下 选择照片大于0时,取消按钮title颜色
|
||||
static var previewBtnHighlightTitleColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().sheetBtnTitleTintColor
|
||||
}
|
||||
|
||||
/// 相册列表界面背景色
|
||||
static var albumListBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().albumListBgColor
|
||||
}
|
||||
|
||||
/// 嵌入式相册列表下方透明区域颜色
|
||||
static var embedAlbumListTranslucentColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().embedAlbumListTranslucentColor
|
||||
}
|
||||
|
||||
/// 相册列表界面 相册title颜色
|
||||
static var albumListTitleColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().albumListTitleColor
|
||||
}
|
||||
|
||||
/// 相册列表界面 数量label颜色
|
||||
static var albumListCountColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().albumListCountColor
|
||||
}
|
||||
|
||||
/// 分割线颜色
|
||||
static var separatorLineColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().separatorColor
|
||||
}
|
||||
|
||||
/// 小图界面背景色
|
||||
static var thumbnailBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().thumbnailBgColor
|
||||
}
|
||||
|
||||
/// 预览大图界面背景色
|
||||
static var previewVCBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().previewVCBgColor
|
||||
}
|
||||
|
||||
/// 相册列表界面底部工具条底色
|
||||
static var bottomToolViewBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewBgColor
|
||||
}
|
||||
|
||||
/// 预览大图界面底部工具条底色
|
||||
static var bottomToolViewBgColorOfPreviewVC: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewBgColorOfPreviewVC
|
||||
}
|
||||
|
||||
/// 相册列表界面底部工具栏按钮 可交互 状态标题颜色
|
||||
static var bottomToolViewBtnNormalTitleColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewBtnNormalTitleColor
|
||||
}
|
||||
|
||||
/// 相册列表界面底部工具栏 `完成` 按钮 可交互 状态标题颜色
|
||||
static var bottomToolViewDoneBtnNormalTitleColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewDoneBtnNormalTitleColor
|
||||
}
|
||||
|
||||
/// 预览大图界面底部工具栏按钮 可交互 状态标题颜色
|
||||
static var bottomToolViewBtnNormalTitleColorOfPreviewVC: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewBtnNormalTitleColorOfPreviewVC
|
||||
}
|
||||
|
||||
/// 预览大图界面底部工具栏 `完成` 按钮 可交互 状态标题颜色
|
||||
static var bottomToolViewDoneBtnNormalTitleColorOfPreviewVC: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewDoneBtnNormalTitleColorOfPreviewVC
|
||||
}
|
||||
|
||||
/// 相册列表界面底部工具栏按钮 不可交互 状态标题颜色
|
||||
static var bottomToolViewBtnDisableTitleColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewBtnDisableTitleColor
|
||||
}
|
||||
|
||||
/// 相册列表界面底部工具栏 `完成` 按钮 不可交互 状态标题颜色
|
||||
static var bottomToolViewDoneBtnDisableTitleColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewDoneBtnDisableTitleColor
|
||||
}
|
||||
|
||||
/// 预览大图界面底部工具栏按钮 不可交互 状态标题颜色
|
||||
static var bottomToolViewBtnDisableTitleColorOfPreviewVC: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewBtnDisableTitleColorOfPreviewVC
|
||||
}
|
||||
|
||||
/// 预览大图界面底部工具栏 `完成` 按钮 不可交互 状态标题颜色
|
||||
static var bottomToolViewDoneBtnDisableTitleColorOfPreviewVC: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewDoneBtnDisableTitleColorOfPreviewVC
|
||||
}
|
||||
|
||||
/// 相册列表界面底部工具栏按钮 可交互 状态背景颜色
|
||||
static var bottomToolViewBtnNormalBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewBtnNormalBgColor
|
||||
}
|
||||
|
||||
/// 预览大图界面底部工具栏按钮 可交互 状态背景颜色
|
||||
static var bottomToolViewBtnNormalBgColorOfPreviewVC: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewBtnNormalBgColorOfPreviewVC
|
||||
}
|
||||
|
||||
/// 相册列表界面底部工具栏按钮 不可交互 状态背景颜色
|
||||
static var bottomToolViewBtnDisableBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewBtnDisableBgColor
|
||||
}
|
||||
|
||||
/// 预览大图界面底部工具栏按钮 不可交互 状态背景颜色
|
||||
static var bottomToolViewBtnDisableBgColorOfPreviewVC: UIColor {
|
||||
ZLPhotoUIConfiguration.default().bottomToolViewBtnDisableBgColorOfPreviewVC
|
||||
}
|
||||
|
||||
/// iOS14 limited 权限时候,小图界面下方显示 选择更多图片 标题颜色
|
||||
static var limitedAuthorityTipsColor: UIColor {
|
||||
return ZLPhotoUIConfiguration.default().limitedAuthorityTipsColor
|
||||
}
|
||||
|
||||
/// 自定义相机录制视频时,进度条颜色
|
||||
static var cameraRecodeProgressColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().cameraRecodeProgressColor
|
||||
}
|
||||
|
||||
/// 已选cell遮罩层颜色
|
||||
static var selectedMaskColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().selectedMaskColor
|
||||
}
|
||||
|
||||
/// 已选cell border颜色
|
||||
static var selectedBorderColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().selectedBorderColor
|
||||
}
|
||||
|
||||
/// 不能选择的cell上方遮罩层颜色
|
||||
static var invalidMaskColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().invalidMaskColor
|
||||
}
|
||||
|
||||
/// 选中图片右上角index text color
|
||||
static var indexLabelTextColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().indexLabelTextColor
|
||||
}
|
||||
|
||||
/// 选中图片右上角index background color
|
||||
static var indexLabelBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().indexLabelBgColor
|
||||
}
|
||||
|
||||
/// 拍照cell 背景颜色
|
||||
static var cameraCellBgColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().cameraCellBgColor
|
||||
}
|
||||
|
||||
/// 调整图片slider默认色
|
||||
static var adjustSliderNormalColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().adjustSliderNormalColor
|
||||
}
|
||||
|
||||
/// 调整图片slider高亮色
|
||||
static var adjustSliderTintColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().adjustSliderTintColor
|
||||
}
|
||||
|
||||
/// 图片编辑器中各种工具下方标题普通状态下的颜色
|
||||
static var imageEditorToolTitleNormalColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().imageEditorToolTitleNormalColor
|
||||
}
|
||||
|
||||
/// 图片编辑器中各种工具下方标题高亮状态下的颜色
|
||||
static var imageEditorToolTitleTintColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().imageEditorToolTitleTintColor
|
||||
}
|
||||
|
||||
/// 图片编辑器中各种工具图标高亮状态下的颜色
|
||||
static var imageEditorToolIconTintColor: UIColor? {
|
||||
ZLPhotoUIConfiguration.default().imageEditorToolIconTintColor
|
||||
}
|
||||
|
||||
/// 编辑器中垃圾箱普通状态下的颜色
|
||||
static var trashCanBackgroundNormalColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().trashCanBackgroundNormalColor
|
||||
}
|
||||
|
||||
/// 编辑器中垃圾箱高亮状态下的颜色
|
||||
static var trashCanBackgroundTintColor: UIColor {
|
||||
ZLPhotoUIConfiguration.default().trashCanBackgroundTintColor
|
||||
}
|
||||
}
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base: UIColor {
|
||||
/// - Parameters:
|
||||
/// - r: 0~255
|
||||
/// - g: 0~255
|
||||
/// - b: 0~255
|
||||
/// - a: 0~1
|
||||
static func rgba(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat, _ a: CGFloat = 1) -> UIColor {
|
||||
return UIColor(red: r / 255, green: g / 255, blue: b / 255, alpha: a)
|
||||
}
|
||||
}
|
||||
37
Pods/ZLPhotoBrowser/Sources/Extensions/UIFont+ZLPhotoBrowser.swift
generated
Normal file
37
Pods/ZLPhotoBrowser/Sources/Extensions/UIFont+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// UIFont+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2022/7/7.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base: UIFont {
|
||||
static func font(ofSize fontSize: CGFloat) -> UIFont {
|
||||
guard let name = ZLCustomFontDeploy.fontName else {
|
||||
return UIFont.systemFont(ofSize: fontSize)
|
||||
}
|
||||
|
||||
return UIFont(name: name, size: fontSize) ?? UIFont.systemFont(ofSize: fontSize)
|
||||
}
|
||||
}
|
||||
543
Pods/ZLPhotoBrowser/Sources/Extensions/UIImage+ZLPhotoBrowser.swift
generated
Normal file
543
Pods/ZLPhotoBrowser/Sources/Extensions/UIImage+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,543 @@
|
||||
//
|
||||
// UIImage+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2020/8/22.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
import Accelerate
|
||||
import MobileCoreServices
|
||||
|
||||
// MARK: data 转 gif image
|
||||
|
||||
public extension ZLPhotoBrowserWrapper where Base: UIImage {
|
||||
static func animateGifImage(data: Data) -> UIImage? {
|
||||
// Kingfisher
|
||||
let info: [String: Any] = [
|
||||
kCGImageSourceShouldCache as String: true,
|
||||
kCGImageSourceTypeIdentifierHint as String: kUTTypeGIF
|
||||
]
|
||||
|
||||
guard let imageSource = CGImageSourceCreateWithData(data as CFData, info as CFDictionary) else {
|
||||
return UIImage(data: data)
|
||||
}
|
||||
|
||||
var frameCount = CGImageSourceGetCount(imageSource)
|
||||
guard frameCount > 1 else {
|
||||
return UIImage(data: data)
|
||||
}
|
||||
|
||||
let maxFrameCount = ZLPhotoConfiguration.default().maxFrameCountForGIF
|
||||
|
||||
let ratio = CGFloat(max(frameCount, maxFrameCount)) / CGFloat(maxFrameCount)
|
||||
frameCount = min(frameCount, maxFrameCount)
|
||||
|
||||
var images = [UIImage]()
|
||||
var frameDuration = [Int]()
|
||||
|
||||
for i in 0..<frameCount {
|
||||
let index = Int(floor(CGFloat(i) * ratio))
|
||||
|
||||
guard let imageRef = CGImageSourceCreateImageAtIndex(imageSource, index, info as CFDictionary) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get current animated GIF frame duration
|
||||
let currFrameDuration = getFrameDuration(from: imageSource, at: index) * min(ratio, 3)
|
||||
// Second to ms
|
||||
frameDuration.append(Int(currFrameDuration * 1000))
|
||||
|
||||
images.append(UIImage(cgImage: imageRef, scale: 1, orientation: .up))
|
||||
}
|
||||
|
||||
// https://github.com/kiritmodi2702/GIF-Swift
|
||||
let duration: Int = {
|
||||
var sum = 0
|
||||
for val in frameDuration {
|
||||
sum += val
|
||||
}
|
||||
return sum
|
||||
}()
|
||||
|
||||
// 求出每一帧的最大公约数
|
||||
let gcd = gcdForArray(frameDuration)
|
||||
var frames = [UIImage]()
|
||||
|
||||
for i in 0..<frameCount {
|
||||
let frameImage = images[i]
|
||||
// 每张图片的时长除以最大公约数,得出需要展示的张数
|
||||
let count = Int(frameDuration[i] / gcd)
|
||||
|
||||
for _ in 0..<count {
|
||||
frames.append(frameImage)
|
||||
}
|
||||
}
|
||||
|
||||
return .animatedImage(with: frames, duration: TimeInterval(duration) / 1000)
|
||||
}
|
||||
|
||||
/// Calculates frame duration at a specific index for a gif from an `imageSource`.
|
||||
static func getFrameDuration(from imageSource: CGImageSource, at index: Int) -> TimeInterval {
|
||||
guard let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, index, nil)
|
||||
as? [String: Any] else { return 0.0 }
|
||||
|
||||
let gifInfo = properties[kCGImagePropertyGIFDictionary as String] as? [String: Any]
|
||||
return getFrameDuration(from: gifInfo)
|
||||
}
|
||||
|
||||
/// Calculates frame duration for a gif frame out of the kCGImagePropertyGIFDictionary dictionary.
|
||||
static func getFrameDuration(from gifInfo: [String: Any]?) -> TimeInterval {
|
||||
let defaultFrameDuration = 0.1
|
||||
guard let gifInfo = gifInfo else { return defaultFrameDuration }
|
||||
|
||||
let unclampedDelayTime = gifInfo[kCGImagePropertyGIFUnclampedDelayTime as String] as? NSNumber
|
||||
let delayTime = gifInfo[kCGImagePropertyGIFDelayTime as String] as? NSNumber
|
||||
let duration = unclampedDelayTime ?? delayTime
|
||||
|
||||
guard let frameDuration = duration else {
|
||||
return defaultFrameDuration
|
||||
}
|
||||
return frameDuration.doubleValue > 0.011 ? frameDuration.doubleValue : defaultFrameDuration
|
||||
}
|
||||
|
||||
private static func gcdForArray(_ array: [Int]) -> Int {
|
||||
if array.isEmpty {
|
||||
return 1
|
||||
}
|
||||
|
||||
var gcd = array[0]
|
||||
|
||||
for val in array {
|
||||
gcd = gcdForPair(val, gcd)
|
||||
}
|
||||
|
||||
return gcd
|
||||
}
|
||||
|
||||
private static func gcdForPair(_ num1: Int?, _ num2: Int?) -> Int {
|
||||
guard var num1 = num1, var num2 = num2 else {
|
||||
return num1 ?? (num2 ?? 0)
|
||||
}
|
||||
|
||||
if num1 < num2 {
|
||||
swap(&num1, &num2)
|
||||
}
|
||||
|
||||
var rest: Int
|
||||
while true {
|
||||
rest = num1 % num2
|
||||
|
||||
if rest == 0 {
|
||||
return num2
|
||||
} else {
|
||||
num1 = num2
|
||||
num2 = rest
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: image edit
|
||||
|
||||
public extension ZLPhotoBrowserWrapper where Base: UIImage {
|
||||
/// 修复转向
|
||||
func fixOrientation() -> UIImage {
|
||||
if base.imageOrientation == .up {
|
||||
return base
|
||||
}
|
||||
|
||||
var transform = CGAffineTransform.identity
|
||||
|
||||
switch base.imageOrientation {
|
||||
case .down, .downMirrored:
|
||||
transform = CGAffineTransform(translationX: width, y: height)
|
||||
transform = transform.rotated(by: .pi)
|
||||
case .left, .leftMirrored:
|
||||
transform = CGAffineTransform(translationX: width, y: 0)
|
||||
transform = transform.rotated(by: CGFloat.pi / 2)
|
||||
case .right, .rightMirrored:
|
||||
transform = CGAffineTransform(translationX: 0, y: height)
|
||||
transform = transform.rotated(by: -CGFloat.pi / 2)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
switch base.imageOrientation {
|
||||
case .upMirrored, .downMirrored:
|
||||
transform = transform.translatedBy(x: width, y: 0)
|
||||
transform = transform.scaledBy(x: -1, y: 1)
|
||||
case .leftMirrored, .rightMirrored:
|
||||
transform = transform.translatedBy(x: height, y: 0)
|
||||
transform = transform.scaledBy(x: -1, y: 1)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
guard let cgImage = base.cgImage, let colorSpace = cgImage.colorSpace else {
|
||||
return base
|
||||
}
|
||||
let context = CGContext(
|
||||
data: nil,
|
||||
width: Int(width),
|
||||
height: Int(height),
|
||||
bitsPerComponent: cgImage.bitsPerComponent,
|
||||
bytesPerRow: 0,
|
||||
space: colorSpace,
|
||||
bitmapInfo: cgImage.bitmapInfo.rawValue
|
||||
)
|
||||
context?.concatenate(transform)
|
||||
switch base.imageOrientation {
|
||||
case .left, .leftMirrored, .right, .rightMirrored:
|
||||
context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: height, height: width))
|
||||
default:
|
||||
context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
|
||||
}
|
||||
|
||||
guard let newCgImage = context?.makeImage() else {
|
||||
return base
|
||||
}
|
||||
return UIImage(cgImage: newCgImage)
|
||||
}
|
||||
|
||||
/// 旋转方向
|
||||
func rotate(orientation: UIImage.Orientation) -> UIImage {
|
||||
guard let imagRef = base.cgImage else {
|
||||
return base
|
||||
}
|
||||
let rect = CGRect(origin: .zero, size: CGSize(width: CGFloat(imagRef.width), height: CGFloat(imagRef.height)))
|
||||
|
||||
var bnds = rect
|
||||
|
||||
var transform = CGAffineTransform.identity
|
||||
|
||||
switch orientation {
|
||||
case .up:
|
||||
return base
|
||||
case .upMirrored:
|
||||
transform = transform.translatedBy(x: rect.width, y: 0)
|
||||
transform = transform.scaledBy(x: -1, y: 1)
|
||||
case .down:
|
||||
transform = transform.translatedBy(x: rect.width, y: rect.height)
|
||||
transform = transform.rotated(by: .pi)
|
||||
case .downMirrored:
|
||||
transform = transform.translatedBy(x: 0, y: rect.height)
|
||||
transform = transform.scaledBy(x: 1, y: -1)
|
||||
case .left:
|
||||
bnds = swapRectWidthAndHeight(bnds)
|
||||
transform = transform.translatedBy(x: 0, y: rect.width)
|
||||
transform = transform.rotated(by: CGFloat.pi * 3 / 2)
|
||||
case .leftMirrored:
|
||||
bnds = swapRectWidthAndHeight(bnds)
|
||||
transform = transform.translatedBy(x: rect.height, y: rect.width)
|
||||
transform = transform.scaledBy(x: -1, y: 1)
|
||||
transform = transform.rotated(by: CGFloat.pi * 3 / 2)
|
||||
case .right:
|
||||
bnds = swapRectWidthAndHeight(bnds)
|
||||
transform = transform.translatedBy(x: rect.height, y: 0)
|
||||
transform = transform.rotated(by: CGFloat.pi / 2)
|
||||
case .rightMirrored:
|
||||
bnds = swapRectWidthAndHeight(bnds)
|
||||
transform = transform.scaledBy(x: -1, y: 1)
|
||||
transform = transform.rotated(by: CGFloat.pi / 2)
|
||||
@unknown default:
|
||||
return base
|
||||
}
|
||||
|
||||
UIGraphicsBeginImageContext(bnds.size)
|
||||
let context = UIGraphicsGetCurrentContext()
|
||||
switch orientation {
|
||||
case .left, .leftMirrored, .right, .rightMirrored:
|
||||
context?.scaleBy(x: -1, y: 1)
|
||||
context?.translateBy(x: -rect.height, y: 0)
|
||||
default:
|
||||
context?.scaleBy(x: 1, y: -1)
|
||||
context?.translateBy(x: 0, y: -rect.height)
|
||||
}
|
||||
context?.concatenate(transform)
|
||||
context?.draw(imagRef, in: rect)
|
||||
let newImage = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
|
||||
return newImage ?? base
|
||||
}
|
||||
|
||||
func swapRectWidthAndHeight(_ rect: CGRect) -> CGRect {
|
||||
var r = rect
|
||||
r.size.width = rect.height
|
||||
r.size.height = rect.width
|
||||
return r
|
||||
}
|
||||
|
||||
func rotate(degress: CGFloat) -> UIImage {
|
||||
guard degress != 0, let cgImage = base.cgImage else {
|
||||
return base
|
||||
}
|
||||
|
||||
let rotatedViewBox = UIView(frame: CGRect(x: 0, y: 0, width: width, height: height))
|
||||
let t = CGAffineTransform(rotationAngle: degress)
|
||||
rotatedViewBox.transform = t
|
||||
let rotatedSize = rotatedViewBox.frame.size
|
||||
|
||||
UIGraphicsBeginImageContext(rotatedSize)
|
||||
|
||||
let bitmap = UIGraphicsGetCurrentContext()
|
||||
bitmap?.translateBy(x: rotatedSize.width / 2, y: rotatedSize.height / 2)
|
||||
bitmap?.rotate(by: degress)
|
||||
bitmap?.scaleBy(x: 1.0, y: -1.0)
|
||||
|
||||
bitmap?.draw(cgImage, in: CGRect(x: -width / 2, y: -height / 2, width: width, height: height))
|
||||
let newImage = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
|
||||
return newImage ?? base
|
||||
}
|
||||
|
||||
/// 加马赛克
|
||||
func mosaicImage() -> UIImage? {
|
||||
guard let cgImage = base.cgImage else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let scale = 8 * width / UIScreen.main.bounds.width
|
||||
let currCiImage = CIImage(cgImage: cgImage)
|
||||
let filter = CIFilter(name: "CIPixellate")
|
||||
filter?.setValue(currCiImage, forKey: kCIInputImageKey)
|
||||
filter?.setValue(scale, forKey: kCIInputScaleKey)
|
||||
guard let outputImage = filter?.outputImage else { return nil }
|
||||
|
||||
let context = CIContext()
|
||||
|
||||
if let cgImage = context.createCGImage(outputImage, from: CGRect(origin: .zero, size: base.size)) {
|
||||
return UIImage(cgImage: cgImage)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func resize(_ size: CGSize, scale: CGFloat? = nil) -> UIImage? {
|
||||
if size.width <= 0 || size.height <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(size, false, scale ?? base.scale)
|
||||
base.draw(in: CGRect(origin: .zero, size: size))
|
||||
let temp = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return temp
|
||||
}
|
||||
|
||||
/// Resize image. Processing speed is better than resize(:) method
|
||||
/// - Parameters:
|
||||
/// - size: Dest size of the image
|
||||
/// - scale: The scale factor of the image
|
||||
func resize_vI(_ size: CGSize, scale: CGFloat? = nil) -> UIImage? {
|
||||
guard let cgImage = base.cgImage else { return nil }
|
||||
|
||||
var format = vImage_CGImageFormat(
|
||||
bitsPerComponent: 8,
|
||||
bitsPerPixel: 32,
|
||||
colorSpace: nil,
|
||||
bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.first.rawValue),
|
||||
version: 0,
|
||||
decode: nil,
|
||||
renderingIntent: .defaultIntent
|
||||
)
|
||||
|
||||
var sourceBuffer = vImage_Buffer()
|
||||
defer {
|
||||
if #available(iOS 13.0, *) {
|
||||
sourceBuffer.free()
|
||||
} else {
|
||||
sourceBuffer.data.deallocate()
|
||||
}
|
||||
}
|
||||
|
||||
var error = vImageBuffer_InitWithCGImage(&sourceBuffer, &format, nil, cgImage, numericCast(kvImageNoFlags))
|
||||
guard error == kvImageNoError else { return nil }
|
||||
|
||||
let destWidth = Int(size.width)
|
||||
let destHeight = Int(size.height)
|
||||
let bytesPerPixel = cgImage.bitsPerPixel / 8
|
||||
let destBytesPerRow = destWidth * bytesPerPixel
|
||||
|
||||
let destData = UnsafeMutablePointer<UInt8>.allocate(capacity: destHeight * destBytesPerRow)
|
||||
defer {
|
||||
destData.deallocate()
|
||||
}
|
||||
var destBuffer = vImage_Buffer(data: destData, height: vImagePixelCount(destHeight), width: vImagePixelCount(destWidth), rowBytes: destBytesPerRow)
|
||||
|
||||
// scale the image
|
||||
error = vImageScale_ARGB8888(&sourceBuffer, &destBuffer, nil, numericCast(kvImageHighQualityResampling))
|
||||
guard error == kvImageNoError else { return nil }
|
||||
|
||||
// create a CGImage from vImage_Buffer
|
||||
guard let destCGImage = vImageCreateCGImageFromBuffer(&destBuffer, &format, nil, nil, numericCast(kvImageNoFlags), &error)?.takeRetainedValue() else { return nil }
|
||||
guard error == kvImageNoError else { return nil }
|
||||
|
||||
// create a UIImage
|
||||
return UIImage(cgImage: destCGImage, scale: scale ?? base.scale, orientation: base.imageOrientation)
|
||||
}
|
||||
|
||||
func toCIImage() -> CIImage? {
|
||||
var ciImage = base.ciImage
|
||||
if ciImage == nil, let cgImage = base.cgImage {
|
||||
ciImage = CIImage(cgImage: cgImage)
|
||||
}
|
||||
return ciImage
|
||||
}
|
||||
|
||||
func clipImage(angle: CGFloat, editRect: CGRect, isCircle: Bool) -> UIImage? {
|
||||
let a = ((Int(angle) % 360) - 360) % 360
|
||||
var newImage: UIImage = base
|
||||
if a == -90 {
|
||||
newImage = rotate(orientation: .left)
|
||||
} else if a == -180 {
|
||||
newImage = rotate(orientation: .down)
|
||||
} else if a == -270 {
|
||||
newImage = rotate(orientation: .right)
|
||||
}
|
||||
guard editRect.size != newImage.size else {
|
||||
return newImage
|
||||
}
|
||||
let origin = CGPoint(x: -editRect.minX, y: -editRect.minY)
|
||||
UIGraphicsBeginImageContextWithOptions(editRect.size, false, newImage.scale)
|
||||
let context = UIGraphicsGetCurrentContext()
|
||||
if isCircle {
|
||||
context?.addEllipse(in: CGRect(origin: .zero, size: editRect.size))
|
||||
context?.clip()
|
||||
}
|
||||
newImage.draw(at: origin)
|
||||
let temp = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
guard let cgi = temp?.cgImage else {
|
||||
return temp
|
||||
}
|
||||
let clipImage = UIImage(cgImage: cgi, scale: newImage.scale, orientation: .up)
|
||||
return clipImage
|
||||
}
|
||||
|
||||
func blurImage(level: CGFloat) -> UIImage? {
|
||||
guard let ciImage = toCIImage() else {
|
||||
return nil
|
||||
}
|
||||
let blurFilter = CIFilter(name: "CIGaussianBlur")
|
||||
blurFilter?.setValue(ciImage, forKey: "inputImage")
|
||||
blurFilter?.setValue(level, forKey: "inputRadius")
|
||||
|
||||
guard let outputImage = blurFilter?.outputImage else {
|
||||
return nil
|
||||
}
|
||||
let context = CIContext()
|
||||
guard let cgImage = context.createCGImage(outputImage, from: ciImage.extent) else {
|
||||
return nil
|
||||
}
|
||||
return UIImage(cgImage: cgImage)
|
||||
}
|
||||
|
||||
func hasAlphaChannel() -> Bool {
|
||||
guard let info = base.cgImage?.alphaInfo else {
|
||||
return false
|
||||
}
|
||||
|
||||
return info == .first || info == .last || info == .premultipliedFirst || info == .premultipliedLast
|
||||
}
|
||||
}
|
||||
|
||||
public extension ZLPhotoBrowserWrapper where Base: UIImage {
|
||||
/// 调整图片亮度、对比度、饱和度
|
||||
/// - Parameters:
|
||||
/// - brightness: value in [-1, 1]
|
||||
/// - contrast: value in [-1, 1]
|
||||
/// - saturation: value in [-1, 1]
|
||||
func adjust(brightness: Float, contrast: Float, saturation: Float) -> UIImage? {
|
||||
guard let ciImage = toCIImage() else {
|
||||
return base
|
||||
}
|
||||
|
||||
let filter = CIFilter(name: "CIColorControls")
|
||||
filter?.setValue(ciImage, forKey: kCIInputImageKey)
|
||||
filter?.setValue(ZLEditImageConfiguration.AdjustTool.brightness.filterValue(brightness), forKey: ZLEditImageConfiguration.AdjustTool.brightness.key)
|
||||
filter?.setValue(ZLEditImageConfiguration.AdjustTool.contrast.filterValue(contrast), forKey: ZLEditImageConfiguration.AdjustTool.contrast.key)
|
||||
filter?.setValue(ZLEditImageConfiguration.AdjustTool.saturation.filterValue(saturation), forKey: ZLEditImageConfiguration.AdjustTool.saturation.key)
|
||||
let outputCIImage = filter?.outputImage
|
||||
return outputCIImage?.zl.toUIImage()
|
||||
}
|
||||
}
|
||||
|
||||
public extension ZLPhotoBrowserWrapper where Base: UIImage {
|
||||
static func image(withColor color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage? {
|
||||
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
|
||||
UIGraphicsBeginImageContext(rect.size)
|
||||
let context = UIGraphicsGetCurrentContext()
|
||||
context?.setFillColor(color.cgColor)
|
||||
context?.fill(rect)
|
||||
let image = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return image
|
||||
}
|
||||
|
||||
func fillColor(_ color: UIColor) -> UIImage? {
|
||||
UIGraphicsBeginImageContextWithOptions(base.size, false, base.scale)
|
||||
let drawRect = CGRect(x: 0, y: 0, width: base.zl.width, height: base.zl.height)
|
||||
color.setFill()
|
||||
UIRectFill(drawRect)
|
||||
base.draw(in: drawRect, blendMode: .destinationIn, alpha: 1)
|
||||
|
||||
let tintedImage = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return tintedImage
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public extension ZLPhotoBrowserWrapper where Base: UIImage {
|
||||
var width: CGFloat {
|
||||
base.size.width
|
||||
}
|
||||
|
||||
var height: CGFloat {
|
||||
base.size.height
|
||||
}
|
||||
}
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base: UIImage {
|
||||
static func getImage(_ named: String) -> UIImage? {
|
||||
if ZLCustomImageDeploy.imageNames.contains(named), let image = UIImage(named: named) {
|
||||
return image
|
||||
}
|
||||
if let image = ZLCustomImageDeploy.imageForKey[named] {
|
||||
return image
|
||||
}
|
||||
return UIImage(named: named, in: Bundle.zlPhotoBrowserBundle, compatibleWith: nil)
|
||||
}
|
||||
}
|
||||
|
||||
public extension ZLPhotoBrowserWrapper where Base: CIImage {
|
||||
func toUIImage() -> UIImage? {
|
||||
let context = CIContext()
|
||||
guard let cgImage = context.createCGImage(base, from: base.extent) else {
|
||||
return nil
|
||||
}
|
||||
return UIImage(cgImage: cgImage)
|
||||
}
|
||||
}
|
||||
76
Pods/ZLPhotoBrowser/Sources/Extensions/UIView+ZLPhotoBrowser.swift
generated
Normal file
76
Pods/ZLPhotoBrowser/Sources/Extensions/UIView+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// UIView+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2022/9/27.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base: UIView {
|
||||
var top: CGFloat {
|
||||
base.frame.minY
|
||||
}
|
||||
|
||||
var bottom: CGFloat {
|
||||
base.frame.maxY
|
||||
}
|
||||
|
||||
var left: CGFloat {
|
||||
base.frame.minX
|
||||
}
|
||||
|
||||
var right: CGFloat {
|
||||
base.frame.maxX
|
||||
}
|
||||
|
||||
var width: CGFloat {
|
||||
base.frame.width
|
||||
}
|
||||
|
||||
var height: CGFloat {
|
||||
base.frame.height
|
||||
}
|
||||
|
||||
var snapshotImage: UIImage? {
|
||||
UIGraphicsBeginImageContextWithOptions(base.bounds.size, base.isOpaque, UIScreen.main.scale)
|
||||
guard let context = UIGraphicsGetCurrentContext() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
base.layer.render(in: context)
|
||||
let image = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return image
|
||||
}
|
||||
|
||||
func setCornerRadius(_ radius: CGFloat) {
|
||||
base.layer.cornerRadius = radius
|
||||
base.layer.masksToBounds = true
|
||||
}
|
||||
|
||||
func addBorder(color: UIColor, width: CGFloat) {
|
||||
base.layer.borderColor = color.cgColor
|
||||
base.layer.borderWidth = width
|
||||
}
|
||||
}
|
||||
|
||||
36
Pods/ZLPhotoBrowser/Sources/Extensions/UIViewController+ZLPhotoBrowser.swift
generated
Normal file
36
Pods/ZLPhotoBrowser/Sources/Extensions/UIViewController+ZLPhotoBrowser.swift
generated
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// UIViewController+ZLPhotoBrowser.swift
|
||||
// ZLPhotoBrowser
|
||||
//
|
||||
// Created by long on 2021/12/28.
|
||||
//
|
||||
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
|
||||
extension ZLPhotoBrowserWrapper where Base: UIViewController {
|
||||
func showAlertController(_ alertController: UIAlertController) {
|
||||
if deviceIsiPad() {
|
||||
alertController.popoverPresentationController?.sourceView = base.view
|
||||
}
|
||||
base.showDetailViewController(alertController, sender: nil)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user