UIImage+Extension.swift 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. //
  2. // UIImage+Extension.swift
  3. // Lanu
  4. //
  5. // Created by OneeChan on 2025/11/16.
  6. //
  7. import Foundation
  8. import Photos
  9. extension UIImage {
  10. /// 生成线性渐变图片
  11. /// - Parameters:
  12. /// - colors: 渐变颜色数组(至少两种)
  13. /// - size: 图片尺寸
  14. /// - startPoint: 渐变起点(坐标系:左上角(0,0),右下角(1,1))
  15. /// - endPoint: 渐变终点
  16. /// - Returns: 生成的渐变图片(nil 表示参数无效)
  17. static func generateLinearGradientImage(
  18. colors: [UIColor],
  19. size: CGSize,
  20. location: [NSNumber],
  21. startPoint: CGPoint = CGPoint(x: 0, y: 0),
  22. endPoint: CGPoint = CGPoint(x: 1, y: 0)
  23. ) -> UIImage? {
  24. // 校验参数有效性
  25. guard colors.count >= 2, size.width > 0, size.height > 0 else {
  26. return nil
  27. }
  28. // 创建渐变图层
  29. let gradientLayer = CAGradientLayer()
  30. gradientLayer.frame = CGRect(origin: .zero, size: size)
  31. gradientLayer.colors = colors.map { $0.cgColor } // 转换为 CGColor
  32. gradientLayer.locations = location
  33. gradientLayer.startPoint = startPoint
  34. gradientLayer.endPoint = endPoint
  35. // 渲染图层为图片
  36. let renderer = UIGraphicsImageRenderer(size: size)
  37. return renderer.image { _ in
  38. gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
  39. }
  40. }
  41. }
  42. enum LNImageCompressType {
  43. case none
  44. case avatar
  45. case photoWall
  46. var maxSize: CGSize {
  47. switch self {
  48. case .none: .zero
  49. case .avatar: .init(width: 600, height: 600)
  50. case .photoWall: .init(width: 750, height: 1334)
  51. }
  52. }
  53. }
  54. extension UIImage {
  55. func saveToLibrary(completion: ((Bool, Error?) -> Void)?) {
  56. // 步骤1:检查并请求相册权限
  57. PHPhotoLibrary.requestAuthorization { status in
  58. DispatchQueue.main.async { // 回调默认在子线程,切回主线程处理UI
  59. switch status {
  60. case .authorized, .limited: // 授权(含iOS 14+有限授权)
  61. // 步骤2:异步保存图片到相册
  62. PHPhotoLibrary.shared().performChanges({
  63. // 创建保存请求
  64. PHAssetChangeRequest.creationRequestForAsset(from: self)
  65. }) { success, error in
  66. DispatchQueue.main.async {
  67. completion?(success, error)
  68. }
  69. }
  70. case .denied, .restricted: // 权限拒绝/受限
  71. let error = NSError(domain: "AlbumError", code: -1, userInfo: [
  72. NSLocalizedDescriptionKey: "相册权限已拒绝,请前往设置开启"
  73. ])
  74. completion?(false, error)
  75. case .notDetermined: // 理论上不会走到这里(requestAuthorization已触发授权)
  76. completion?(false, NSError(domain: "AlbumError", code: -2, userInfo: [
  77. NSLocalizedDescriptionKey: "权限请求未完成"
  78. ]))
  79. @unknown default:
  80. completion?(false, NSError(domain: "AlbumError", code: -3, userInfo: [
  81. NSLocalizedDescriptionKey: "未知权限状态"
  82. ]))
  83. }
  84. }
  85. }
  86. }
  87. func compress(type: LNImageCompressType) -> UIImage? {
  88. let maxSize: CGSize = type.maxSize
  89. if maxSize == .zero {
  90. UIGraphicsBeginImageContext(CGSizeMake(size.width, size.height));
  91. draw(in: .init(origin: .zero, size: size))
  92. let convertToUpImage = UIGraphicsGetImageFromCurrentImageContext();
  93. UIGraphicsEndImageContext();
  94. return convertToUpImage
  95. }
  96. if size.width <= maxSize.width
  97. && size.height <= maxSize.height {
  98. return self
  99. }
  100. let widthRatio = maxSize.width / size.width
  101. let heightRatio = maxSize.height / size.height
  102. let scaleRatio = min(widthRatio, heightRatio)
  103. let newSize = CGSize(width: size.width * scaleRatio,
  104. height: size.height * scaleRatio)
  105. let renderer = UIGraphicsImageRenderer(size: newSize)
  106. let resizedImage = renderer.image { _ in
  107. draw(in: CGRect(origin: .zero, size: newSize))
  108. }
  109. return resizedImage
  110. }
  111. }