Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camera View Orientation Bug? #216

Open
ghost opened this issue Feb 11, 2020 · 14 comments
Open

Camera View Orientation Bug? #216

ghost opened this issue Feb 11, 2020 · 14 comments
Labels
bug Something isn't working

Comments

@ghost
Copy link

ghost commented Feb 11, 2020

If i change the Orientation on the iPad (iOS 11) its rotating the Camera View.
After its rotated the Axis in the Camera View are swapped. When i turn the iPad to the left the camera view moves the visible camera output to the bottom.
Is this a bug or could u give me any advice to fix this behaviour?
Its mentioned in #76 and #185 and it's still a problem or am i missing something?

@bdjessup
Copy link

bdjessup commented Mar 9, 2020

I am still seeing this bug as well (iPad Pro, iOS 13).

Regardless of whether an app is launched in landscape or portrait, the scanner opens in portrait.

@github-actions
Copy link

github-actions bot commented Apr 9, 2020

This issue is stale because it has been open for 30 days with no activity. Remove the Stale label or comment or this will be closed in 10 days.

@github-actions github-actions bot added the Stale label Apr 9, 2020
@AvdLee AvdLee reopened this Aug 17, 2020
@AvdLee AvdLee added bug Something isn't working and removed Stale labels Aug 17, 2020
@Pellagius
Copy link

Just bumping to add interest - Im of firm belief this is actually an issue at the iOS framework level, other libraries and scanning implementations have users reporting the same issue. I first discovered it using WeScan.

I experience the bug on an iPad Air iOS 12.4.8, there are other iOS devices not experiencing the bug.

Is there any insight into its remedy here?

@AvdLee
Copy link
Contributor

AvdLee commented Aug 21, 2020

Is there any insight into its remedy here?

We have not yet found the time to dive in. In those other projects, have you found an example with a fix too? That could help speed up fixing this.

@ethanwa
Copy link

ethanwa commented Mar 22, 2021

My customers are seeing this bug as well on all iPad devices. Any way to make this a priority fix?

@AvdLee
Copy link
Contributor

AvdLee commented Mar 23, 2021

@ethanwa unfortunately, we're not actively developing WeScan at this moment. We're happy to receive any contributions and review accordingly.

@willm132
Copy link

willm132 commented May 18, 2021

Has anyone been able to fix this yet? My app only works in landscape and the camera pops up in portrait orientation.

@willm132
Copy link

@AvdLee Would just changing this be able to fix our issues?

override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {        
    return .portrait   
// can we change this to .landscape to change the orientation? 
// Or is there more to this like having to change camera properties?
}

@AvdLee
Copy link
Contributor

AvdLee commented May 26, 2021

@AvdLee Would just changing this be able to fix our issues?

I've not tried that out but to me, that would disable landscape completely, wouldn't it?

@willm132
Copy link

@AvdLee I am not sure. Is anyone able to take a look at a fix for this?

@AvdLee
Copy link
Contributor

AvdLee commented May 28, 2021

@AvdLee I am not sure. Is anyone able to take a look at a fix for this?

Currently, WeScan is not on our list of priorities. We're open for contributions and aim to review PRs within 1 working day. So feel free to apply a fix 🙂

@samkass
Copy link

samkass commented Dec 3, 2023

I also ran into this.

So I tried to dig into it, and it's a bit of a rabbit hole. Just returning .all from supportedInterfaceOrientations doesn't do much. I then was able to correct the video preview in CameraScannerViewController by updating the orientation in viewDidLayoutSubviews, which fixed the video, but the rectangle overlays were still wrong. To fix that you'd have to recalculate the quad transforms. Once the preview is fixed, you'd then have to update the capture code to ensure the actual images are properly processed in the right orientation.

The whole package seems to be designed for portrait mode, so there is no isolated surgical fix.

I looked around for other example code, and all examples I could find, including from Apple, do not handle landscape mode properly for any of their VN examples with previews.

