Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to crop a UIImage without losing it's scale property?

Goal: Crop a UIImage (that starts with a scale property of 2.0)

I perform the following code:

let croppedCGImage = originalUIImage.cgImage!.cropping(to: cropRect)
let croppedUIImage = UIImage(cgImage: croppedCGImage!)

This code works, however the result, croppedUIImage, has an incorrect scale property of 1.0.


I've tried specifying the scale when creating the final image:

let croppedUIImage = UIImage(cgImage: croppedCGImage!, scale: 2.0, orientation: .up)

This yields the correct scale, but it cuts the size dimensions in half incorrectly.


What should I do here?

(*Note: the scale property on the UIImage is important because I later save the image with UIImagePNGRepresentation(_ image: UIImage) which is affected by the scale property)



Edit:

I got the following to work. Unfortunately it's just substantially slower than the CGImage cropping function.

extension UIImage {
    func cropping(to rect: CGRect) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(rect.size, false, self.scale)

        self.draw(in: CGRect(x: -rect.origin.x, y: -rect.origin.y, width: self.size.width, height: self.size.height))

        let croppedImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        return croppedImage
    }
}
like image 714
bearMountain Avatar asked Sep 23 '16 07:09

bearMountain


3 Answers

Try this:

extension UIImage {
    func imageByCropToRect(rect:CGRect, scale:Bool) -> UIImage {

        var rect = rect
        var scaleFactor: CGFloat = 1.0
        if scale  {
            scaleFactor = self.scale
            rect.origin.x *= scaleFactor
            rect.origin.y *= scaleFactor
            rect.size.width *= scaleFactor
            rect.size.height *= scaleFactor
        }

        var image: UIImage? = nil;
        if rect.size.width > 0 && rect.size.height > 0 {
            let imageRef = self.cgImage!.cropping(to: rect)
            image = UIImage(cgImage: imageRef!, scale: scaleFactor, orientation: self.imageOrientation)
        }

        return image!
    }
}
like image 70
CHwang Avatar answered Nov 11 '22 10:11

CHwang


Use this Extension :-

extension UIImage {

    func cropping(to quality: CGInterpolationQuality, rect: CGRect) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(rect.size, false, self.scale)

        let context = UIGraphicsGetCurrentContext()! as CGContext
        context.interpolationQuality = quality

        let drawRect : CGRect = CGRect(x: -rect.origin.x, y: -rect.origin.y, width: self.size.width, height: self.size.height)

        context.clip(to: CGRect(x:0, y:0, width: rect.size.width, height: rect.size.height))

        self.draw(in: drawRect)

        let croppedImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        return croppedImage
    }
}
like image 5
Rahul Mayani Avatar answered Nov 11 '22 08:11

Rahul Mayani


I'm using the ImageHelper Pod for iOS and tvOS and it's working perfectly and might also fit your needs.

It brings a lot UIImage Extensions such as:

Crop and Resize

// Crops an image to a new rect
func crop(bounds: CGRect) -> UIImage?

// Crops an image to a centered square
func cropToSquare() -> UIImage? {

// Resizes an image
func resize(size:CGSize, contentMode: UIImageContentMode = .ScaleToFill) -> UIImage?

Screen Density

// To create an image that is Retina aware, use the screen scale as a multiplier for your size. You should also use this technique for padding or borders.
let width = 140 * UIScreen.mainScreen().scale
let height = 140 * UIScreen.mainScreen().scale
let image = UIImage(named: "myImage")?.resize(CGSize(width: width, height: height))

Also stuff like: Image Effects

// Applies a light blur effect to the image
func applyLightEffect() -> UIImage?
// Applies a extra light blur effect to the image
func applyExtraLightEffect() -> UIImage?
// Applies a dark blur effect to the image
func applyDarkEffect() -> UIImage?
// Applies a color tint to an image
func applyTintEffect(tintColor: UIColor) -> UIImage?
// Applies a blur to an image based on the specified radius, tint color saturation and mask image
func applyBlur(blurRadius:CGFloat, tintColor:UIColor?, saturationDeltaFactor:CGFloat, maskImage:UIImage? = nil) -> UIImage?
like image 5
David Seek Avatar answered Nov 11 '22 09:11

David Seek