在swift ios中扫描后如何获取二维码图像?
How to get image of qr-code after scanning in swift ios?
我正在 Xcode 中使用 swift 开发二维码 reader 应用程序。我用以下代码扫描了二维码:
import UIKit
import AVFoundation
class ScannerViewController: UIViewController {
var captureSession = AVCaptureSession()
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
var qrCodeFrameView: UIView?
var scannerMetadataObj : AVMetadataMachineReadableCodeObject?
@IBOutlet weak var testImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back)
guard let captureDevice = deviceDiscoverySession.devices.first else {
print("Failed to get the camera device")
return
}
do {
let input = try AVCaptureDeviceInput(device: captureDevice)
captureSession.addInput(input)
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession.addOutput(captureMetadataOutput)
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
captureMetadataOutput.metadataObjectTypes = supportedCodeTypes
} catch {
return
}
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer!)
qrCodeFrameView = UIView()
if let qrCodeFrameView = qrCodeFrameView {
qrCodeFrameView.layer.borderColor = UIColor.green.cgColor
qrCodeFrameView.layer.borderWidth = 2
view.addSubview(qrCodeFrameView)
view.bringSubviewToFront(qrCodeFrameView)
}
}
override func viewWillAppear(_ animated: Bool) {
captureSession.startRunning()
}
override func viewWillDisappear(_ animated: Bool) {
captureSession.stopRunning()
qrCodeFrameView?.frame = CGRect.zero
}
}
extension ScannerViewController: AVCaptureMetadataOutputObjectsDelegate {
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
// Check if the metadataObjects array is not nil and it contains at least one object.
if metadataObjects.count == 0 {
qrCodeFrameView?.frame = CGRect.zero
return
}
// Get the metadata object.
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
scannerMetadataObj = metadataObj
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
qrCodeFrameView?.frame = barCodeObject!.bounds
self.testImageView.image = // set image with qr-code
}
}
扫描二维码后,我想获取二维码的图片,将testImageView的图片设置为获取的图片。怎么可能?我这样做是因为我想将该图像保存在数据库中以备将来使用。在这里我唯一的问题是如何从 videoPreviewLayer 获取二维码图像并将 testImageView 的图像设置为该图像。
您可以在需要时添加 AVCapturePhotoOutput 和 capturePhoto。
在 ScannerViewController 添加两个属性:
private let photoOutput = AVCapturePhotoOutput()
private var isCapturing = false
在 viewDidLoad 处向 captureSession 添加新输出:
captureSession.addOutput(photoOutput)
在 metadataOutput 方法中调用 capturePhoto 并记住捕获状态。因为 metadataOutput 方法可以被非常频繁地调用:
let photoSettings = AVCapturePhotoSettings()
if !isCapturing {
isCapturing = true
photoOutput.capturePhoto(with: photoSettings, delegate: self)
}
实现 AVCapturePhotoCaptureDelegate 协议:
extension ScannerViewController: AVCapturePhotoCaptureDelegate {
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
isCapturing = false
guard let imageData = photo.fileDataRepresentation() else {
print("Error while generating image from photo capture data.");
return
}
guard let qrImage = UIImage(data: imageData) else {
print("Unable to generate UIImage from image data.");
return
}
testImageView.image = qrImage
}
}
如果需要,进行一些额外的照片设置和错误处理也是个好主意。
我正在 Xcode 中使用 swift 开发二维码 reader 应用程序。我用以下代码扫描了二维码:
import UIKit
import AVFoundation
class ScannerViewController: UIViewController {
var captureSession = AVCaptureSession()
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
var qrCodeFrameView: UIView?
var scannerMetadataObj : AVMetadataMachineReadableCodeObject?
@IBOutlet weak var testImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back)
guard let captureDevice = deviceDiscoverySession.devices.first else {
print("Failed to get the camera device")
return
}
do {
let input = try AVCaptureDeviceInput(device: captureDevice)
captureSession.addInput(input)
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession.addOutput(captureMetadataOutput)
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
captureMetadataOutput.metadataObjectTypes = supportedCodeTypes
} catch {
return
}
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer!)
qrCodeFrameView = UIView()
if let qrCodeFrameView = qrCodeFrameView {
qrCodeFrameView.layer.borderColor = UIColor.green.cgColor
qrCodeFrameView.layer.borderWidth = 2
view.addSubview(qrCodeFrameView)
view.bringSubviewToFront(qrCodeFrameView)
}
}
override func viewWillAppear(_ animated: Bool) {
captureSession.startRunning()
}
override func viewWillDisappear(_ animated: Bool) {
captureSession.stopRunning()
qrCodeFrameView?.frame = CGRect.zero
}
}
extension ScannerViewController: AVCaptureMetadataOutputObjectsDelegate {
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
// Check if the metadataObjects array is not nil and it contains at least one object.
if metadataObjects.count == 0 {
qrCodeFrameView?.frame = CGRect.zero
return
}
// Get the metadata object.
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
scannerMetadataObj = metadataObj
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
qrCodeFrameView?.frame = barCodeObject!.bounds
self.testImageView.image = // set image with qr-code
}
}
扫描二维码后,我想获取二维码的图片,将testImageView的图片设置为获取的图片。怎么可能?我这样做是因为我想将该图像保存在数据库中以备将来使用。在这里我唯一的问题是如何从 videoPreviewLayer 获取二维码图像并将 testImageView 的图像设置为该图像。
您可以在需要时添加 AVCapturePhotoOutput 和 capturePhoto。
在 ScannerViewController 添加两个属性:
private let photoOutput = AVCapturePhotoOutput() private var isCapturing = false
在 viewDidLoad 处向 captureSession 添加新输出:
captureSession.addOutput(photoOutput)
在 metadataOutput 方法中调用 capturePhoto 并记住捕获状态。因为 metadataOutput 方法可以被非常频繁地调用:
let photoSettings = AVCapturePhotoSettings() if !isCapturing { isCapturing = true photoOutput.capturePhoto(with: photoSettings, delegate: self) }
实现 AVCapturePhotoCaptureDelegate 协议:
extension ScannerViewController: AVCapturePhotoCaptureDelegate { func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { isCapturing = false guard let imageData = photo.fileDataRepresentation() else { print("Error while generating image from photo capture data."); return } guard let qrImage = UIImage(data: imageData) else { print("Unable to generate UIImage from image data."); return } testImageView.image = qrImage } }
如果需要,进行一些额外的照片设置和错误处理也是个好主意。