0

I'm building a Mac OS app in SwiftUI. I have a use case where I must crop part of the image (which is a screenshot) and ensure the cropped part is at least 320x240 and match the aspect ratio if it exceeds.

I have below code so far:

func fitImageInRect(_ original: NSImage, rect: CGRect) -> NSImage {
    var originalRect = CGRect(x: 0, y: 0, width: original.size.width, height: original.size.height)
    var width = 0.0, height = 0.0
    if rect.width > rect.height {
        width = rect.width
        if width > 320 {
            let ratio = width / 320
            height = 240 * ratio
        } else {
            width = 320
            height = 240
        }
    } else {
        height = rect.height
        if height > 240 {
            let ratio = height / 240
            width = 320 * ratio
        } else {
            width = 320
            height = 240
        }
    }

    var originX = rect.origin.x
    var originY = rect.origin.y
    
    if originX > (originalRect.width - 320) {
        originX = originalRect.width - 320
    }
    
    if originY > (originalRect.height - 240) {
        originY = originalRect.height - 240
    }

    let thumbnailRect = CGRect(x: Int(originX), y: Int(originY), width: Int(width), height: Int(height))

    guard let ref = original.cgImage(forProposedRect: &originalRect, context: nil, hints: nil) else { return original }
    let cropped = ref.cropping(to: thumbnailRect)

    return NSImage(cgImage: cropped!, size: NSSize(width: width, height: height))
}

The goal is as follows:

  1. If the rect size is 150x50, then the cropped photo be 320x240 with rect at center of it.
  2. If the rect size is 640x50, then the cropped photo be 640x480 with rect at center of it.

But somehow, the code is behaving otherwise. The final output is seemingly from a vertically flipped thumbnailRect and I can't figure out why.

VPZ
  • 741
  • 8
  • 19
  • What is the `rect` parameter that you pass in? – Joakim Danielson May 26 '23 at 08:40
  • It's smaller area in the image e.g., 150x100 that I want to be centered in a thumbnail of 320x240 size cropped out of 1920x1080 screenshot. – VPZ May 26 '23 at 10:07
  • Ok, so we can assume that it's smaller (or equal) to the image size – Joakim Danielson May 26 '23 at 10:10
  • 100%, yes. It will always be smaller than 1920x1080 but can be smaller or bigger than 320x240 – VPZ May 26 '23 at 11:02
  • 1
    I played around with this a bit and while I didn’t solve the problem I did notice that when printing `ref` the size values of the CGImage was much larger than the original image which makes me believe the issue is with how `ref` was created. – Joakim Danielson May 26 '23 at 11:15
  • Yeah, I did some debugging too. ```NSImage size 3024.000000x1964.000000 actually was 6048x3928 on CGImage Cropping to 320.000000x240.000000 on 92.302368,1724.000000``` Seems like the cgImage created from screenshot's `NSImage` is double the size. So the rect is not vertically flipped, it's that the `CGImage` is too large and it starts from bottom on `NSImage`'s farthest `y` origin. – VPZ May 29 '23 at 03:04

0 Answers0