How do I use the metadataOutputRectOfInterestForRect method and rectOfInterest property to scan a specific area? (QR Code)
I wasn't really able to clarify the issue with metadataOutputRectOfInterestForRect, however, you can directly set the property as well. You need to the have the resolution in width and height of your video, which you can specify in advance. I quickly used the 640*480 setting. As stated in the documentation, these values have to be
"extending from (0,0) in the top left to (1,1) in the bottom right, relative to the device’s natural orientation".
See https://developer.apple.com/documentation/avfoundation/avcaptureoutput/1616304-metadataoutputrectofinterestforr
Below is the code I tried
var x = scanRect.origin.x/480
var y = scanRect.origin.y/640
var width = scanRect.width/480
var height = scanRect.height/640
var scanRectTransformed = CGRectMake(x, y, width, height)
captureMetadataOutput.rectOfInterest = scanRectTransformed
I just tested it on an iOS device and it seems to work.
Edit
At least I've solved the metadataOutputRectOfInterestForRect problem. I believe you have to do this after the camera has been properly set up and is running, as the camera's resolution is not yet available.
First, add a notification observer method within viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("avCaptureInputPortFormatDescriptionDidChangeNotification:"), name:AVCaptureInputPortFormatDescriptionDidChangeNotification, object: nil)
Then add the following method
func avCaptureInputPortFormatDescriptionDidChangeNotification(notification: NSNotification) {
captureMetadataOutput.rectOfInterest = videoPreviewLayer.metadataOutputRectOfInterestForRect(scanRect)
}
Here you can then reset the rectOfInterest property. Then, in your code, you can display the AVMetadataObject within the didOutputMetadataObjects function
var rect = videoPreviewLayer.rectForMetadataOutputRectOfInterest(YourAVMetadataObject.bounds)
dispatch_async(dispatch_get_main_queue(),{
self.qrCodeFrameView.frame = rect
})
I've tried, and the rectangle was always within the specified area.
Xcode AVCapturesession scan Barcode in specific frame (rectOfInterest is not working)
As soon as i got it, it was absolutely clear:
The AVCaptureMetadataOutput is defined by pixels, therefore to map the coordinates of the display to that in the output, i had to use metadataOutputRectOfInterestForRect:
From AVCaptureOutput.h:
/*!
@method metadataOutputRectOfInterestForRect:
@abstract
Converts a rectangle in the receiver's coordinate space to a rectangle of interest in the coordinate space of an AVCaptureMetadataOutput
whose capture device is providing input to the receiver.
@param rectInOutputCoordinates
A CGRect in the receiver's coordinates.
@result
A CGRect in the coordinate space of the metadata output whose capture device is providing input to the receiver.
@discussion
AVCaptureMetadataOutput rectOfInterest is expressed as a CGRect where {0,0} represents the top left of the picture area,
and {1,1} represents the bottom right on an unrotated picture. This convenience method converts a rectangle in
the coordinate space of the receiver to a rectangle of interest in the coordinate space of an AVCaptureMetadataOutput
whose AVCaptureDevice is providing input to the receiver. The conversion takes orientation, mirroring, and scaling into
consideration. See -transformedMetadataObjectForMetadataObject:connection: for a full discussion of how orientation and mirroring
are applied to sample buffers passing through the output.
*/
- (CGRect)metadataOutputRectOfInterestForRect:(CGRect)rectInOutputCoordinates NS_AVAILABLE_IOS(7_0);
After using this to set the rectOfInterest it worked.
How to make camera background darker other than rectOfInterest in Swift 5, XCode 11
let path = CGMutablePath()
path.addRect(bounds)
path.addRect(rectOfInterest)
let maskLayer = CAShapeLayer()
maskLayer.path = path
maskLayer.fillColor = UIColor.black.withAlphaComponent(0.6).cgColor
maskLayer.fillRule = .evenOdd
addSublayer(maskLayer)
Add the mask layer before adding the layer with the edges.
Have a look at this repo for my implementation.
Related Topics
Proper Use of Loadview and Viewdidload with Uiviewcontroller Without Nibs/Xibs
How to Programmatically Increase Uitableview Cell's Height in Iphone
Rotate a Uiview Around Its Center But Several Times
Programmatically Get a Storyboard Id
Horizontal Uiscrollview Inside Custom Uitableviewcell - Using Ib Storyboard - Not Scrolling
iOS Jailbreak How Do Intercept Sms/Text Messages
Convert String With Unknown Format (Any Format) to Date
Concurrent VS Serial Queues in Gcd
How to Use Objective-C Blocks as Properties
How to Programmatically Find Swift's Version
How to Fix Failed to Fetch Default Token Error
Facebook Sdk 3.1 for iOS - Runs on iOS6, But Crashes on iOS 5.X
Working with Live Photos in Playground
Dynamic Height for Static Table Cells with Wrapping Labels
Swiftui: Navigationdestinationlink Deprecated