Flutter mobile_scanner camerax setFocus 기능 구현

신석진( Seokjin Shin)·2023년 6월 12일
0

portrait 모드가 아니라면 너비와 높이를 바꾸어서 좌표를 계산해야한다. 또한 좌우 flutter에서 발생한 좌표를 y축 반전해야 올바른 좌표가 나온다.

kotlin 코드

/**
* Set the focus point of the camera.
*/
fun setFocus(point: Map<String, Double>) {
    val x = point["x"]!!.toFloat()
    val y = point["y"]!!.toFloat()

    val portrait = camera!!.cameraInfo.sensorRotationDegrees % 180 == 0
    val resolution = preview!!.resolutionInfo!!.resolution
    val width = resolution.width.toFloat()
    val height = resolution.height.toFloat()

    val meteringPoint = SurfaceOrientedMeteringPointFactory(
        if (portrait) width else height,
        if (portrait) height else width
    ).createPoint(x, y)

    // Prepare focus action to be triggered.
    val action = FocusMeteringAction.Builder(meteringPoint).build()

    // Execute focus action
    camera!!.cameraControl.startFocusAndMetering(action)
}

swift 코드

func setFocus(_ point: Dictionary<String, Double>) throws {
        if (device == nil) {
            throw MobileScannerError.focusWhenStopped
        }
        
        do {
            try device.lockForConfiguration()
            
            var size = latestBuffer.image.size
            
            var portrait = UIDevice.current.orientation.isPortrait
            var width = portrait ? size.width : size.height
            var height = portrait ? size.height : size.width
            
            var touch_x = (point["x"] ?? 0.0)
            var touch_y = (point["y"] ?? 0.0)
            
            var x = touch_x / width
            var y = touch_y / height
            
            var point = CGPoint(x: x, y: y)
            
            if device.isFocusPointOfInterestSupported {
                device.focusPointOfInterest = point
            }
            
            if device.isExposurePointOfInterestSupported{
                device.exposurePointOfInterest = point
            }
            
            if device.isFocusModeSupported(.continuousAutoFocus) {
                device.focusMode = .continuousAutoFocus
            }
            
            if device.isExposureModeSupported(.continuousAutoExposure){
                device.exposureMode = .continuousAutoExposure
            }
            
            device.unlockForConfiguration()
        } catch {
            throw MobileScannerError.cameraError(error)
        }
    }

화면 회전 여부에 따른 값 변경 외에는 크게 로직이 들어있지는 않다.

dart 코드

GestureDetector(
          //플러터에서 터치된 위치를 계산한다.
          onTapDown: (details) {
            final position = details.globalPosition;
            var x = position.dx * ratio;
            var y = (position.dy - top) * ratio;

            final controller = qrController.controller.value;
            final arguments = controller?.startArguments.value;

            //실제 기기의 픽셀 사이즈를 계산한다.
            final fullWidth = size.width * ratio;
            final fullHeight =
                (size.height + top + bottom) * ratio + kToolbarHeight;

            final image = arguments?.size ?? const Size(0, 0);
            final device = Size(fullWidth, fullHeight);
            final preview = image * device.width / image.width;

            //플러터에서 옮겨준 위치를 계산한다.
            y = y - (101 + upperRest) * ratio;

            //프리뷰에서 확장된 이미지의 터치 위치를 계산한다.
            y = preview.height / device.height * y;

            //좌우 반전된 터치 영역을 계산한다.
            x = device.width - x;

            //90도 회전된 터치 영역을 넘겨준다.
            qrController.focus(y, x);
          },
        ),

실질적인 좌표 계산은 Flutter에서 해서 넘기는 방향으로 개발을 진행하였다. 플러그인에 로직이 녹아 있으면 범용적으로 쓰이기 어렵다고 판단했기 때문이다.

참고
Github repo
AOS camerax tap to focus
AOS focus point
iOS focus point

0개의 댓글