The last comment here was from 2 years ago, so if anyone else solved this in the interim I'm interested in what they did.

@pragadeeshNIS
Copy link

Hi, Any update on this issue?
Did anyone find any solution for this?

@camilocalvo
Copy link

I got this to work, but improvements to the code are welcome.

First, at the top of the CameraScannerViewController.swift file, add a variable to track the current orientation:

private var orientation: UIDeviceOrientation = .portrait

Next, you'll need to listen for orientation changes and use those to rotate the video feed manually. You can use the following modification to viewDidLayoutSubviews, plus a helper function:

private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {
    layer.videoOrientation = orientation
    videoPreviewLayer.frame = view.bounds
}

override public func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    if let connection = videoPreviewLayer.connection {
        let currentDevice = UIDevice.current
        orientation = currentDevice.orientation
        
        let previewLayerConnection: AVCaptureConnection = connection
        
        if previewLayerConnection.isVideoOrientationSupported {
            switch orientation {
            case .portrait: self.updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
            case .landscapeRight: self.updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeLeft)
            case .landscapeLeft: self.updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeRight)
            case .portraitUpsideDown: self.updatePreviewLayer(layer: previewLayerConnection, orientation: .portraitUpsideDown)
            default: self.updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
            }
        }
    }
    
    videoPreviewLayer.frame = view.layer.bounds
}

Now we'll deal with the quad layer, which is also out of sync. Go to the function on line 182, captureSessionManager (there are several functions with that name, so make sure you have the right one). Here, replace the line that sets portraitImageSize with the following two lines:

let rotationAngle = orientation == .portrait ? CGFloat.pi / 2.0 : orientation == .landscapeLeft ? 0 : CGFloat.pi
let portraitImageSize = orientation == .portrait ? CGSize(width: imageSize.height, height: imageSize.width) : CGSize(width: imageSize.width, height: imageSize.height)

And update the rotationTransform assignment later in the function to use your new rotationAngle variable:

let rotationTransform = CGAffineTransform(rotationAngle: rotationAngle)

Finally, there's ensuring that the image is oriented correctly when you go to edit it. For this, go to the completeImageCapture function at the end of the CaptureSessionManager extension (line 324). The changes here are spread out around the function, so I'll post the entire modified function. The idea is to rotate the image and the quad layer by the proper amount for both landscape orientations.

private func completeImageCapture(with imageData: Data) {
        DispatchQueue.global(qos: .background).async { [weak self] in
            CaptureSession.current.isEditing = true
            guard let image = UIImage(data: imageData) else {
                let error = ImageScannerControllerError.capture
                DispatchQueue.main.async {
                    guard let self else {
                        return
                    }
                    self.delegate?.captureSessionManager(self, didFailWithError: error)
                }
                return
            }
            
            let currentDevice = UIDevice.current
            let orientation = currentDevice.orientation
            
            var rotatedImage = image
            var angle: CGFloat = CGFloat.pi / 2

            switch orientation {
            case .landscapeLeft:
                rotatedImage = UIImage(cgImage: image.cgImage!, scale: 1.0, orientation: .down)
                angle = 0
            case .landscapeRight:
                rotatedImage = UIImage(cgImage: image.cgImage!, scale: 1.0, orientation: .up)
                angle = CGFloat.pi
            default:
                break
            }

            var quad: Quadrilateral?
            if let displayedRectangleResult = self?.displayedRectangleResult {
                quad = self?.displayRectangleResult(rectangleResult: displayedRectangleResult)
                quad = quad?.scale(displayedRectangleResult.imageSize, rotatedImage.size, withRotationAngle: angle)
            }

            DispatchQueue.main.async {
                guard let self else {
                    return
                }
                self.delegate?.captureSessionManager(self, didCapturePicture: rotatedImage, withQuad: quad)
            }
        }
    }

Let me know if anyone has any questions. If demand is high enough I can create a PR as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

8 participants