diff --git a/Source/LBXScanView.swift b/Source/LBXScanView.swift index abaf0f1..ee32141 100755 --- a/Source/LBXScanView.swift +++ b/Source/LBXScanView.swift @@ -181,7 +181,7 @@ open class LBXScanView: UIView { // 执行绘画 context.strokePath() - if viewStyle.isNeedShowRetangle { + if viewStyle.isNeedShowRetangle && viewStyle.scanBgImage == nil { // 中间画矩形(正方形) context.setStrokeColor(viewStyle.colorRetangleLine.cgColor) context.setLineWidth(viewStyle.widthRetangleLine) @@ -196,72 +196,79 @@ open class LBXScanView: UIView { scanRetangleRect = CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height) - // 画矩形框4格外围相框角 - - // 相框角的宽度和高度 - let wAngle = viewStyle.photoframeAngleW - let hAngle = viewStyle.photoframeAngleH - - // 4个角的 线的宽度 - let linewidthAngle = viewStyle.photoframeLineW // 经验参数:6和4 - - // 画扫码矩形以及周边半透明黑色坐标参数 - var diffAngle = linewidthAngle / 3 - diffAngle = linewidthAngle / 2 // 框外面4个角,与框有缝隙 - diffAngle = linewidthAngle / 2 // 框4个角 在线上加4个角效果 - diffAngle = 0 // 与矩形框重合 - - switch viewStyle.photoframeAngleStyle { - case .Outer: diffAngle = linewidthAngle / 3 // 框外面4个角,与框紧密联系在一起 - case .On: diffAngle = 0 - case .Inner: diffAngle = -viewStyle.photoframeLineW / 2 + if let bgImage = viewStyle.scanBgImage { + let imgV = UIImageView.init(image: bgImage) + let scanFrame = getScanRectForAnimation() + imgV.frame = CGRect(x: scanFrame.origin.x - 5, y: scanFrame.origin.y - 5, width: scanFrame.size.width + 10, height: scanFrame.size.height + 10) + self.addSubview(imgV) + } else { + // 画矩形框4格外围相框角 + + // 相框角的宽度和高度 + let wAngle = viewStyle.photoframeAngleW + let hAngle = viewStyle.photoframeAngleH + + // 4个角的 线的宽度 + let linewidthAngle = viewStyle.photoframeLineW // 经验参数:6和4 + + // 画扫码矩形以及周边半透明黑色坐标参数 + var diffAngle = linewidthAngle / 3 + diffAngle = linewidthAngle / 2 // 框外面4个角,与框有缝隙 + diffAngle = linewidthAngle / 2 // 框4个角 在线上加4个角效果 + diffAngle = 0 // 与矩形框重合 + + switch viewStyle.photoframeAngleStyle { + case .Outer: diffAngle = linewidthAngle / 3 // 框外面4个角,与框紧密联系在一起 + case .On: diffAngle = 0 + case .Inner: diffAngle = -viewStyle.photoframeLineW / 2 + } + + context.setStrokeColor(viewStyle.colorAngle.cgColor) + context.setFillColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) + + // Draw them with a 2.0 stroke width so they are a bit more visible. + context.setLineWidth(linewidthAngle) + + + // + let leftX = XRetangleLeft - diffAngle + let topY = YMinRetangle - diffAngle + let rightX = XRetangleRight + diffAngle + let bottomY = YMaxRetangle + diffAngle + + // 左上角水平线 + context.move(to: CGPoint(x: leftX - linewidthAngle / 2, y: topY)) + context.addLine(to: CGPoint(x: leftX + wAngle, y: topY)) + + // 左上角垂直线 + context.move(to: CGPoint(x: leftX, y: topY - linewidthAngle / 2)) + context.addLine(to: CGPoint(x: leftX, y: topY + hAngle)) + + // 左下角水平线 + context.move(to: CGPoint(x: leftX - linewidthAngle / 2, y: bottomY)) + context.addLine(to: CGPoint(x: leftX + wAngle, y: bottomY)) + + // 左下角垂直线 + context.move(to: CGPoint(x: leftX, y: bottomY + linewidthAngle / 2)) + context.addLine(to: CGPoint(x: leftX, y: bottomY - hAngle)) + + // 右上角水平线 + context.move(to: CGPoint(x: rightX + linewidthAngle / 2, y: topY)) + context.addLine(to: CGPoint(x: rightX - wAngle, y: topY)) + + // 右上角垂直线 + context.move(to: CGPoint(x: rightX, y: topY - linewidthAngle / 2)) + context.addLine(to: CGPoint(x: rightX, y: topY + hAngle)) + + // 右下角水平线 + context.move(to: CGPoint(x: rightX + linewidthAngle / 2, y: bottomY)) + context.addLine(to: CGPoint(x: rightX - wAngle, y: bottomY)) + + // 右下角垂直线 + context.move(to: CGPoint(x: rightX, y: bottomY + linewidthAngle / 2)) + context.addLine(to: CGPoint(x: rightX, y: bottomY - hAngle)) } - context.setStrokeColor(viewStyle.colorAngle.cgColor) - context.setFillColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) - - // Draw them with a 2.0 stroke width so they are a bit more visible. - context.setLineWidth(linewidthAngle) - - - // - let leftX = XRetangleLeft - diffAngle - let topY = YMinRetangle - diffAngle - let rightX = XRetangleRight + diffAngle - let bottomY = YMaxRetangle + diffAngle - - // 左上角水平线 - context.move(to: CGPoint(x: leftX - linewidthAngle / 2, y: topY)) - context.addLine(to: CGPoint(x: leftX + wAngle, y: topY)) - - // 左上角垂直线 - context.move(to: CGPoint(x: leftX, y: topY - linewidthAngle / 2)) - context.addLine(to: CGPoint(x: leftX, y: topY + hAngle)) - - // 左下角水平线 - context.move(to: CGPoint(x: leftX - linewidthAngle / 2, y: bottomY)) - context.addLine(to: CGPoint(x: leftX + wAngle, y: bottomY)) - - // 左下角垂直线 - context.move(to: CGPoint(x: leftX, y: bottomY + linewidthAngle / 2)) - context.addLine(to: CGPoint(x: leftX, y: bottomY - hAngle)) - - // 右上角水平线 - context.move(to: CGPoint(x: rightX + linewidthAngle / 2, y: topY)) - context.addLine(to: CGPoint(x: rightX - wAngle, y: topY)) - - // 右上角垂直线 - context.move(to: CGPoint(x: rightX, y: topY - linewidthAngle / 2)) - context.addLine(to: CGPoint(x: rightX, y: topY + hAngle)) - - // 右下角水平线 - context.move(to: CGPoint(x: rightX + linewidthAngle / 2, y: bottomY)) - context.addLine(to: CGPoint(x: rightX - wAngle, y: bottomY)) - - // 右下角垂直线 - context.move(to: CGPoint(x: rightX, y: bottomY + linewidthAngle / 2)) - context.addLine(to: CGPoint(x: rightX, y: bottomY - hAngle)) - context.strokePath() } diff --git a/Source/LBXScanViewController.swift b/Source/LBXScanViewController.swift index e0375de..8578811 100755 --- a/Source/LBXScanViewController.swift +++ b/Source/LBXScanViewController.swift @@ -46,6 +46,9 @@ open class LBXScanViewController: UIViewController { // 相机启动提示文字 public var readyString: String! = "loading" + /// 没有从图片中识别到二维码 + public var scanImageFailure: (() -> Void)? + open override func viewDidLoad() { super.viewDidLoad() @@ -84,21 +87,18 @@ open class LBXScanViewController: UIViewController { AVMetadataObject.ObjectType.ean13 as NSString, AVMetadataObject.ObjectType.code128 as NSString] as [AVMetadataObject.ObjectType] } - - scanObj = LBXScanWrapper(videoPreView: view, - objType: arrayCodeType!, - isCaptureImg: isNeedCodeImage, - cropRect: cropRect, - success: { [weak self] (arrayResult) -> Void in - guard let strongSelf = self else { - return - } - if !strongSelf.isSupportContinuous { - // 停止扫描动画 - strongSelf.qRScanView?.stopScanAnimation() - } - strongSelf.handleCodeResult(arrayResult: arrayResult) - }) + + scanObj = LBXScanWrapper(videoPreView: view, objType: arrayCodeType!, isCaptureImg: isNeedCodeImage, cropRect: cropRect, success: { [weak self] (arrayResult) -> Void in + guard let strongSelf = self else { return } + if !strongSelf.isSupportContinuous { + // 停止扫描动画 + strongSelf.qRScanView?.stopScanAnimation() + } + strongSelf.handleCodeResult(arrayResult: arrayResult) + }, ambientLightValueClosure: { [weak self] value in + guard let strongSelf = self else { return } + strongSelf.ambientLightValueDidChange(value: value) + }) } scanObj?.supportContinuous = isSupportContinuous; @@ -144,6 +144,8 @@ open class LBXScanViewController: UIViewController { } } + open func ambientLightValueDidChange(value: Double) {} + open override func viewWillDisappear(_ animated: Bool) { NSObject.cancelPreviousPerformRequests(withTarget: self) qRScanView?.stopScanAnimation() @@ -177,6 +179,8 @@ extension LBXScanViewController: UIImagePickerControllerDelegate, UINavigationCo let arrayResult = LBXScanWrapper.recognizeQRImage(image: image) if !arrayResult.isEmpty { handleCodeResult(arrayResult: arrayResult) + } else { + scanImageFailure?() } } diff --git a/Source/LBXScanViewStyle.swift b/Source/LBXScanViewStyle.swift index 0218ac6..18fd214 100644 --- a/Source/LBXScanViewStyle.swift +++ b/Source/LBXScanViewStyle.swift @@ -68,6 +68,9 @@ public struct LBXScanViewStyle { /// 动画效果的图像,如线条或网格的图像 public var animationImage: UIImage? + + /// 扫码区域的背景图片 + public var scanBgImage: UIImage? //MARK: - 非识别区域颜色, 默认 RGBA (0,0,0,0.5),范围(0--1) diff --git a/Source/LBXScanWrapper.swift b/Source/LBXScanWrapper.swift index 126441c..5ee8905 100755 --- a/Source/LBXScanWrapper.swift +++ b/Source/LBXScanWrapper.swift @@ -33,11 +33,12 @@ public struct LBXScanResult { -open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate { +open class LBXScanWrapper: NSObject, AVCaptureMetadataOutputObjectsDelegate, AVCaptureVideoDataOutputSampleBufferDelegate { let device = AVCaptureDevice.default(for: AVMediaType.video) var input: AVCaptureDeviceInput? var output: AVCaptureMetadataOutput + var videoDataOutput: AVCaptureVideoDataOutput let session = AVCaptureSession() var previewLayer: AVCaptureVideoPreviewLayer? @@ -58,6 +59,8 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate { //连续扫码 var supportContinuous = false + /// 自动开启闪光灯后回调 + var ambientLightValueClosure: ((Double) -> Void)? /** 初始化设备 @@ -72,10 +75,13 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate { objType: [AVMetadataObject.ObjectType] = [(AVMetadataObject.ObjectType.qr as NSString) as AVMetadataObject.ObjectType], isCaptureImg: Bool, cropRect: CGRect = .zero, - success: @escaping (([LBXScanResult]) -> Void)) { + success: @escaping (([LBXScanResult]) -> Void), + ambientLightValueClosure: ((Double) -> Void)? = nil) { + self.ambientLightValueClosure = ambientLightValueClosure successBlock = success output = AVCaptureMetadataOutput() + videoDataOutput = AVCaptureVideoDataOutput() isNeedCaptureImage = isCaptureImg stillImageOutput = AVCaptureStillImageOutput() @@ -104,6 +110,11 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate { if session.canAddOutput(stillImageOutput) { session.addOutput(stillImageOutput) } + + if session.canAddOutput(videoDataOutput) { + session.addOutput(videoDataOutput) + videoDataOutput.setSampleBufferDelegate(self, queue: DispatchQueue.main) + } stillImageOutput.outputSettings = [AVVideoCodecJPEG: AVVideoCodecKey] @@ -147,6 +158,19 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate { captureOutput(output, didOutputMetadataObjects: metadataObjects, from: connection) } + public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { + + if let metadata = CMCopyDictionaryOfAttachments(allocator: nil, target: sampleBuffer, attachmentMode: kCMAttachmentMode_ShouldPropagate) as? [String: Any] { + let exifKey = kCGImagePropertyExifDictionary as String + if let exifMetadata = metadata[exifKey] as? [String: Any] { + let brightlessKey = kCGImagePropertyExifBrightnessValue as String + if let brightlessVal: Double = exifMetadata[brightlessKey] as? Double { + ambientLightValueClosure?(brightlessVal) + } + } + } + } + func start() { if !session.isRunning { isNeedScanResult = true diff --git a/swiftScan.xcodeproj/project.pbxproj b/swiftScan.xcodeproj/project.pbxproj index e1e6e4f..3de4755 100755 --- a/swiftScan.xcodeproj/project.pbxproj +++ b/swiftScan.xcodeproj/project.pbxproj @@ -177,7 +177,7 @@ TargetAttributes = { 7D42B9AB1C05EE9A0084D045 = { CreatedOnToolsVersion = 7.1; - DevelopmentTeam = 8LQ7CL73D8; + DevelopmentTeam = 9HV4B937SU; LastSwiftMigration = 0820; ProvisioningStyle = Automatic; }; @@ -378,11 +378,11 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 8LQ7CL73D8; + DEVELOPMENT_TEAM = 9HV4B937SU; INFOPLIST_FILE = swiftScan/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.lbx.hk2019235; + PRODUCT_BUNDLE_IDENTIFIER = com.zhouss.scan; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "5afb03a3-32bd-412b-9db2-5fa2d3271415"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/swiftScan/Assets.xcassets/AppIcon.appiconset/Contents.json b/swiftScan/Assets.xcassets/AppIcon.appiconset/Contents.json index 118c98f..8121323 100644 --- a/swiftScan/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/swiftScan/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -2,37 +2,52 @@ "images" : [ { "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" + "scale" : "2x", + "size" : "20x20" }, { "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" + "scale" : "3x", + "size" : "20x20" }, { "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" + "scale" : "2x", + "size" : "29x29" }, { "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" + "scale" : "3x", + "size" : "29x29" }, { "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" + "scale" : "2x", + "size" : "40x40" }, { "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/swiftScan/Assets.xcassets/Contents.json b/swiftScan/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/swiftScan/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/swiftScan/Assets.xcassets/scan_border.imageset/Contents.json b/swiftScan/Assets.xcassets/scan_border.imageset/Contents.json new file mode 100644 index 0000000..5396847 --- /dev/null +++ b/swiftScan/Assets.xcassets/scan_border.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "scan_border@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "scan_border@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/swiftScan/Assets.xcassets/scan_border.imageset/scan_border@2x.png b/swiftScan/Assets.xcassets/scan_border.imageset/scan_border@2x.png new file mode 100644 index 0000000..ea3a166 Binary files /dev/null and b/swiftScan/Assets.xcassets/scan_border.imageset/scan_border@2x.png differ diff --git a/swiftScan/Assets.xcassets/scan_border.imageset/scan_border@3x.png b/swiftScan/Assets.xcassets/scan_border.imageset/scan_border@3x.png new file mode 100644 index 0000000..c8e1afa Binary files /dev/null and b/swiftScan/Assets.xcassets/scan_border.imageset/scan_border@3x.png differ diff --git a/swiftScan/QQScanViewController.swift b/swiftScan/QQScanViewController.swift index 777c363..d11d4ab 100644 --- a/swiftScan/QQScanViewController.swift +++ b/swiftScan/QQScanViewController.swift @@ -42,6 +42,7 @@ class QQScanViewController: LBXScanViewController { //框向上移动10个像素 scanStyle?.centerUpOffset += 10 + scanStyle?.scanBgImage = UIImage.init(named: "scan_border") // Do any additional setup after loading the view. } @@ -67,6 +68,14 @@ class QQScanViewController: LBXScanViewController { vc.codeResult = result navigationController?.pushViewController(vc, animated: true) } + + override func ambientLightValueDidChange(value: Double) { + if value < 0 { + scanObj?.setTorch(torch: true) + isOpenedFlash = true + btnFlash.setImage(UIImage(named: "CodeScan.bundle/qrcode_scan_btn_flash_down"), for:UIControl.State.normal) + } + } func drawBottomItems() { if (bottomItemsView != nil) {