For those, who might run into similar problems as I did, I post this Swift playground code, which helped me understand what's going on and how to tackle it:
import UIKit
let image : UIImage = UIImage(named: "down.JPG")!
image.size
image.imageOrientation.rawValue
let center = CGPoint(x: 0.3, y: 0.3)
let kx = (center.x > 0.5 ? (1-center.x) : center.x)
let ky = (center.y > 0.5 ? (1-center.y) : center.y)
let size = CGSize(width: image.size.width*kx, height: image.size.height*ky)
// cropRect is defined in UIImage coordinate system
// it is defined as a rectangle with center in "center", with proportions
// to the original image. size of rectangle is defined by the distance from
// the center to the nearest edge divided by 2
// this was chosen due to my specific needs and can be adjusted at will
// (just don't exceed limits of the original image)
var cropRect = CGRect(x: center.x*image.size.width-size.width/2,
y: center.y*image.size.height-size.height/2,
width: size.width,
height: size.height)
cropRect
if self.imageOrientation == .right || self.imageOrientation == .down || self.imageOrientation == .left
{
let k : CGFloat = (self.imageOrientation == .right ? -1 :(self.imageOrientation == .left ? 1 : 2))
let dy = (self.imageOrientation == .right ? self.size.width : (self.imageOrientation == .left ? 0 :self.size.height))
let dx = (self.imageOrientation == .down ? self.size.width : (self.imageOrientation == .left ? self.size.height : 0))
let rotate = CGAffineTransform(rotationAngle: k*90/180*CGFloat.pi)
let translate = CGAffineTransform(translationX: dx, y: dy)
cropRect = cropRect.applying(rotate).applying(translate)
}
let cgImage = image.cgImage!
cgImage.width
cgImage.height
cropRect
let cropped = cgImage.cropping(to: cropRect)
if cropped != nil
{
cropped!.width
cropped!.height
let croppedImage = UIImage(cgImage: cropped!, scale: image.scale, orientation: image.imageOrientation)
}
Take 4 pictures: "up.JPG", "down.JPG", "left.JPG" and "right.JPG" for all possible camera configurations and upload them to the Resources subfolder of your playground. Load them one by one and check what's happening to the arguments. This code helped me to come up with the working solution: when image has .right or .down orientation, apply affine transforms to the cropping rectangle in order to get desired cropping.