使用UIView水平裁剪图像

时间:2018-08-27 11:03:18

标签: ios swift camera swift4 crop

我想在自定义相机中捕获图像后裁剪图像,对于裁剪图像,我正在使用本教程Tutorial for crop image

在我的项目中,我没有使用scrollView,而是使用View(并且将其用作AVVideoCapturePreviewLayer)

这是情节提要的图像 enter image description here

AVVideoCapturePreviewLayer的预览视图

用于在捕获图像后放置图像的预览图像(与“预览视图”相同)

用于在预览图像(长宽比为16 :: 9)中裁剪图像的静态图片,并将CropAreaView放在自定义类“静态图片”中

这是裁剪的代码

var cropArea:CGRect {

    get {

        let factor = previewImage.image!.size.width/view.frame.width
        let imageFrame = previewImage.imageFrame()

        let x = (previewView.frame.origin.x + stillPicture.frame.origin.x - imageFrame.origin.x) * factor

        let y = (previewView.frame.origin.y + stillPicture.frame.origin.y - imageFrame.origin.y) * factor

        let width = stillPicture.frame.size.width  * factor
            let height = stillPicture.frame.size.height  * factor


        return CGRect(x: x, y: y, width: width, height: height)
    }
}



extension UIImageView {

        func imageFrame() -> CGRect {

            let imageViewSize = self.frame.size
            guard let imageSize = self.image?.size else {return CGRect.zero}
            let imageRatio = imageSize.width / imageSize.height
            let imageViewRatio = imageViewSize.width / imageViewSize.height



            if imageRatio < imageViewRatio {

                let scaleFactor = imageViewSize.height / imageSize.height
                let width = imageSize.width * scaleFactor
                let topleftX = (imageViewSize.width - width) * 0.5
                return CGRect (x: topleftX, y: 0, width: width, height: imageViewSize.height)

            } else {

                let scalFactor = imageViewSize.width / imageSize.width
                let height = imageSize.height * scalFactor
                let topleftY = (imageViewSize.height - height) * 0.5
                return CGRect (x: 0, y: topleftY, width: imageViewSize.width, height: height)
            }

        }
    }


    class CropAreaView: UIView {

        override func point (inside point: CGPoint, with event: UIEvent?) -> Bool {

            return false

        }
    }

这是用于捕获图像的

        let dataSementara : UIImage = UIImage (data: dataImage)!
        previewImage.image = dataSementara


        let croppedCGImage = previewImage.image?.cgImage?.cropping(to: cropArea)
        let croppedImage = UIImage(cgImage: croppedCGImage!)
        previewImage.image = croppedImage
        takenImage = previewImage.image

这是相机视图 enter image description here

这是捕获后的结果enter image description here

我已经更改了cropArea:CG Rect和func imageFrame()-> CGRect中的变量,但仍然没有运气(仍然水平裁剪)

