4

I get images that are in 1920x1080 resolution. I am attempting to crop them to the center square area (ie 1080x1080 square in the center). The resolution may change in the future. Would it be possible to crop the image this way? I have tried a couple things posted on SO, but I always get an image that is 660x1080 if I try to crop then center. Here is an image depicting what I want to achieve. pic

Basically the red is original, green is what I want, and yellow is just showing mixX and midY lines.

The code I tried.

func imageByCroppingImage(image: UIImage, toSize size: CGSize) -> UIImage{
    let newCropWidth: CGFloat?
    let newCropHeight: CGFloat?

    if image.size.width < image.size.height {
        if image.size.width < size.width {
            newCropWidth = size.width
        } else {
            newCropWidth = image.size.width
        }
        newCropHeight = (newCropWidth! * size.height) / size.width
    } else {
        if image.size.height < size.height {
            newCropHeight = size.height
        } else {
            newCropHeight = image.size.height
        }
        newCropWidth = (newCropHeight! * size.width) / size.height
    }

    let x = image.size.width / 2.0 - newCropWidth! / 2.0
    let y = image.size.height / 2.0 - newCropHeight! / 2.0

    let cropRect = CGRect(x: x, y: y, width: newCropWidth!, height: newCropHeight!)
    let imageRef = image.cgImage!.cropping(to: cropRect)

    let cropped = UIImage(cgImage: imageRef!, scale: 1.0, orientation: .right)
    return cropped
}

And then I pass that method a CGSize(1080, 1080). I get an image that is 660, 1080. Any thoughts?

The intent is to crop the image, not to just display it centered.

Minebomber
  • 1,209
  • 2
  • 12
  • 35
  • try with imageView.center & also share the code – Arun Jun 08 '17 at 13:27
  • Are you trying to literally crop the original image or just present it squared? – Leo Dabus Jun 08 '17 at 13:30
  • @LeoDabus trying to crop it. – Minebomber Jun 08 '17 at 13:36
  • You can use https://stackoverflow.com/questions/29046571/cut-a-uiimage-into-a-circle-swiftios/29047372#29047372 without adding `UIBezierPath(ovalIn: breadthRect).addClip()` – Leo Dabus Jun 08 '17 at 13:50
  • @LeoDabus I tried that with a test 1080x1920 image found online (https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ0K0TZoRAJUOFLFNf55wsyR9xzGMA-BD-_BetOBBSk-AzGdVwL8Q) and this is what I get. (http://imgur.com/GOzmiUA) It turns out VERY pixelated. – Minebomber Jun 08 '17 at 16:47
  • The original link is very low quality 168x300 – Leo Dabus Jun 08 '17 at 16:49
  • 1
    @LeoDabus I just realized that in my testing. I updated the image and it works. If you could put the original comment in an answer ill accept it. Thank you so much. – Minebomber Jun 08 '17 at 16:56

1 Answers1

10

You can use the same approach I used in this answer without the line UIBezierPath(ovalIn: breadthRect).addClip()


extension UIImage {
    var isPortrait:  Bool    { size.height > size.width }
    var isLandscape: Bool    { size.width > size.height }
    var breadth:     CGFloat { min(size.width, size.height) }
    var breadthSize: CGSize  { .init(width: breadth, height: breadth) }
    func squared(isOpaque: Bool = false) -> UIImage? {
        guard let cgImage = cgImage?
            .cropping(to: .init(origin: .init(x: isLandscape ? ((size.width-size.height)/2).rounded(.down) : 0,
                                              y: isPortrait  ? ((size.height-size.width)/2).rounded(.down) : 0),
                                size: breadthSize)) else { return nil }
        let format = imageRendererFormat
        format.opaque = isOpaque
        return UIGraphicsImageRenderer(size: breadthSize, format: format).image { _ in
            UIImage(cgImage: cgImage, scale: 1, orientation: imageOrientation)
            .draw(in: .init(origin: .zero, size: breadthSize))
        }
    }
}

let imageURL = URL(string: "https://i.stack.imgur.com/Xs4RX.jpg")!
let image = UIImage(data: try! Data(contentsOf: imageURL))!

let squared = image.squared()
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571