AVFoundation - CIFilter

  • 扫码
import UIKit
import AVFoundation
let kScreenWidth:CGFloat = UIScreen.main.bounds.width
let kScreenHeight:CGFloat = UIScreen.main.bounds.height


class ViewController: UIViewController {


    @IBOutlet weak var scanHeightConst: NSLayoutConstraint!
    @IBOutlet weak var scanTopConst: NSLayoutConstraint!
    @IBOutlet weak var resultLabel: UIButton!
    /// 专门用于保存描边的图层
    private lazy var containerLayer: CALayer = CALayer()
    private lazy var session: AVCaptureSession = {
       let session = AVCaptureSession()
        return session
    }()
    private lazy var previewLayer: AVCaptureVideoPreviewLayer = {
        let previewLayer = AVCaptureVideoPreviewLayer(session: session)
        previewLayer.frame = view.bounds
        return previewLayer
    }()
    override func viewDidLoad() {
        super.viewDidLoad()
     
        scan()
     
    }
    override func viewDidAppear(_ animated: Bool){
        super.viewWillAppear(animated)
        /**
         whose view is not in the window hierarchy!
         */
        cammerRoot()
        scanAnimation()
    }

    private func scanAnimation(){
        
        scanTopConst.constant = -scanHeightConst.constant
        view.layoutIfNeeded()

        UIView.animate(withDuration: 2.0) {
            UIView.setAnimationRepeatCount(MAXFLOAT)
            self.scanTopConst.constant = self.scanHeightConst.constant
//            self.scanImageView.layer.masksToBounds = true
            self.view.layoutIfNeeded()
        }
    }
    //扫描
    private func scan(){
        
        guard let device = AVCaptureDevice.default(for: AVMediaType.video) else{
            print("设备失败")
            return
        }
        guard let input = try? AVCaptureDeviceInput(device: device) else{
            print("输入设备失败")
            return
        }
        let output = AVCaptureMetadataOutput()
        if !session.canAddInput(input) {
            return
        }
        if !session.canAddOutput(output) {
            return
        }
        // 3.添加输入和输出到会话中(老是忘记就会导致界面啥都没有)
        session.addInput(input)
        session.addOutput(output)
        
        output.metadataObjectTypes = output.availableMetadataObjectTypes
        output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        //设置可扫描区域
        let redView = UIView(frame: CGRect(x: 0, y: 0, width: 240, height: 240))
        redView.center = view.center
        print(redView.frame)//(40.0, 164.0, 240.0, 240.0)
        redView.layer.borderWidth = 2
        redView.layer.borderColor = UIColor.red.cgColor
        view.addSubview(redView)
        output.rectOfInterest = CGRect(x:redView.frame.origin.y/kScreenHeight , y: (kScreenWidth - redView.frame.origin.x - 240)/kScreenWidth, width: 240/kScreenHeight, height: 240/kScreenWidth)
        print(output.rectOfInterest) //(0.0704225352112676, 0.125, 0.422535211267606, 0.75)
        view.layer.insertSublayer(previewLayer, at: 0)
        session.startRunning()
        
    }
    //权限访问
    private func cammerRoot(){
        let mediaType = AVMediaType.video
        let authStatus = AVCaptureDevice.authorizationStatus(for: mediaType)
        if authStatus == AVAuthorizationStatus.restricted || authStatus == AVAuthorizationStatus.denied || authStatus == AVAuthorizationStatus.notDetermined {
            
            let alertViewController = UIAlertController(title: "权限", message: "请在iPhone的“设置”-“隐私”-“相机”功能中,找到“项目名称”打开相机访问权限", preferredStyle: .alert)
            let cancelAction = UIAlertAction(title: "取消", style: .cancel, handler: { (alerAction: UIAlertAction) in
                
            })
            let sureAction = UIAlertAction(title: "设置", style: .destructive, handler: { (sureAction: UIAlertAction) in
                
                guard let url = URL.init(string: "prefs:root=Privacy&path=CAMERA") else{
                    print("url为空")
                    return
                }
                if #available(iOS 10.0, *) {
                    
                    if UIApplication.shared.canOpenURL(url){
                        
                        UIApplication.shared.open(url, options: [:], completionHandler: nil)
                    }
                } else {
                    // Fallback on earlier versions
                    
                    if UIApplication.shared.canOpenURL(url){
                        UIApplication.shared.canOpenURL(url)
                    }
                }
            })
            alertViewController.addAction(cancelAction)
            alertViewController.addAction(sureAction)
            present(alertViewController, animated: true, completion: nil)
        }else{
            print("有权限")
        }
        
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

extension ViewController: AVCaptureMetadataOutputObjectsDelegate{
    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        if metadataObjects.count > 0 {
            session.stopRunning()
        }
        let lastObjc:AVMetadataMachineReadableCodeObject = metadataObjects.last as! AVMetadataMachineReadableCodeObject
        let finalResult = lastObjc.stringValue
        //显示结果
        resultLabel.setTitle(finalResult, for: .normal)
        
