Don_Mag icon

Untitled

Don_Mag | PRO | 09/10/20 09:11:11 PM UTC (Edited) | 0 ⭐ | 1743 👁️ | Never ⏰ | []
Swift |

4.91 KB

|

None

|

0 👍

/

0 👎

// usage:
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
 
        if let img = UIImage(named: "bkg") {
            if let centerImg = img.clipFromCenter(clipSize: CGSize(width: 250, height: 200))
            // do what you want with the new UIImage
            }
        }
    }
}
 
// extension - see DonMag added: 
//    func clipFromCenter(clipSize: CGSize) -> UIImage?
// at end
//
// from: https://stackoverflow.com/a/28513086/6257435
extension UIImage {
    
    /// Resize the image to be the required size, stretching it as needed.
    ///
    /// - parameter newSize:      The new size of the image.
    /// - parameter contentMode:  The `UIView.ContentMode` to be applied when resizing image.
    ///                           Either `.scaleToFill`, `.scaleAspectFill`, or `.scaleAspectFit`.
    ///
    /// - returns:                Return `UIImage` of resized image.
    
    func scaled(to newSize: CGSize, contentMode: UIView.ContentMode = .scaleToFill) -> UIImage? {
        switch contentMode {
        case .scaleToFill:
            return filled(to: newSize)
            
        case .scaleAspectFill, .scaleAspectFit:
            let horizontalRatio = size.width  / newSize.width
            let verticalRatio   = size.height / newSize.height
            
            let ratio: CGFloat!
            if contentMode == .scaleAspectFill {
                ratio = min(horizontalRatio, verticalRatio)
            } else {
                ratio = max(horizontalRatio, verticalRatio)
            }
            
            let sizeForAspectScale = CGSize(width: size.width / ratio, height: size.height / ratio)
            let image = filled(to: sizeForAspectScale)
            let doesAspectFitNeedCropping = contentMode == .scaleAspectFit && (newSize.width > sizeForAspectScale.width || newSize.height > sizeForAspectScale.height)
            if contentMode == .scaleAspectFill || doesAspectFitNeedCropping {
                let subRect = CGRect(
                    x: floor((sizeForAspectScale.width - newSize.width) / 2.0),
                    y: floor((sizeForAspectScale.height - newSize.height) / 2.0),
                    width: newSize.width,
                    height: newSize.height)
                return image?.cropped(to: subRect)
            }
            return image
            
        default:
            return nil
        }
    }
    
    /// Resize the image to be the required size, stretching it as needed.
    ///
    /// - parameter newSize:   The new size of the image.
    ///
    /// - returns:             Resized `UIImage` of resized image.
    
    func filled(to newSize: CGSize) -> UIImage? {
        let format = UIGraphicsImageRendererFormat()
        format.opaque = false
        format.scale = scale
        
        return UIGraphicsImageRenderer(size: newSize, format: format).image { _ in
            draw(in: CGRect(origin: .zero, size: newSize))
        }
    }
    
    /// Crop the image to be the required size.
    ///
    /// - parameter bounds:    The bounds to which the new image should be cropped.
    ///
    /// - returns:             Cropped `UIImage`.
    
    func cropped(to bounds: CGRect) -> UIImage? {
        // if bounds is entirely within image, do simple CGImage `cropping` ...
        
        if CGRect(origin: .zero, size: size).contains(bounds), imageOrientation == .up, let cgImage = cgImage {
            return cgImage.cropping(to: bounds * scale).flatMap {
                UIImage(cgImage: $0, scale: scale, orientation: imageOrientation)
            }
        }
        
        // ... otherwise, manually render whole image, only drawing what we need
        
        let format = UIGraphicsImageRendererFormat()
        format.opaque = false
        format.scale = scale
        
        return UIGraphicsImageRenderer(size: bounds.size, format: format).image { _ in
            let origin = CGPoint(x: -bounds.minX, y: -bounds.minY)
            draw(in: CGRect(origin: origin, size: size))
        }
    }
    
    /// Resize the image to fill the rectange of the specified size, preserving the aspect ratio, trimming if needed.
    ///
    /// - parameter newSize:   The new size of the image.
    ///
    /// - returns:             Return `UIImage` of resized image.
    
    func scaledAspectFill(to newSize: CGSize) -> UIImage? {
        return scaled(to: newSize, contentMode: .scaleAspectFill)
    }
    
    /// Resize the image to fit within the required size, preserving the aspect ratio, with no trimming taking place.
    ///
    /// - parameter newSize:   The new size of the image.
    ///
    /// - returns:             Return `UIImage` of resized image.
    
    func scaledAspectFit(to newSize: CGSize) -> UIImage? {
        return scaled(to: newSize, contentMode: .scaleAspectFit)
    }
    
    // MARK: DonMag added
    func clipFromCenter(clipSize: CGSize) -> UIImage? {
        var r: CGRect = CGRect(origin: .zero, size: clipSize)
        r.origin.x = (size.width - clipSize.width) * 0.5
        r.origin.y = (size.height - clipSize.height) * 0.5
        return cropped(to: r)
    }
 
}
 
extension CGSize {
    static func * (lhs: CGSize, rhs: CGFloat) -> CGSize {
        return CGSize(width: lhs.width * rhs, height: lhs.height * rhs)
    }
}
 
extension CGPoint {
    static func * (lhs: CGPoint, rhs: CGFloat) -> CGPoint {
        return CGPoint(x: lhs.x * rhs, y: lhs.y * rhs)
    }
}
 
extension CGRect {
    static func * (lhs: CGRect, rhs: CGFloat) -> CGRect {
        return CGRect(origin: lhs.origin * rhs, size: lhs.size * rhs)
    }
}
 

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