barcode scanner zoom기능 구현
개요
관리하는 어플 내 barcode scanner 에서 아이폰 14 pro, 15 pro와 같이 카메라가 3개 이상인, 즉 광각모드를 지원하는 기기의 경우 바코드를 가까이 댔을 때 초점을 잃어 스캔하지 못하는 기기자체의 오류 발생
→ 멀리서 초점은 맞춰지지만 바코드끼리 겹쳐져서 인식이 안되는 문제가 발생하는 것
그래서 든 생각은?
그래서 내가 선택한 방법은,
1. 광각카메라를 인식하여 광각카메라인 경우 카메라 입력에 추가하여 예외처리하기
구현했지만 카메라를 제대로 인식하지 못해 보류 (코드엔 넣어놓음)
// 광각 카메라 찾기
guard let wideAngleCamera = AVCaptureDevice.DiscoverySession(
deviceTypes: [.builtInWideAngleCamera],
mediaType: .video,
position: .back).devices.first else {
fatalError("광각 카메라를 찾을 수 없습니다.")
}
captureDevice = wideAngleCamera
2. auto-focusing 구현
자동으로 초점을 맞추도록 구현하려고 했으나 어플에 해당 코드를 집어넣으면 코드에 오류 발생, 문제를 해결하지 못해 해당 방법은 기각함
3. touch-focusing 구현
- 터치하면 focusing 되도록 구현했고 작동은 하지만 문제를 해결할만큼 확실히 작동하는 것 같지는 않음
// 터치 제스처 설정
private func setupTapGestureRecognizer() {
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapToFocus(_:)))
view.addGestureRecognizer(tapGestureRecognizer)
}
@objc private func handleTapToFocus(_ tap: UITapGestureRecognizer) {
let location = tap.location(in: view)
let devicePoint = previewLayer.captureDevicePointConverted(fromLayerPoint: location)
guard let device = captureDevice else { return }
do {
try device.lockForConfiguration()
if device.isFocusPointOfInterestSupported {
device.focusPointOfInterest = devicePoint
device.focusMode = .autoFocus
}
if device.isExposurePointOfInterestSupported {
device.exposurePointOfInterest = devicePoint
device.exposureMode = .autoExpose
}
device.unlockForConfiguration()
// 포커스 애니메이션
focusView.center = location
focusView.isHidden = false
UIView.animate(withDuration: 0.3, animations: {
self.focusView.transform = CGAffineTransform(scaleX: 1.25, y: 1.25)
}) { _ in
UIView.animate(withDuration: 0.3) {
self.focusView.transform = CGAffineTransform.identity
}
}
} catch {
print("포커스 설정 중 오류 발생: \\(error.localizedDescription)")
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// 카메라 포커스 모드 설정
if let videoCaptureDevice = captureDevice {
do {
try videoCaptureDevice.lockForConfiguration()
if videoCaptureDevice.isFocusModeSupported(.continuousAutoFocus) {
videoCaptureDevice.focusMode = .continuousAutoFocus
}
if videoCaptureDevice.isAutoFocusRangeRestrictionSupported {
videoCaptureDevice.autoFocusRangeRestriction = .near
}
videoCaptureDevice.unlockForConfiguration()
} catch {
print("카메라 포커스 설정에 실패했습니다.")
}
}
}
setupTapGestureRecognizer() // 터치 제스처 설정 추가
// 포커스 뷰 선언
private var focusView: UIView!
// 포커스 애니메이션 뷰 설정
focusView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
focusView.layer.borderWidth = 1.0
focusView.layer.borderColor = UIColor.yellow.cgColor
focusView.backgroundColor = UIColor.clear
focusView.isHidden = true
view.addSubview(focusView)
4. zoom 기능 구현
차라리 멀리서 초점을 맞춰서 확대하자!
private func setupPinchGestureRecognizer() {
let pinchGestureRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(handlePinchCamera(_:)))
view.addGestureRecognizer(pinchGestureRecognizer)
@objc private func handlePinchCamera(_ pinch: UIPinchGestureRecognizer) {
guard let device = captureDevice else { return }
let minZoomFactor: CGFloat = 1.0
let maxZoomFactor: CGFloat = device.maxAvailableVideoZoomFactor
switch pinch.state {
case .began:
lastZoomFactor = device.videoZoomFactor
case .changed:
var newZoomFactor = lastZoomFactor * pinch.scale
newZoomFactor = min(max(newZoomFactor, minZoomFactor), maxZoomFactor)
do {
try device.lockForConfiguration()
device.videoZoomFactor = newZoomFactor
device.unlockForConfiguration()
} catch {
print("줌 조절 중 오류 발생: \\(error.localizedDescription)")
}
case .ended, .cancelled:
pinch.scale = 1.0
default:
break
}
}
Finally
zoom 기능 구현 후 touch-focusing 보완해서 두 기능을 넣어 어플 배포 완료