IOS自动抓图

Posted

技术标签:

【中文标题】IOS自动抓图【英文标题】:Capture picture automatically in IOS 【发布时间】:2013-10-21 21:31:18 【问题描述】:

我的要求是编写一个示例 ios 应用程序,该应用程序将自动捕获相机图片。使用提供的各种 S.O 链接,我确实实现了以下代码 -

我的 CameraViewController.h 类定义如下:

@interface CameraViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>

@property (strong, nonatomic) IBOutlet UIImageView *ImageView;

@end

CameraViewController.m 代码如下:

    -(void)viewDidAppear:(BOOL)animated

    NSLog(@"Setting the background now");

    UIImagePickerController *picker = [[UIImagePickerController alloc] init];picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;
    picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
    picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
    picker.showsCameraControls = NO;
    picker.navigationBarHidden = NO;
    picker.toolbarHidden = NO;
    [self presentViewController:picker animated:YES completion:NULL];

    NSLog(@"Taking the picture now");
   [picker takePicture];





-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info


    NSLog(@"Entered the case of finishing pictures");


- (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker

    NSLog(@"Entered the case of cancel");


上述代码的作用是成功启动相机应用程序,但是我不确定 takePicture API 是否能够成功单击图片。我在 Ipad 内的照片应用程序中没有看到任何保存的图片,所以我认为该图片没有被点击。 有人可以告诉我上面的代码是否正确,或者一旦显示相机控件,我需要做什么来自动单击捕获按钮的部分

【问题讨论】:

【参考方案1】:

[请转到 Apple 文档中的“使用 UIImagePickerController 选择图片并拍摄照片”,以获取类 UIImagePickerController 的属性 cameraOverlayView,以获取满足您需要的完整示例应用程序,以及更多内容。]

您将CameraViewController 指定为采用UIImagePickerControllerDelegate 协议,因此您必须实现两条消息:

- (void)   imagePickerController: (UIImagePickerController *) picker      
   didFinishPickingMediaWithInfo: (NSDictionary *) info;

- (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker;

正如 iOS 文档所述,NSDictionary* info 有一个密钥 UIImagePickerControllerOriginalImage,它将返回 UIImage。像这样访问它:

UIImage *snapshot = (UIImage *) [info objectForKey: UIImagePickerControllerOriginalImage];

由于您的计划是使用 takePicture 自动拍照(无需用户交互),因此请务必指定

  picker.showsCameraControls = NO;

【讨论】:

我今天做了更多的阅读。我的要求是在显示相机预览后自动单击图片(用户不应手动单击相机应用程序上的按钮)。我的假设是 takePicture API 会?在我的情况下,didFinishPickingMediaWithInfo 将不起作用,因为用户无法手动单击或选择“使用照片”选项 Apple 文档要求您在以编程方式调用 takePicture 时不要显示图像选择器控件。请参阅上面的编辑。 好的,我确实将图像选择器控件添加到否,我已经用最新的代码编辑了我的原始问题,但它仍然没有进入 didFinishPickingMediaWithInfo 函数。我的疑问是 takePicture 是否真的点击了图片?我还能如何进入 didFinishPickingMediaWithInfo API ? 编辑了注释以查看 Apple 示例代码,该代码完全符合您的要求(并且还做得更多)。祝你好运。 我确实参考了这个例子,它非常有见地,但它仍然没有解决我的问题。我希望应用程序自动化到用户甚至不应该按下自定义按钮的程度,但是当我尝试自己调用该方法或模拟按钮按下时,应用程序不会产生预期的结果。我应该尝试添加一个计时器吗?【参考方案2】:

你需要实现 UIImagePIckerControllerDelegate 的 imagePickerController:didFinishPickingMediaWithInfo: 方法。

之后,查看 mediaInfo 字典,里面有一个 UIImage 可以使用。

【讨论】:

我在日志语句中添加了以下代码,但它并没有进入这个函数,是我遗漏了什么吗? -(void) imagePickerController: (UIImagePickerController *) picker didFinishPickingMediaWithInfo: (NSDictionary *) info NSLog(@"进入整理图片的情况"); - (void) imagePickerControllerDidCancel: (UIImagePickerController *) 选择器 【参考方案3】:

我知道这是旧的,但使用计时器的更好替代方法(请参阅已接受答案中的 cmets)是实现完成处理程序而不是传入 NULL。

[self presentViewController:picker animated:YES completion:^
    NSLog(@"Taking the picture now");
    [picker takePicture];
];

这样,每次都能一致地拍摄照片,并且您不会浪费时间添加不必要的延迟。

【讨论】:

【参考方案4】:
**You can auto capturing both camera image and video recording by use this code.**

import UIKit
import AVFoundation
import MobileCoreServices

class ViewController: UIViewController, UIGestureRecognizerDelegate 

    let captureSession = AVCaptureSession()
    var captureDevice : AVCaptureDevice?
    var imagePicker = UIImagePickerController()
    var flagVideoRecording = false
    var arrImages = [UIImage]()
    var countVideoRecording = 0
    var labelTime = UILabel()
    var timer: Timer?
    
    override func viewDidLoad() 
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(actionRepeatCapturing), name: .AVCaptureSessionDidStartRunning, object: nil)
    
    
    @objc func actionRepeatCapturing() 
        flagVideoRecording = false
        startCapturingBothImageAndRecordView()
    
    
    //MARK:- UIButton's Action
    @IBAction func actionCaptureImage(_ sender: UIButton) 
        flagVideoRecording = false
        
        if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) ==  AVAuthorizationStatus.authorized 
            startCapturingBothImageAndRecordView()
         else 
            AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler:  (granted: Bool) -> Void in
                if granted == true 
                    self.startCapturingBothImageAndRecordView()
                 else 
                    DispatchQueue.main.async 
                        self.alertToEncourageAccessInitially("Camera access required for capturing photos!", actionTitle: "Allow Camera")
                    
                
            )
        
    
    
    @IBAction func actionCaptureVideo(_ sender: UIButton) 
        flagVideoRecording = true
        if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) ==  AVAuthorizationStatus.authorized 
            switch AVAudioSession.sharedInstance().recordPermission 
            case AVAudioSession.RecordPermission.granted:
                self.startCapturingBothImageAndRecordView()
            case AVAudioSession.RecordPermission.denied:
                self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
            case AVAudioSession.RecordPermission.undetermined:
                
                AVAudioSession.sharedInstance().requestRecordPermission( (granted) in
                    if granted 
                        self.startCapturingBothImageAndRecordView()
                     else 
                        self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
                    
                )
                
            default:
                break
            
         else 
            AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler:  (granted: Bool) -> Void in
                if granted == true 
                    switch AVAudioSession.sharedInstance().recordPermission 
                    case AVAudioSession.RecordPermission.granted:
                        self.startCapturingBothImageAndRecordView()
                    case AVAudioSession.RecordPermission.denied:
                        self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
                    case AVAudioSession.RecordPermission.undetermined:
                        
                        AVAudioSession.sharedInstance().requestRecordPermission( (granted) in
                            if granted 
                                self.startCapturingBothImageAndRecordView()
                             else 
                                self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
                            
                        )
                        
                    default:
                        break
                    
                 else 
                    DispatchQueue.main.async 
                        self.alertToEncourageAccessInitially("Camera access required for record video", actionTitle: "Allow Camera")
                    
                
            )
        
    


extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate 
    func startCapturingBothImageAndRecordView() 
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) 
            debugPrint("captureVideoPressed and camera available.")
            imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.sourceType = .camera
            if flagVideoRecording 
                imagePicker.mediaTypes = [kUTTypeMovie as String]
                imagePicker.allowsEditing = false
                imagePicker.showsCameraControls = false
                
                let viewTime = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 40))
                viewTime.backgroundColor = .black
                viewTime.alpha = 0.1
                labelTime = UILabel(frame: CGRect(x: self.view.frame.width/2-50, y: 10, width: 100, height: 25))
                labelTime.font = UIFont.boldSystemFont(ofSize: 17)
                labelTime.text = "00.00:00"
                labelTime.textColor = .white
                labelTime.textAlignment = .center
                labelTime.backgroundColor = .red
                imagePicker.view.addSubview(viewTime)
                imagePicker.view.addSubview(labelTime)
                
                self.timer = Timer.scheduledTimer(timeInterval: 1,
                                     target: self,
                                     selector: #selector(self.actionStopVideoRecording),
                                     userInfo: nil,
                                     repeats: true)
             else 
                imagePicker.allowsEditing = false
                imagePicker.showsCameraControls = false
            
         else 
            debugPrint("Camera not available.")
        
        
        
        self.present(self.imagePicker, animated: true, completion: 
            if self.flagVideoRecording 
                self.imagePicker.startVideoCapture()
             else 
                self.imagePicker.takePicture()
            
        )
    
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) 
        
        if flagVideoRecording 
            if let videoFileURL = info[UIImagePickerController.InfoKey.mediaURL] as? URL 
                debugPrint(videoFileURL)
                
//                let data = try Data(contentsOf: videoFileURL, options: .mappedIfSafe)
//                debugPrint(data)
            
            self.dismiss(animated: true, completion: nil)
         else 
            if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
                arrImages.append(pickedImage)
            
            
            sleep(1)
            
            if arrImages.count >= 5 
                self.dismiss(animated: true, completion: nil)
             else 
                NotificationCenter.default.post(name: .AVCaptureSessionDidStartRunning, object: nil, userInfo: nil)
            
        
    
    
    @objc func actionStopVideoRecording() 
        countVideoRecording += 1
        labelTime.text = countVideoRecording == 10 ? "00:00:\(countVideoRecording)":"00:00:0\(countVideoRecording)"
        
        if countVideoRecording == 10 
            imagePicker.stopVideoCapture()
            timer?.invalidate()
            timer = nil
        
    


extension ViewController 
    func alertToEncourageAccessInitially(_ msgString: String, actionTitle: String) 
        let alert = UIAlertController(
            title: "IMPORTANT",
            message: msgString,
            preferredStyle: UIAlertController.Style.alert
        )
        alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: actionTitle, style: .destructive, handler:  (alert) -> Void in
            let myUrl = URL(string: UIApplication.openSettingsURLString)!
                if let url = URL(string: "\(myUrl)"), !url.absoluteString.isEmpty 
                    UIApplication.shared.open(url, options: [:], completionHandler: nil)
                

                // or outside scope use this
                guard let url = URL(string: "\(myUrl)"), !url.absoluteString.isEmpty else 
                   return
                
                 UIApplication.shared.open(url, options: [:], completionHandler: nil)
        ))
        present(alert, animated: true, completion: nil)
    

【讨论】:

以上是关于IOS自动抓图的主要内容,如果未能解决你的问题,请参考以下文章

win10按键精灵抓抓抓图跟鼠标位置颜色不符合

如何把浏览的书籍自动抓图

QQuickWidget 抓图

剪切板实现进程间持续抓图转显

Qt之使用GDI实现屏幕快速抓图与缩放

抓图小爬虫