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

feat: Android Camera v2 API #339

Open
wants to merge 38 commits into
base: master
Choose a base branch
from

Conversation

dpa99c
Copy link

@dpa99c dpa99c commented Jun 22, 2024

This PR contains a rewrite of the Android implementation to use the Camera v2 API instead of the deprecated Camera API.

The main reason for this change is to fix issues I was encountering with the existing implementation where the camera preview/captured image from this plugin did not correspond the camera preview/captured image from the default Camera app. i.e. this fixes #275

It also opens the way to fetch the device's camera details and select a specific camera/lens based on these [see #256].
While the fetch side is implemented by this PR (getCameraCharacteristics()), the selection of a specific camera/lens is not (as I didn't need it for my use case).

I also implements getZoom(), setZoom() and getMaxZoom() on both Android & iOS, reworking my previous PR #326 on Android to work with Camera v2 API.

@forgr-owner
Copy link

Hey @dpa99c feel free to propose your PR here: Cap-go/camera-preview#61
There is bounty of $100

@varshith257
Copy link

varshith257 commented Jul 7, 2024

@dpa99c Is this changes works? Maybe a demo video demonstrating this changes could be good to add in PR description.

It could get easy for @pbowyer or @arielhernandezmusa to get quick reviewed. Hope this get merged soon. I am waiting for the Camera2 API to be integrated in the capacitor soon :)

@eggbeard
Copy link

This is a huge step in the right direction and deserves some attention to get it merged.
I am struggling to get the preview to display with the correct aspect ratio, with this PR

# Conflicts:
#	android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java
…s to ensure all forms of exception are caught

# Conflicts:
#	android/src/main/java/com/ahm/capacitor/camera/preview/CameraActivity.java
#	android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java
Send error and log messages as plugin events back to JS layer
…and do not attempt to restore previous orientation

# Conflicts:
#	android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java
@dpa99c dpa99c mentioned this pull request Nov 12, 2024
@dpa99c
Copy link
Author

dpa99c commented Nov 12, 2024

I am using this test project to validate the plugin functionality:
https://github.com/dpa99c/capacitor-camera-preview-test

@eggbeard
Copy link

eggbeard commented Nov 13, 2024

@dpa99c Thanks for the test project. I believe that using a square preview in the test project is camouflaging a bug in computing the transformation matrix for the preview, since width and height are often the same and many aspect ratios collapse out to 1.

If you make the width, twice the height, then it becomes apparent that, in landscape mode the preview looks stretched vertically, while in portrait the opposite happens (the preview is squashed in Y)

I took a look through configureTransform, but to be honest did not understand it very well. It seems likely that scaleY is calculated wrongly, but trying to work out what it should be hurts my brain.

I have only tested on Android. I don't have access to an apple device

return mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
}

private void configureTransform(int viewWidth, int viewHeight) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still haven't pinned this one down, but something like:

private void configureTransform(int viewWidth, int viewHeight) {
        if (cameraDevice == null || !textureView.isAvailable() || mPreviewSize == null) {
            return;
        }
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        Matrix matrix = new Matrix();
        RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
        RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
        float centerX = viewRect.centerX();
        float centerY = viewRect.centerY();
        if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
            bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
            matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
            float scale = Math.max(
                    (float) viewHeight / mPreviewSize.getHeight(),
                    (float) viewWidth / mPreviewSize.getWidth());
            matrix.postScale(scale, scale, centerX, centerY);
            matrix.postRotate(90 * (rotation - 2), centerX, centerY);
        } else if (Surface.ROTATION_180 == rotation) {
            matrix.postRotate(180, centerX, centerY);
        }
        textureView.setTransform(matrix);
    }

Copy link
Member

@ryaa ryaa Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eggbeard I have tested your PR dpa99c#1 and it works great. @dpa99c I suggest to merge this PR into the capacitor-community/camera-preview master and release it, as this is a long-awaited change which should resolve bunch of the existing bugs/limitations :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have another fix to also include in this PR, so I'll try to make some time today to add this and @eggbeard's fix to the PR. Looks like I also need to resolve conflicts with master so will do that at the same time.

I suggest some exhaustive testing to find any other issues before merging in to master though.
I created this code for a specific use case (e.g. square preview) so have not extensively tested other generic usages.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dpa99c thank you very much for the prompt feedback. I will try to do more testing once you add your changes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having trouble getting this working for different preview aspect ratios so it's going to take me a bit longer to get it right

@ryaa
Copy link
Member

ryaa commented Dec 19, 2024

I am struggling to get the preview to display with the correct aspect ratio, with this PR

It seems that I faced the same issue while testing this PR with my existing implementation. Here is my preview UI
Screenshot_20241219_082741_BOSS811

and here is the photo taken/saved
B833400772_lnFJEuRMY

In my implementation I use the below camera preview options (note that x, y, width and height are not provided!)

      const footerHeight = (this.footer && this.footer.nativeElement) ? this.footer.nativeElement.offsetHeight : 44;
      const cameraPreviewOptions: CameraPreviewOptions = {
        position: 'rear',
        paddingBottom: footerHeight,
        rotateWhenOrientationChanged: true,
        lockAndroidOrientation: false,
        toBack: true,
        disableAudio: true,
        disableExifHeaderStripping: false
      };

while the test/demo app for this PR uses this https://github.com/dpa99c/capacitor-camera-preview-test/blob/master/src/views/HomePage.vue#L95 camera preview options (note that x, y, width and height are provided!) which makes the preview to be a square with the same width/height. Therefore, I think that, the camera preview works incorrectly when x, y, width and height are not provided. Please note that these are optional (see https://github.com/capacitor-community/camera-preview?tab=readme-ov-file#startoptions) and, I think, that the camera plugin should work as before when these are not provided.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Preview size is not correctly calculated in Portrait mode
5 participants