はじめに
QR読取時に読取範囲を指定する必要があったのだが、なかなか思うように範囲を設定できなかったのでログに残しておく。
CGRect直で読取り範囲を算出(失敗)
AVCaptureMetadataOutput
インスタンスのrectOfInterest
プロパティにCGRect
インスタンスを使って読取範囲を指定するサンプルをいくつか見つけたのだが、意図通りに読取範囲を指定することができなかった(Y軸にずれがある)。
// CGRectで指定しているサンプル
self.metadataOutput.rectOfInterest = CGRect(x: frame.minY,y: 1-frame.minX-frame.size.width, width: frame.size.height,height: frame.size.width)
[参考]
[難点]
- 座標とサイズの指定が割合の値である。
- カメラの向きが横(Landscape)になっており、xyが反転している。
- 実機による検証で、実際にどこが読み取り範囲になっているのかを確認する方法がわからない(分かる人がいたら教えてください)
自分としては、1.と2.については配慮して値を割り出したつもりだったのだが意図通りの動作にならない。
AVCaptureVideoPreviewLayer
のmetadataOutputRectConverted
メソッドを使用(成功)
rectOfInterest
の設定値を、自力で割り出すのではなく、AVCaptureVideoPreviewLayer
のmetadataOutputRectConverted
メソッドで変換すると意図通りに読取り範囲を指定できた。
// preview: AVCaptureVideoPreviewLayerインスタンスを入れるUIViewインスタンス
// previewLayer: AVCaptureVideoPreviewLayerインスタンス
// metadataOutput: AVCaptureMetadataOutputインスタンス
let size = 240
let screenWidth = preview.frame.size.width
let screenHeight = preview.frame.size.height
let xPos = (CGFloat(screenWidth) / CGFloat(2)) - (CGFloat(size) / CGFloat(2))
let yPos = (CGFloat(screenHeight) / CGFloat(2)) - (CGFloat(size) / CGFloat(2))
let scanRect = CGRect(x: Int(xPos), y: Int(yPos), width: size, height: size)
// rectOfInterestに入れる値をAVCaptureVideoPreviewLayerインスタンスのmetadataOutputRectConvertedメソッド経由で算出
self.metadataOutput.rectOfInterest = self.previewLayer.metadataOutputRectConverted(fromLayerRect: scanRect)
let v = UIView()
v.layer.borderWidth = 1
v.layer.borderColor = UIColor.red.cgColor
v.frame = scanRect
preview.addSubview(v)
[参考]