AVFoundation PhotoApp - 在图像保存在库中之前无法使闪存正常工作
Posted
技术标签:
【中文标题】AVFoundation PhotoApp - 在图像保存在库中之前无法使闪存正常工作【英文标题】:AVFoundation PhotoApp - Can't get the flash working before the image saves in the library 【发布时间】:2017-03-03 08:14:35 【问题描述】:在我发布用于控制我的 cameraApp 主视图的 viewController 的整个代码之前,我会告诉你会发生什么,什么有效,什么无效。用于拍摄照片并保存照片的按钮,用于更改相机(前/后),将闪光灯设置为自动/关闭。这段代码中还有其他一些东西现在已经设置但未使用,但我不认为它们导致了这个问题,我认为我的无知是主要问题。我想通过你们的帮助实现的是,当我按下相机按钮时,如果闪光灯设置为自动,应用程序会在需要时使用闪光灯,然后保存图片。我希望有人可以帮助我,苹果文档告诉你所有的命令,但没有简单的方法把它们放在哪里。在此先感谢,这是我的代码:
import UIKit
import AVFoundation
import PageMenu
class randomController: UIViewController, UIImagePickerControllerDelegate,UINavigationControllerDelegate, CAPSPageMenuDelegate, AVCapturePhotoCaptureDelegate
@IBOutlet weak var cameraPreview: UIImageView!
@IBAction func cameraButton(_ sender: Any)
let settings = AVCapturePhotoSettings()
let previewPixelType = settings.availablePreviewPhotoPixelFormatTypes.first!
let previewFormat = [
kCVPixelBufferPixelFormatTypeKey as String: previewPixelType,
kCVPixelBufferWidthKey as String: 160,
kCVPixelBufferHeightKey as String: 160
]
let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
if (device?.hasTorch)!
do
print("diosotterrato")
try device?.lockForConfiguration()
//device?.torchMode = AVCaptureTorchMode.on
// device?.torchMode = AVCaptureTorchMode.Off
device?.torchMode = AVCaptureTorchMode.auto
device?.unlockForConfiguration()
catch
print(error)
settings.previewPhotoFormat = previewFormat
sessionOutput.capturePhoto(with: settings, delegate: self)
@IBOutlet weak var backgroundMarrone: UIImageView!
func askPermission()
print("here")
let cameraPermissionStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
switch cameraPermissionStatus
case .authorized:
print("Already Authorized")
case .denied:
print("denied")
let alert = UIAlertController(title: "Sorry :(" , message: "But could you please grant permission for camera within device settings", preferredStyle: .alert)
let action = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
alert.addAction(action)
present(alert, animated: true, completion: nil)
case .restricted:
print("restricted")
default:
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler:
[weak self]
(granted :Bool) -> Void in
if granted == true
// User granted
print("User granted")
DispatchQueue.main.async()
//Do smth that you need in main thread
else
// User Rejected
print("User Rejected")
DispatchQueue.main.async()
let alert = UIAlertController(title: "WHY?" , message: "Camera it is the main feature of our application", preferredStyle: .alert)
let action = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
alert.addAction(action)
self?.present(alert, animated: true, completion: nil)
);
@IBOutlet weak var cameracapture: UIImageView!
var pageMenu : CAPSPageMenu?
var captureSession = AVCaptureSession();
var sessionOutput = AVCapturePhotoOutput();
var sessionOutputSetting = AVCapturePhotoSettings(format: [AVVideoCodecKey:AVVideoCodecJPEG]);
var previewLayer = AVCaptureVideoPreviewLayer();
var flashButton = UIButton()
override func viewDidLoad()
super.viewDidLoad()
pageMenu?.delegate = self
var controllerArray : [UIViewController] = []
backgroundMarrone.frame = CGRect(x: 0, y:(view.frame.maxY/10*5), width: self.view.frame.width, height: self.view.frame.height )
cameraPreview.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: backgroundMarrone.frame.minY )
let switchCameraButton = UIButton(frame: CGRect(x: 5, y: cameraPreview.frame.maxY/12*9.8, width: 50, height: 50))
switchCameraButton.backgroundColor = UIColor(red: 100.0/255.0, green: 39.0/255.0, blue: 87.0/255.0, alpha: 0.0)
switchCameraButton.addTarget(self, action: #selector(pressButton(button:)), for: .touchUpInside)
switchCameraButton.setImage(#imageLiteral(resourceName: "btn_reverse_camera copy.png"), for: UIControlState.normal)
self.view.addSubview(switchCameraButton)
flashButton = UIButton(frame: CGRect(x: cameraPreview.frame.maxX - 55, y: cameraPreview.frame.maxY/12*9.8, width: 50, height: 50))
flashButton.backgroundColor = UIColor(red: 100.0/255.0, green: 39.0/255.0, blue: 87.0/255.0, alpha: 0.0)
flashButton.addTarget(self, action: #selector(pressButton1(button:)), for: .touchUpInside)
flashButton.setImage(#imageLiteral(resourceName: "btn_flash copy.png"), for: UIControlState.normal)
self.view.addSubview(flashButton)
let libraryController : UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "libraryController") as! libraryController
libraryController.title = "Libreria"
controllerArray.append(libraryController)
let photoController : UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "photoController") as! photoController
photoController.title = "Foto"
controllerArray.append(photoController)
let videoController : UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "videoController") as! videoController
videoController.title = "Video"
controllerArray.append(videoController)
let parameters: [CAPSPageMenuOption] = [
.menuItemSeparatorWidth(0),
.useMenuLikeSegmentedControl(true),
.menuItemSeparatorPercentageHeight(0.1),
.centerMenuItems (true)
]
pageMenu = CAPSPageMenu(viewControllers: controllerArray, frame: CGRect(x: 0, y: cameraPreview.frame.maxY , width: self.view.frame.width, height: view.frame.height ), pageMenuOptions: parameters)
self.view.addSubview(pageMenu!.view)
var ciaone = false
override func viewWillAppear(_ animated: Bool)
let deviceDiscoverySession = AVCaptureDeviceDiscoverySession(deviceTypes: [AVCaptureDeviceType.builtInDualCamera, AVCaptureDeviceType.builtInTelephotoCamera,AVCaptureDeviceType.builtInWideAngleCamera], mediaType: AVMediaTypeVideo, position: AVCaptureDevicePosition.unspecified)
for device in (deviceDiscoverySession?.devices)!
print("tipo di device: \(device.position)")
if(device.position == AVCaptureDevicePosition.front)
do
let input = try AVCaptureDeviceInput(device: device)
if(captureSession.canAddInput(input))
captureSession.addInput(input);
captureSession.startRunning()
print("entrato1")
if(captureSession.canAddOutput(sessionOutput))
captureSession.addOutput(sessionOutput);
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession);
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
previewLayer.connection.videoOrientation = AVCaptureVideoOrientation.portrait;
cameraPreview.layer.addSublayer(previewLayer);
print("entrato2")
catch
print("exception!");
func beginSession(captureDevice : AVCaptureDevice?)
ciaone = false
if captureSession.isRunning
captureSession.beginConfiguration()
let currentInput : AVCaptureInput = captureSession.inputs[0] as! AVCaptureInput
captureSession.removeInput(currentInput)
do
try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice))
catch
print("Error adding video input device")
captureSession.commitConfiguration()
else
// Setup the camera and layer for the first time.
do
try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice))
catch
print("Error adding video input device")
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
self.view.layer.insertSublayer(previewLayer, at: 0)
previewLayer.frame = cameraPreview.bounds
captureSession.startRunning()
func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?, previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?)
if let error = error
print("error occure : \(error.localizedDescription)")
if let sampleBuffer = photoSampleBuffer,
let previewBuffer = previewPhotoSampleBuffer,
let dataImage = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: previewBuffer)
print(UIImage(data: dataImage)?.size as Any)
let dataProvider = CGDataProvider(data: dataImage as CFData)
let cgImageRef: CGImage! = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent)
let image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: UIImageOrientation.right)
UIImageWriteToSavedPhotosAlbum(image, self, nil, nil)
self.cameracapture.image = image
else
print("some error here")
var a = 0
func pressButton(button: UIButton)
if (a == 0)
print("dioschifoso!")
beginSession(captureDevice: AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo))
a = 1
else
beginSession(captureDevice: AVCaptureDevice.defaultDevice(withDeviceType: AVCaptureDeviceType.builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: AVCaptureDevicePosition.front))
a = 0
var flash = 0
func toggleTorch(on: Bool)
//guard let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) else return
/*
if device.hasTorch
do
try device.lockForConfiguration()
if on == true
device.torchMode = .on
else
device.torchMode = .off
device.unlockForConfiguration()
catch
print("Torch could not be used")
else
print("Torch is not available")
*/
func pressButton1(button: UIButton)
let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
if (device?.hasTorch)!
do
try device?.lockForConfiguration()
//device?.torchMode = AVCaptureTorchMode.on
// device?.torchMode = AVCaptureTorchMode.Off
device?.torchMode = AVCaptureTorchMode.off
device?.unlockForConfiguration()
catch
print(error)
if (a == 0)
let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
if (device?.hasTorch)!
do
try device?.lockForConfiguration()
device?.torchMode = AVCaptureTorchMode.auto
// device?.torchMode = AVCaptureTorchMode.Off
//device?.torchMode = AVCaptureTorchMode.auto
device?.unlockForConfiguration()
catch
print(error)
//toggleTorch(on: true)
flashButton.setImage(#imageLiteral(resourceName: "btn_flash_off.png"), for: UIControlState.normal)
a = 1
else
//toggleTorch(on: false)
flashButton.setImage(#imageLiteral(resourceName: "btn_flash copy.png"), for: UIControlState.normal)
a = 0
override func viewDidLayoutSubviews()
super.viewDidLayoutSubviews()
previewLayer.frame = cameraPreview.bounds
func capturePicture()
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
【问题讨论】:
【参考方案1】:Swift 3.0 和 Xcode >= 8
@IBAction func flashTapped()
// check if flashlight available
let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
if (device?.hasTorch)! && (device?.hasFlash)!
do
try device?.lockForConfiguration()
catch
// handle error
return
if device?.torchMode == .auto
device?.torchMode = .on
device?.flashMode = .on
else if device?.torchMode == .on
device?.torchMode = .off
device?.flashMode = .off
else
device?.torchMode = .auto
device?.flashMode = .auto
device?.unlockForConfiguration()
【讨论】:
我会在几分钟内整合这段代码,到时候我会报告的!顺便感谢您的帮助:) 实现了它,但它给了我很多错误,最大的错误发生在 device.lock 配置中,xcode 告诉我“参数传递给不带参数的调用”。除此之外,还有很多可选类型展开。 谢谢,iOS 10 弃用了 .flashmode,改用 AVCapturePhotoSettings.flashMode ,我该如何实现呢? 另外,我试过你的更新代码,它可以工作,但是当我拍摄照片时,如果它设置为自动,例如在黑暗的房间里,它不使用闪光灯。我不明白为什么:( 第一次尝试使用闪光灯模式 = 打开并检查暗室是否正常工作?以上是关于AVFoundation PhotoApp - 在图像保存在库中之前无法使闪存正常工作的主要内容,如果未能解决你的问题,请参考以下文章