这是完整的代码:

    class CustomCameraKTPViewController: UIViewController , AVCapturePhotoCaptureDelegate {

        @IBOutlet weak var stillPicture : CropAreaView!
        @IBOutlet weak var previewImage : UIImageView!
        @IBOutlet weak var previewView: PreviewViewKTP!


        var timer = Timer()
        var seconds = 30
        var delegate:sendDataToViewProtocol? = nil
        var takenImage : UIImage!
        var userDataPhotoCamera = userImage()
        var imageData1: NSData!
        var imageStr1: String!

        let captureSession = AVCaptureSession()
        var videoPreviewLayer: AVCaptureVideoPreviewLayer?
        let capturePhotoOutput = AVCapturePhotoOutput()
        let capturePhotoDelegate = CaptureKTPImage()


        var cropArea:CGRect {

            get {

                let factor = previewImage.image!.size.width/view.frame.width
                let imageFrame = previewImage.imageFrame()

                let x = (previewView.frame.origin.x + stillPicture.frame.origin.x - imageFrame.origin.x) * factor

                let y = (previewView.frame.origin.y + stillPicture.frame.origin.y - imageFrame.origin.y) * factor

                let width = stillPicture.frame.size.width  * factor
                    let height = stillPicture.frame.size.height  * factor


                return CGRect(x: x, y: y, width: width, height: height)
            }
        }

        override func viewDidLoad() {
            super.viewDidLoad()
            checkCameraUsagePermission()
            if takenImage != nil {

                timer.invalidate()
                dismiss (animated: true)
            }

            runTimer()
        }


        func initialiseCaptureSession() {

            let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)

            guard let input = try? AVCaptureDeviceInput(device: captureDevice!),
                captureSession.canAddInput(input)
                else { return }

            captureSession.addInput(input)
            self.previewView.videoPreviewLayer.session = self.captureSession
            self.previewView.videoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

            capturePhotoOutput.isHighResolutionCaptureEnabled = true
            captureSession.addOutput(capturePhotoOutput)

            captureSession.startRunning()
        }

        @IBAction func onTapTakePhoto(_ sender: UIButton) {

            timer.invalidate()

            let settings = AVCapturePhotoSettings()
            let previewPixelType = settings.availablePreviewPhotoPixelFormatTypes.first!
            let previewFormat = [kCVPixelBufferPixelFormatTypeKey as String: previewPixelType]
            settings.previewPhotoFormat = previewFormat
            capturePhotoOutput.capturePhoto(with: settings, delegate: self)


        }


        func photoOutput(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {

            if let error = error {

                print(error.localizedDescription)

            }

            // take the session output, get the buffer, and create an image from that buffer



            if let sampleBuffer = photoSampleBuffer, let previewBuffer = previewPhotoSampleBuffer, let dataImage = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: previewBuffer) {
                // gambar yg sudah diambil


                let dataSementara : UIImage = UIImage (data: dataImage)!
                previewImage.image = dataSementara


                let croppedCGImage = previewImage.image?.cgImage?.cropping(to: cropArea)
                let croppedImage = UIImage(cgImage: croppedCGImage!)
                previewImage.image = croppedImage
                takenImage = previewImage.image



                let expectedSizeInMb = 3
                let sizeInBytes = expectedSizeInMb * 1024 * 1024
                var needCompress:Bool = true
                var imgData:Data?
                var compressingValue:CGFloat = 1.0


                print ("\(takenImage)")

                if takenImage != nil {

                    while (needCompress && compressingValue > 0.0) {
                        if let data: Data = UIImageJPEGRepresentation(takenImage!, compressingValue) {

                            if data.count < sizeInBytes {

                                needCompress = false
                                imgData = data

                            } else {
                                compressingValue -= 0.01
                            }
                        }
                    }
                    if let data = imgData {

                        if (data.count < sizeInBytes) {

                            UIImage(data: data)
                            print ("\(data)")

                        }
                    }

                    userDataPhotoCamera.fotoID =  imgData?.base64EncodedString(options: Data.Base64EncodingOptions.lineLength64Characters)

                    if (delegate != nil) {
                        //Check textField is empty
                        if(userDataPhotoCamera.fotoID != "" || userDataPhotoCamera.fotoID != nil){
                            //set textField Data to protocol Function
                            delegate?.inputData(data: userDataPhotoCamera.fotoID!)


                            self.view.removeFromSuperview()

                        }
                    }
            } else {

                print("Error setting up photo capture")
                self.view.removeFromSuperview()
                }
            }
        }

        func checkCameraUsagePermission() {
            switch AVCaptureDevice.authorizationStatus(for: .video) {
            case .authorized:
                self.initialiseCaptureSession()

            case .notDetermined:
                AVCaptureDevice.requestAccess(for: .video) { granted in
                    if granted {
                        self.initialiseCaptureSession()
                    }
                }
            case .denied:
                return
            case .restricted:
                return
            }
        }

        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

            if (segue.identifier == "segueToPreviewKTP") {

                let destinationCamera = segue.destination as! PreviewKTPPhotoViewController
                destinationCamera.previewImage = takenImage
                destinationCamera.PreviewuserDataPhotoCamera.fotoID = userDataPhotoCamera.fotoID

                }
            }

    }


    extension CustomCameraKTPViewController {


         func runTimer() {

         timer = Timer.scheduledTimer(timeInterval: 1, target: self,   selector: (#selector(CustomCameraKTPViewController.updateTimer)), userInfo: nil, repeats: true)


         }

         @objc func updateTimer() {
         seconds -= 1     //This will decrement(count down)the seconds.
         print ("\(seconds)") //This will update the label.

         if seconds == 0 {

         //set ulang timer dan matikan
         timer.invalidate()

         let alertController = UIAlertController (title: "Error", message: "Camera otomatis mati setelah 30 detik", preferredStyle: .alert)
         let dismissAction = UIAlertAction (title: "Dismiss", style: .cancel, handler: nil)

         alertController.addAction(dismissAction)
         present (alertController, animated: true, completion: nil)
         self.view.removeFromSuperview()

         seconds = 30
         timer.invalidate()

            }
        }
    }


    extension UIImageView {

        func imageFrame() -> CGRect {

            let imageViewSize = self.frame.size
            guard let imageSize = self.image?.size else {return CGRect.zero}
            let imageRatio = imageSize.width / imageSize.height
            let imageViewRatio = imageViewSize.width / imageViewSize.height



            if imageRatio < imageViewRatio {

                let scaleFactor = imageViewSize.height / imageSize.height
                let width = imageSize.width * scaleFactor
                let topleftX = (imageViewSize.width - width) * 0.5
                return CGRect (x: topleftX, y: 0, width: width, height: imageViewSize.height)

            } else {

                let scalFactor = imageViewSize.width / imageSize.width
                let height = imageSize.height * scalFactor
                let topleftY = (imageViewSize.height - height) * 0.5
                return CGRect (x: 0, y: topleftY, width: imageViewSize.width, height: height)
                    }
        }
    }


    class CropAreaView: UIView {

        override func point (inside point: CGPoint, with event: UIEvent?) -> Bool {
        return false

        }
    }

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

通过更改var cropArea:CGRect中的返回CGRect来解决

来自

    return CGRect(x: x, y: y, width: width, height: height)

收件人

    return CGRect(x: y, y: x, width: width, height: height)