Don_Mag

Untitled

Sep 10th, 2020 (edited)
783
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // usage:
  2. class ViewController: UIViewController {
  3.     override func viewDidLoad() {
  4.         super.viewDidLoad()
  5.  
  6.         if let img = UIImage(named: "bkg") {
  7.             if let centerImg = img.clipFromCenter(clipSize: CGSize(width: 250, height: 200))
  8.             // do what you want with the new UIImage
  9.             }
  10.         }
  11.     }
  12. }
  13.  
  14. // extension - see DonMag added:
  15. //    func clipFromCenter(clipSize: CGSize) -> UIImage?
  16. // at end
  17. //
  18. // from: https://stackoverflow.com/a/28513086/6257435
  19. extension UIImage {
  20.    
  21.     /// Resize the image to be the required size, stretching it as needed.
  22.     ///
  23.     /// - parameter newSize:      The new size of the image.
  24.     /// - parameter contentMode:  The `UIView.ContentMode` to be applied when resizing image.
  25.     ///                           Either `.scaleToFill`, `.scaleAspectFill`, or `.scaleAspectFit`.
  26.     ///
  27.     /// - returns:                Return `UIImage` of resized image.
  28.    
  29.     func scaled(to newSize: CGSize, contentMode: UIView.ContentMode = .scaleToFill) -> UIImage? {
  30.         switch contentMode {
  31.         case .scaleToFill:
  32.             return filled(to: newSize)
  33.            
  34.         case .scaleAspectFill, .scaleAspectFit:
  35.             let horizontalRatio = size.width  / newSize.width
  36.             let verticalRatio   = size.height / newSize.height
  37.            
  38.             let ratio: CGFloat!
  39.             if contentMode == .scaleAspectFill {
  40.                 ratio = min(horizontalRatio, verticalRatio)
  41.             } else {
  42.                 ratio = max(horizontalRatio, verticalRatio)
  43.             }
  44.            
  45.             let sizeForAspectScale = CGSize(width: size.width / ratio, height: size.height / ratio)
  46.             let image = filled(to: sizeForAspectScale)
  47.             let doesAspectFitNeedCropping = contentMode == .scaleAspectFit && (newSize.width > sizeForAspectScale.width || newSize.height > sizeForAspectScale.height)
  48.             if contentMode == .scaleAspectFill || doesAspectFitNeedCropping {
  49.                 let subRect = CGRect(
  50.                     x: floor((sizeForAspectScale.width - newSize.width) / 2.0),
  51.                     y: floor((sizeForAspectScale.height - newSize.height) / 2.0),
  52.                     width: newSize.width,
  53.                     height: newSize.height)
  54.                 return image?.cropped(to: subRect)
  55.             }
  56.             return image
  57.            
  58.         default:
  59.             return nil
  60.         }
  61.     }
  62.    
  63.     /// Resize the image to be the required size, stretching it as needed.
  64.     ///
  65.     /// - parameter newSize:   The new size of the image.
  66.     ///
  67.     /// - returns:             Resized `UIImage` of resized image.
  68.    
  69.     func filled(to newSize: CGSize) -> UIImage? {
  70.         let format = UIGraphicsImageRendererFormat()
  71.         format.opaque = false
  72.         format.scale = scale
  73.        
  74.         return UIGraphicsImageRenderer(size: newSize, format: format).image { _ in
  75.             draw(in: CGRect(origin: .zero, size: newSize))
  76.         }
  77.     }
  78.    
  79.     /// Crop the image to be the required size.
  80.     ///
  81.     /// - parameter bounds:    The bounds to which the new image should be cropped.
  82.     ///
  83.     /// - returns:             Cropped `UIImage`.
  84.    
  85.     func cropped(to bounds: CGRect) -> UIImage? {
  86.         // if bounds is entirely within image, do simple CGImage `cropping` ...
  87.        
  88.         if CGRect(origin: .zero, size: size).contains(bounds), imageOrientation == .up, let cgImage = cgImage {
  89.             return cgImage.cropping(to: bounds * scale).flatMap {
  90.                 UIImage(cgImage: $0, scale: scale, orientation: imageOrientation)
  91.             }
  92.         }
  93.        
  94.         // ... otherwise, manually render whole image, only drawing what we need
  95.        
  96.         let format = UIGraphicsImageRendererFormat()
  97.         format.opaque = false
  98.         format.scale = scale
  99.        
  100.         return UIGraphicsImageRenderer(size: bounds.size, format: format).image { _ in
  101.             let origin = CGPoint(x: -bounds.minX, y: -bounds.minY)
  102.             draw(in: CGRect(origin: origin, size: size))
  103.         }
  104.     }
  105.    
  106.     /// Resize the image to fill the rectange of the specified size, preserving the aspect ratio, trimming if needed.
  107.     ///
  108.     /// - parameter newSize:   The new size of the image.
  109.     ///
  110.     /// - returns:             Return `UIImage` of resized image.
  111.    
  112.     func scaledAspectFill(to newSize: CGSize) -> UIImage? {
  113.         return scaled(to: newSize, contentMode: .scaleAspectFill)
  114.     }
  115.    
  116.     /// Resize the image to fit within the required size, preserving the aspect ratio, with no trimming taking place.
  117.     ///
  118.     /// - parameter newSize:   The new size of the image.
  119.     ///
  120.     /// - returns:             Return `UIImage` of resized image.
  121.    
  122.     func scaledAspectFit(to newSize: CGSize) -> UIImage? {
  123.         return scaled(to: newSize, contentMode: .scaleAspectFit)
  124.     }
  125.    
  126.     // MARK: DonMag added
  127.     func clipFromCenter(clipSize: CGSize) -> UIImage? {
  128.         var r: CGRect = CGRect(origin: .zero, size: clipSize)
  129.         r.origin.x = (size.width - clipSize.width) * 0.5
  130.         r.origin.y = (size.height - clipSize.height) * 0.5
  131.         return cropped(to: r)
  132.     }
  133.  
  134. }
  135.  
  136. extension CGSize {
  137.     static func * (lhs: CGSize, rhs: CGFloat) -> CGSize {
  138.         return CGSize(width: lhs.width * rhs, height: lhs.height * rhs)
  139.     }
  140. }
  141.  
  142. extension CGPoint {
  143.     static func * (lhs: CGPoint, rhs: CGFloat) -> CGPoint {
  144.         return CGPoint(x: lhs.x * rhs, y: lhs.y * rhs)
  145.     }
  146. }
  147.  
  148. extension CGRect {
  149.     static func * (lhs: CGRect, rhs: CGFloat) -> CGRect {
  150.         return CGRect(origin: lhs.origin * rhs, size: lhs.size * rhs)
  151.     }
  152. }
  153.  
RAW Paste Data