Search code examples
iosswiftcrop

CGImage cropping doesn't give the specified rectangle


I have a view where you can paint on. I save the minimal and maximal x and y touch-locations to specify the rectangle in which was painted. I tested, if the rectangle was right by adding a view with it as a frame, and everything worked fine. But when I am cropping the image to the rectangle, it gives me some other part.

guard let cg_img = self.asImage().cgImage?.cropping(to: CGRect(x: minX, y: minY, width: maxX-minX, height: maxY-minY)) else { return }

My asImage-method:

extension UIView {
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
}

I probably missed something about the cropping method, but I didn't find anything helpful.


Solution

  • Your method to retrieve the UIImage from the UIView will return an image with the scale of the device. And your coordinates are likely in “points”. But CGImage coordinates are in pixels. You’ll have to convert your coordinates accordingly (by the scale of the image). E.g. if you’re on a @3x device, multiply these values by the scale of the original image before cropping.


    This won’t be an issue for your screen snapshots, but for the sake of future readers, please note that the CGRect of the CGImage crop will be affected by the image rotation, e.g. portrait images captured by the camera. See imageOrientation. Bottom line, in addition to the scale issue noted earlier, also be aware that the width and height of the CGImage may be flipped from those of the UIImage.