What exactly is CIImage extent

I have doubts about Core Image coordinate system, way transforms are applied and way the image extent is determined. I couldn't find much in documentation or on internet so I tried the following code to rotate CIImage and display it in UIImageView. As I understand there is no absolute coordinate system in Core Image. The bottom left corner of an image is supposed to be (0,0). But my experiments show something else.

I created a prototype to rotate a CIImage by pi/10 radians on each button click. Here is the code I wrote.

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    imageView.contentMode = .scaleAspectFit
    let uiImage = UIImage(contentsOfFile: imagePath)
    
    ciImage = CIImage(cgImage: (uiImage?.cgImage)!)
    imageView.image = uiImage
}

private var currentAngle = CGFloat(0)
private var ciImage:CIImage!
private var ciContext = CIContext()

  @IBAction func rotateImage() {
    
    let extent = ciImage.extent
    
    let translate = CGAffineTransform(translationX: extent.midX, y: extent.midY)
    let uiImage = UIImage(contentsOfFile: imagePath)
    
    currentAngle = currentAngle + CGFloat.pi/10
    
    let rotate = CGAffineTransform(rotationAngle: currentAngle)
    let translateBack = CGAffineTransform(translationX: -extent.midX, y: -extent.midY)
    
    let transform = translateBack.concatenating(rotate.concatenating(translate))
    
    ciImage = CIImage(cgImage: (uiImage?.cgImage)!)
    ciImage = ciImage.transformed(by: transform)
    
    NSLog("Extent \(ciImage.extent), Angle \(currentAngle)")
    let cgImage = ciContext.createCGImage(ciImage, from: ciImage.extent)
    
    imageView.image = UIImage(cgImage: cgImage!)
}

But in the logs, I see the extent of images have negative origin.x and origin.y. What does it mean? Relative to whom it is negative and where exactly is (0,0) then? What exactly is image extent and how does Core Image coordinate system work?

2021-09-24 14:43:29.280393+0400 CoreImagePrototypes[65817:5175194] Metal API Validation Enabled

2021-09-24 14:43:31.094877+0400 CoreImagePrototypes[65817:5175194] Extent (-105.0, -105.0, 1010.0, 1010.0), Angle 0.3141592653589793

2021-09-24 14:43:41.426371+0400 CoreImagePrototypes[65817:5175194] Extent (-159.0, -159.0, 1118.0, 1118.0), Angle 0.6283185307179586

2021-09-24 14:43:42.244703+0400 CoreImagePrototypes[65817:5175194] Extent (-159.0, -159.0, 1118.0, 1118.0), Angle 0.9424777960769379

  • WHat is the size of the image ? Isn't rotation around the center of the image (that would explain x is growing negatively, till you reach π/4.

  • Size of the image is 800x800, but that's not the point I guess. The main goal is understanding how extent is influenced by transform and how exactly does Core Image Coordinate system work? Why the origin of new image formed by rotation negative and not (0,0)? Because without this understanding, it is impossible to develop anything serious and complex.

  • OOPer image illustrates precisely what I said: rotation is around the center, hence when rotating, the left edge is more on the left (in fact the whole frame is larger). The size was needed to compute how much frame changed.

Add a Comment

Accepted Reply

The doc of extent says:

This rectangle specifies the extent of the image in working space coordinates.

In other words, it is a rectangular region which the processed image is expected to occupy in the same coordinate as in the original image.

Don't you think it is quite reasonable you get negative values when you applied rotation on the image?

  • Ok so it is the smallest bounding box of the image in that case, that seems reasonable. So I will need to manually resize the image to fit in the original bounding box for which I will need to scale the image back. The next question that arises is how do I know the bounding box before applying a transform? I will need that to calculate the scaling factor.

  • @testinstadev, Generally, you should better not include two or more different topics in one thread. But you already have it in the local variable extent.

  • Ok I used trigonometry to calculate the new extent. Formulas work! Thank you so much for clarifying.

Add a Comment

Replies

The doc of extent says:

This rectangle specifies the extent of the image in working space coordinates.

In other words, it is a rectangular region which the processed image is expected to occupy in the same coordinate as in the original image.

Don't you think it is quite reasonable you get negative values when you applied rotation on the image?

  • Ok so it is the smallest bounding box of the image in that case, that seems reasonable. So I will need to manually resize the image to fit in the original bounding box for which I will need to scale the image back. The next question that arises is how do I know the bounding box before applying a transform? I will need that to calculate the scaling factor.

  • @testinstadev, Generally, you should better not include two or more different topics in one thread. But you already have it in the local variable extent.

  • Ok I used trigonometry to calculate the new extent. Formulas work! Thank you so much for clarifying.

Add a Comment