        // 通过预览图层将corners值转换为我们能识别的类型
        let metaObj = previewLayer.transformedMetadataObject(for: metadataObjects.last!)
    }
}
AVFoundation - CIFilter_第1张图片
result.png
AVFoundation - CIFilter_第2张图片
坐标转换.png
  • 条码生成
- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIImage * img = [self qrCodeImageWithInfo:@"http:www.baidu.com" width:150];
    UIImageView * imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 150, 35)];
    imgView.center = self.view.center;
    imgView.image = img;
    [self.view addSubview:imgView];
    
  
}
- (UIImage *)qrCodeImageWithInfo:(NSString *)info  width:(CGFloat)width
{
    if (!info) {
        return nil;
    }
    
    NSData *strData = [info dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO];
    //创建二维码滤镜
    CIFilter *qrFilter = [CIFilter filterWithName:@"CICode128BarcodeGenerator"];
    [qrFilter setValue:strData forKey:@"inputMessage"];
    CIImage *qrImage = qrFilter.outputImage;
    //颜色滤镜
    CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"];
    [colorFilter setDefaults];
    [colorFilter setValue:qrImage forKey:kCIInputImageKey];
    [colorFilter setValue:[CIColor colorWithRed:0 green:0 blue:0] forKey:@"inputColor0"];
    CIImage *colorImage = colorFilter.outputImage;
    //返回二维码
//    CGFloat scale = width/31;
//    UIImage *codeImage = [UIImage imageWithCIImage:[colorImage imageByApplyingTransform:CGAffineTransformMakeScale(scale, scale)]];
    
//    UIImage *codeImage = [UIImage imageWithCIImage:colorImage];//返回普通条形码
    UIImage *codeImage = [self getErWeiMaImageFormCIImage:colorImage withSize:150];//高清条码
    return codeImage;
}
- (UIImage *)getErWeiMaImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
    
    // 1.创建bitmap;
    size_t width = CGRectGetWidth(extent) * scale;
    size_t height = CGRectGetHeight(extent) * scale;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    
    // 2.保存bitmap到图片
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    return [UIImage imageWithCGImage:scaledImage];
}
  • 二维码生成
- (void)viewDidLoad {
    [super viewDidLoad];
    
    CIImage * CIImg = [self createQRForString:@"http:www.baidu.com"];
    UIImage * img = [self createNonInterpolatedUIImageFormCIImage:CIImg withSize:150];
    UIImageView * imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 150, 150)];
    imgView.center = self.view.center;
    imgView.image = img;
    [self.view addSubview:imgView];
    
}
- (CIImage *)createQRForString:(NSString *)qrString {
    NSData *stringData = [qrString dataUsingEncoding:NSUTF8StringEncoding];
    // 创建filter
    CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    // 设置内容
    [qrFilter setValue:stringData forKey:@"inputMessage"];
    [qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];//纠错级别
    // 返回CIImage
    return qrFilter.outputImage;
}
- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
    // 1.创建bitmap;
    size_t width = CGRectGetWidth(extent) * scale;
    size_t height = CGRectGetHeight(extent) * scale;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    // 2.保存bitmap到图片
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    //原图
    UIImage *outputImage = [UIImage imageWithCGImage:scaledImage];
    UIGraphicsBeginImageContextWithOptions(outputImage.size, NO, [[UIScreen mainScreen] scale]);
    [outputImage drawInRect:CGRectMake(0,0 , size, size)];
    //水印图
    UIImage *waterimage = [UIImage imageNamed:@"缴费信息"];
    UIImageView * imageView = [[UIImageView alloc] initWithImage:waterimage];
    [waterimage drawInRect:CGRectMake((size- imageView.bounds.size.width)/2.0, (size-imageView.bounds.size.width)/2.0, imageView.bounds.size.width, imageView.bounds.size.height)];
    UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newPic;
}
AVFoundation - CIFilter_第3张图片
Simulator Screen Shot - iPhone 8 Plus - 2018-03-14 at 15.33.18.png

你可能感兴趣的:(AVFoundation - CIFilter)