iOS在Cameraview和捕获的图像上添加水印或叠加

问题描述

我正在尝试使用带有Swift 5的iOS 13.6在摄像机视图和捕获的图像上方添加水印。这是我的代码:

import UIKit
import AVFoundation
import Foundation

class ViewController: UIViewController,AVCapturePhotoCaptureDelegate {

    @IBOutlet weak var navigationBar: UINavigationBar!
    @IBOutlet weak var shapeLayer: UIView!
    @IBOutlet weak var imgOverlay: UIImageView!
    
    var captureSession = AVCaptureSession()
    let stillImageOutput = AVCapturePhotoOutput()
    var previewLayer : AVCaptureVideoPreviewLayer?

    var captureDevice : AVCaptureDevice?
    var backCamera = AVCaptureDevice.default(.builtInWideAngleCamera,for: .video,position: .back)
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        captureSession.sessionPreset = AVCaptureSession.Preset.high
        
        if #available(iOS 13.6,*){
            let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera,position: .back)
            do {
                let input = try AVCaptureDeviceInput(device: captureDevice!)
                captureSession = AVCaptureSession()
                captureSession.addInput(input)
                previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
                previewLayer?.frame = view.layer.bounds
                shapeLayer.layer.addSublayer(previewLayer!)
                captureSession.startRunning()
            } catch {
                print("error")
            }
        }
        
        if let devices = AVCaptureDevice.devices() as? [AVCaptureDevice] {
            // Loop through all the capture devices on this phone
            for device in devices {
                // Make sure this particular device supports video
                if (device.hasMediaType(AVMediaType.video)) {
                    // Finally check the position and confirm we've got the back camera
                    if(device.position == AVCaptureDevice.Position.back) {
                        captureDevice = device
                        if captureDevice != nil {
                            print("Capture device found")
                            beginSession()
                        }
                    }
                }
            }
        }
    }
    
    func beginSession() {

        
        do {
            try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice!))
            stillImageOutput.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]

            if captureSession.canAddOutput(stillImageOutput) {
                captureSession.addOutput(stillImageOutput)
            }

        }
        catch {
            print("error: \(error.localizedDescription)")
        }
 
        
        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)

        
        // this is what displays the camera view. But - it's on TOP of the drawn view,and under the overview. ??
        self.view.layer.addSublayer(previewLayer)
        previewLayer.frame = self.view.layer.frame


        imgOverlay.frame = self.view.frame
        imgOverlay.image = self.drawCirclesOnImage(fromImage: nil,targetSize: imgOverlay.bounds.size)

        self.view.bringSubviewToFront(navigationBar)
        self.view.bringSubviewToFront(imgOverlay)
        //self.view.bringSubview(toFront: btnCapture)
        // don't use shapeLayer anymore...
        //      self.view.bringSubview(toFront: shapeLayer)


        captureSession.startRunning()
        print("Capture session running")

    }

    func getImageWithColor(color: UIColor,size: CGSize) -> UIImage {
        let rect = CGRect(origin: CGPoint(x: 0,y: 0),size: CGSize(width: size.width,height: size.height))
        UIGraphicsBeginImageContextWithOptions(size,false,0)
        color.setFill()
        UIRectFill(rect)
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }

    func drawCirclesOnImage(fromImage: UIImage? = nil,targetSize: CGSize? = CGSize.zero) -> UIImage? {

        if fromImage == nil && targetSize == CGSize.zero {
            return nil
        }

        var tmpimg: UIImage?

        if targetSize == CGSize.zero {

            tmpimg = fromImage

        } else {

            tmpimg = getImageWithColor(color: UIColor.clear,size: targetSize!)

        }

        guard let img = tmpimg else {
            return nil
        }

        let imageSize = img.size
        let scale: CGFloat = 0
        UIGraphicsBeginImageContextWithOptions(imageSize,scale)

        img.draw(at: CGPoint.zero)

        let w = imageSize.width

        let midX = imageSize.width / 2
        let midY = imageSize.height / 2

        // red circles - radius in %
        let circleRads = [ 0.07,0.13,0.17,0.22,0.29,0.36,0.40,0.48,0.60,0.75 ]

        // center "dot" - radius is 1.5%
        var circlePath = UIBezierPath(arcCenter: CGPoint(x: midX,y: midY),radius: CGFloat(w * 0.015),startAngle: CGFloat(0),endAngle:CGFloat(M_PI * 2),clockwise: true)

        UIColor.red.setFill()
        circlePath.stroke()
        circlePath.fill()

        // blue circle is between first and second red circles
        circlePath = UIBezierPath(arcCenter: CGPoint(x: midX,radius: w * CGFloat((circleRads[0] + circleRads[1]) / 2.0),clockwise: true)

        UIColor.blue.setStroke()
        circlePath.lineWidth = 2.5
        circlePath.stroke()

        UIColor.red.setStroke()

        for pct in circleRads {

            let rad = w * CGFloat(pct)

            circlePath = UIBezierPath(arcCenter: CGPoint(x: midX,radius: CGFloat(rad),clockwise: true)

            circlePath.lineWidth = 2.5
            circlePath.stroke()

        }

        let newImage = UIGraphicsGetImageFromCurrentImageContext()

        UIGraphicsEndImageContext()

        return newImage
    }
    
    
    func saveToCamera() {
        
        if let videoConnection = stillImageOutput.connection(with: AVMediaType.video) {
            
              stillImageOutput.captureStillImageAsynchronously(from: videoConnection,completionHandler: { (CMSampleBuffer,Error) in

                if let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(CMSampleBuffer) {
                    if let cameraImage = UIImage(data: imageData) {
                        // cameraImage is the camera preview image.

                        // I need to combine/merge it with the myImage that is actually the blue circles.

                        // This converts the UIView of the bllue circles to an image. Uses 'extension' at top of code.
                        let myImage = UIImage(view: self.shapeLayer)
                        print("converting myImage to an image")

                        let newImage = self.composite(image:cameraImage,overlay:(myImage),scaleOverlay:true)
                       UIImageWriteToSavedPhotosAlbum(newImage!,nil,nil)

                    }
                }
            })
        }
    }



    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
   
}

上面给出的示例中的某些代码与Swift 3兼容,但是我无法像下面给出的代码那样将其转换:

do {
            try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice!))
            stillImageOutput.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]

            if captureSession.canAddOutput(stillImageOutput) {
                captureSession.addOutput(stillImageOutput)
            }

        }
        catch {
            print("error: \(error.localizedDescription)")
        }

此方法也与Swift 3兼容,但能够在Swift 5上进行转换:

func saveToCamera() {
        
        if let videoConnection = stillImageOutput.connection(with: AVMediaType.video) {
            
              stillImageOutput.captureStillImageAsynchronously(from: videoConnection,nil)

                    }
                }
            })
        }
    }

因此,基本上我想在cameraview上添加图像或形状,然后在该捕获的图像上添加水印。我也无法在互联网上找到任何可以在cameraview上添加水印/叠加图像并将其另存为捕获图像的示例。如果有人可以分享与Swift 4/5兼容的示例,这将很有帮助。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...