Tom Shen
Tom Shen

Reputation: 2028

How to trim an NSImage by giving bounds

I have an NSImage object, I have an CIDetector object that detects QR codes on that image. After it detects, I wants to trim that image so it only has the QR code in it. This is how I've got the bounds of the QR code:

NSArray *features = [myQRDetector featureInImage:myCIImage];
CIQRCodeFeature *qrFeature = features[0];
CGRect qrBounds = qrFeature.bounds;

Now how can I trim the image so it only contains the area described by qrBounds variable.

Upvotes: 2

Views: 2093

Answers (3)

endavid
endavid

Reputation: 1963

The answer from onmyway133 is great, but it doesn't preserve the datatype of the source image. For instance, if your source is an .hdr image, each color channel will be floats, but the cropped image will be an 8-bit integer RGBA image.

For preserving the format of the source, it seems you have to go down to the associated CGImage. I do this:

extension NSImage {
    func cropping(to rect: CGRect) -> NSImage {
        var imageRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        guard let imageRef = self.cgImage(forProposedRect: &imageRect, context: nil, hints: nil) else {
            return NSImage(size: rect.size)
        }
        guard let crop = imageRef.cropping(to: rect) else {
            return NSImage(size: rect.size)
        }
        return NSImage(cgImage: crop, size: NSZeroSize)
    }
}

Upvotes: 3

onmyway133
onmyway133

Reputation: 48175

In Swift 5

func trim(image: NSImage, rect: CGRect) -> NSImage {
    let result = NSImage(size: rect.size)
    result.lockFocus()

    let destRect = CGRect(origin: .zero, size: result.size)
    image.draw(in: destRect, from: rect, operation: .copy, fraction: 1.0)

    result.unlockFocus()
    return result
}

Upvotes: 6

Ken Thomases
Ken Thomases

Reputation: 90651

You need to create a new NSImage and draw the part of the original image you want to it.

NSImage* newImage = [[NSImage alloc] initWithSize:NSSizeFromCGSize(qrBounds.size)];
[newImage lockFocus];
NSRect dest = { NSZeroPoint, newImage.size };
[origImage drawInRect:dest fromRect:NSRectFromCGRect(qrBounds) operation:NSCompositeCopy fraction:1];
[newImage unlockFocus];

Upvotes: 1

Related Questions