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

🐛 Preview looks stretched on Android #2583

Closed
3 of 5 tasks
grevtsovna opened this issue Feb 19, 2024 · 70 comments
Closed
3 of 5 tasks

🐛 Preview looks stretched on Android #2583

grevtsovna opened this issue Feb 19, 2024 · 70 comments
Labels
🐛 bug Something isn't working

Comments

@grevtsovna
Copy link

grevtsovna commented Feb 19, 2024

What's happening?

The preview looks stretched on Android.
Screenshot_1708313396

I figured out that it becomes ok when I change the height of the container in which the Camera renders. Here are a screenshot and logs after changing the height in debug mode.
Screenshot_1708313761

2024-02-19 09:35:57.796  9065-9100  Parcel                  com.rncameratest                     W  Expecting binder but got null!
2024-02-19 09:35:57.922  9065-9065  PreviewView             com.rncameratest                     I  PreviewView is 1426x1740, rendering 960x1280 content (LANDSCAPE_LEFT). Resizing to: 1305x1740 (CONTAIN)
2024-02-19 09:35:57.967  9065-9100  EGL_emulation           com.rncameratest                     D  app_time_stats: avg=18224.98ms min=1.65ms max=90444.32ms count=5

It reproduces in the example app as well. To reproduce that, I needed to tap the QR-icon. Here is a screenshot.
Screenshot_1708314932

Investigating the problem I found out that onMeasure in PrevieView.kt method doesn't call after changing the surface size (you can see this in logs). Maybe this is a problem but I'm not sure as I don't have great experience in android development.

Reproduceable Code

function App() {
  const isDarkMode = useColorScheme() === 'dark';

  const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
  };

  const device = useCameraDevice('back');
  const [isMounted, setIsMounted] = React.useState(true);
  const { hasPermission, requestPermission } = useCameraPermission();

  if (!hasPermission) {
    requestPermission();
  }

  if (!device || !hasPermission) {
    return null;
  }

  return (
    <SafeAreaView style={backgroundStyle}>
      <Button
        title={isMounted ? 'Unmount' : 'Mount'}
        onPress={() => setIsMounted(!isMounted)}
      />
      <View style={{ height: 500, borderWidth: 2, borderColor: 'blue' }}>
        {isMounted && (
          <Camera
            device={device}
            isActive
            style={StyleSheet.absoluteFill}
            resizeMode="contain"
          />
        )}
      </View>
    </SafeAreaView>
  );
}

Relevant log output

---------------------------- PROCESS STARTED (9065) for package com.rncameratest ----------------------------
2024-02-19 09:34:27.006  9065-9118  CameraManagerGlobal     com.rncameratest                     I  Connecting to camera service
2024-02-19 09:34:27.014  9065-9065  unknown:ReactNative     com.rncameratest                     W  Packager connection already open, nooping.
2024-02-19 09:34:27.021  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.traceupdateoverlay.TraceUpdateOverlayManager
2024-02-19 09:34:27.023  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.uimanager.LayoutShadowNode
2024-02-19 09:34:27.025  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.drawer.ReactDrawerLayoutManager
2024-02-19 09:34:27.025  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.scroll.ReactHorizontalScrollViewManager
2024-02-19 09:34:27.026  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.scroll.ReactHorizontalScrollContainerViewManager
2024-02-19 09:34:27.026  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.progressbar.ReactProgressBarViewManager
2024-02-19 09:34:27.027  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.progressbar.ProgressBarShadowNode
2024-02-19 09:34:27.027  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.scroll.ReactScrollViewManager
2024-02-19 09:34:27.028  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.switchview.ReactSwitchManager
2024-02-19 09:34:27.028  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.switchview.ReactSwitchManager$ReactSwitchShadowNode
2024-02-19 09:34:27.028  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.swiperefresh.SwipeRefreshLayoutManager
2024-02-19 09:34:27.029  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.text.frescosupport.FrescoBasedReactTextInlineImageViewManager
2024-02-19 09:34:27.029  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.text.frescosupport.FrescoBasedReactTextInlineImageShadowNode
2024-02-19 09:34:27.029  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.image.ReactImageManager
2024-02-19 09:34:27.030  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.modal.ReactModalHostManager
2024-02-19 09:34:27.031  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.modal.ModalHostShadowNode
2024-02-19 09:34:27.031  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.text.ReactRawTextManager
2024-02-19 09:34:27.031  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.text.ReactRawTextShadowNode
2024-02-19 09:34:27.031  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.textinput.ReactTextInputManager
2024-02-19 09:34:27.033  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.textinput.ReactTextInputShadowNode
2024-02-19 09:34:27.034  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.text.ReactTextViewManager
2024-02-19 09:34:27.034  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.text.ReactTextShadowNode
2024-02-19 09:34:27.034  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.view.ReactViewManager
2024-02-19 09:34:27.035  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.text.ReactVirtualTextViewManager
2024-02-19 09:34:27.037  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.text.ReactVirtualTextShadowNode
2024-02-19 09:34:27.037  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.facebook.react.views.unimplementedview.ReactUnimplementedViewManager
2024-02-19 09:34:27.038  9065-9123  unknown:Vi...rtyUpdater com.rncameratest                     W  Could not find generated setter for class com.mrousavy.camera.CameraViewManager
2024-02-19 09:34:27.058  9065-9123  flipper                 com.rncameratest                     I  flipper: FlipperClient::addPlugin Fresco
2024-02-19 09:34:27.058  9065-9123  CameraDevices           com.rncameratest                     I  Camera #0 is now available.
2024-02-19 09:34:27.058  9065-9123  CameraDevices           com.rncameratest                     I  Camera #1 is now available.
2024-02-19 09:34:27.129  9065-9123  ziparchive              com.rncameratest                     W  Unable to open '/data/app/~~xNbgRO-rLXYkt-8Wh3plnQ==/com.google.android.trichromelibrary_616716433-eGWjDUvFX1A0Lohkh9NPww==/base.dm': No such file or directory
2024-02-19 09:34:27.129  9065-9123  ziparchive              com.rncameratest                     W  Unable to open '/data/app/~~xNbgRO-rLXYkt-8Wh3plnQ==/com.google.android.trichromelibrary_616716433-eGWjDUvFX1A0Lohkh9NPww==/base.dm': No such file or directory
2024-02-19 09:34:27.129  9065-9123  om.rncameratest         com.rncameratest                     W  Entry not found
2024-02-19 09:34:27.130  9065-9123  nativeloader            com.rncameratest                     D  Configuring classloader-namespace for other apk /data/app/~~xNbgRO-rLXYkt-8Wh3plnQ==/com.google.android.trichromelibrary_616716433-eGWjDUvFX1A0Lohkh9NPww==/base.apk. target_sdk_version=34, uses_libraries=ALL, library_path=/data/app/~~sNcuhOLFwtB-nZjP6iJRNA==/com.google.android.webview-wyea3Y44NWbGbRddarRSAw==/lib/arm64:/data/app/~~sNcuhOLFwtB-nZjP6iJRNA==/com.google.android.webview-wyea3Y44NWbGbRddarRSAw==/base.apk!/lib/arm64-v8a:/data/app/~~xNbgRO-rLXYkt-8Wh3plnQ==/com.google.android.trichromelibrary_616716433-eGWjDUvFX1A0Lohkh9NPww==/base.apk!/lib/arm64-v8a, permitted_path=/data:/mnt/expand
2024-02-19 09:34:27.131  9065-9123  nativeloader            com.rncameratest                     D  Configuring classloader-namespace for other apk /data/app/~~sNcuhOLFwtB-nZjP6iJRNA==/com.google.android.webview-wyea3Y44NWbGbRddarRSAw==/base.apk. target_sdk_version=34, uses_libraries=, library_path=/data/app/~~sNcuhOLFwtB-nZjP6iJRNA==/com.google.android.webview-wyea3Y44NWbGbRddarRSAw==/lib/arm64:/data/app/~~sNcuhOLFwtB-nZjP6iJRNA==/com.google.android.webview-wyea3Y44NWbGbRddarRSAw==/base.apk!/lib/arm64-v8a:/data/app/~~xNbgRO-rLXYkt-8Wh3plnQ==/com.google.android.trichromelibrary_616716433-eGWjDUvFX1A0Lohkh9NPww==/base.apk!/lib/arm64-v8a, permitted_path=/data:/mnt/expand
2024-02-19 09:34:27.133  9065-9123  WebViewFactory          com.rncameratest                     I  Loading com.google.android.webview version 121.0.6167.164 (code 616716433)
2024-02-19 09:34:27.167  9065-9123  cr_WVCFactoryProvider   com.rncameratest                     I  Loaded version=121.0.6167.164 minSdkVersion=29 isBundle=true multiprocess=true packageId=2
2024-02-19 09:34:27.172  9065-9129  chromium                com.rncameratest                     E  [0219/093427.171739:ERROR:variations_seed_loader.cc(37)] Seed missing signature.
2024-02-19 09:34:27.172  9065-9129  chromium                com.rncameratest                     I  [0219/093427.172398:INFO:variations_seed_loader.cc(66)] Failed to open file for reading.: No such file or directory (2)
2024-02-19 09:34:27.178  9065-9123  cr_LibraryLoader        com.rncameratest                     I  Successfully loaded native library
2024-02-19 09:34:27.178  9065-9123  cr_CachingUmaRecorder   com.rncameratest                     I  Flushed 7 samples from 7 histograms, 0 samples were dropped.
2024-02-19 09:34:27.182  9065-9122  ReactNativeJS           com.rncameratest                     I  Running "RNCameraTest" with {"rootTag":11}
2024-02-19 09:34:27.183  9065-9132  TrafficStats            com.rncameratest                     D  tagSocket(135) with statsTag=0xffffffff, statsUid=-1
2024-02-19 09:34:27.185  9065-9133  TrafficStats            com.rncameratest                     D  tagSocket(137) with statsTag=0xffffffff, statsUid=-1
2024-02-19 09:34:27.356  9065-9122  Compatibil...geReporter com.rncameratest                     D  Compat change id reported: 206033068; UID 10162; state: ENABLED
2024-02-19 09:34:27.425  9065-9065  PreviewView             com.rncameratest                     I  Creating PreviewView...
2024-02-19 09:34:27.425  9065-9065  PreviewView             com.rncameratest                     I  PreviewView is 0x0, rendering 1080x1920 content (LANDSCAPE_LEFT). Resizing to: 0x0 (COVER)
2024-02-19 09:34:27.426  9065-9065  PreviewView             com.rncameratest                     I  Resize Mode changed: COVER -> CONTAIN
2024-02-19 09:34:27.426  9065-9065  CameraView              com.rncameratest                     I  Updating CameraSession...
2024-02-19 09:34:27.428  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Waiting for lock...
2024-02-19 09:34:27.429  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Updating CameraSession Configuration... Difference(deviceChanged=true, outputsChanged=true, sidePropsChanged=true, isActiveChanged=true)
2024-02-19 09:34:27.429  9065-9119  CameraSession           com.rncameratest                     I  Configuring inputs for CameraSession...
2024-02-19 09:34:27.429  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setInput(0)
2024-02-19 09:34:27.429  9065-9119  CameraSession           com.rncameratest                     I  Destroying previous outputs...
2024-02-19 09:34:27.429  9065-9119  CameraSession           com.rncameratest                     I  Creating outputs for Camera #0...
2024-02-19 09:34:27.430  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setOutputs([])
2024-02-19 09:34:27.430  9065-9119  CameraSession           com.rncameratest                     I  Successfully configured Session with 0 outputs for Camera #0!
2024-02-19 09:34:27.430  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setRepeatingRequest(...)
2024-02-19 09:34:27.431  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setIsActive(false)
2024-02-19 09:34:27.431  9065-9119  Persistent...ureSession com.rncameratest                     D  Configure() with isActive: false, ID: 0, device: null, session: null
2024-02-19 09:34:27.431  9065-9119  Persistent...ureSession com.rncameratest                     I  Creating new device...
2024-02-19 09:34:27.431  9065-9119  CameraManager           com.rncameratest                     I  Camera #0: Opening...
2024-02-19 09:34:27.434  9065-9123  CameraDevices           com.rncameratest                     I  Camera #0 is now unavailable.
2024-02-19 09:34:27.437  9065-9065  CameraView              com.rncameratest                     I  Updating CameraSession...
2024-02-19 09:34:27.439  9065-9065  PreviewView             com.rncameratest                     I  PreviewView is 1426x1736, rendering 1080x1920 content (LANDSCAPE_LEFT). Resizing to: 977x1736 (CONTAIN)
2024-02-19 09:34:27.440  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Waiting for lock...
2024-02-19 09:34:27.440  9065-9120  CameraManager           com.rncameratest                     I  Camera #0: Opened!
2024-02-19 09:34:27.441  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Completed CameraSession Configuration! (isActive: false, isRunning: false)
2024-02-19 09:34:27.441  9065-9119  CameraView              com.rncameratest                     I  invokeOnInitialized()
2024-02-19 09:34:27.441  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Updating CameraSession Configuration... Difference(deviceChanged=false, outputsChanged=false, sidePropsChanged=false, isActiveChanged=true)
2024-02-19 09:34:27.441  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setIsActive(false)
2024-02-19 09:34:27.441  9065-9119  Persistent...ureSession com.rncameratest                     D  Configure() with isActive: false, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@61379b4, session: null
2024-02-19 09:34:27.442  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Completed CameraSession Configuration! (isActive: true, isRunning: false)
2024-02-19 09:34:27.443  9065-9065  CameraSession           com.rncameratest                     I  PreviewView Surface created! Surface(name=null)/@0xa97d9dd
2024-02-19 09:34:27.443  9065-9065  CameraSession           com.rncameratest                     I  Setting Preview Output...
2024-02-19 09:34:27.443  9065-9065  CameraSession           com.rncameratest                     I  PreviewView Surface updated! Surface(name=null)/@0xa97d9dd 1920 x 1080
2024-02-19 09:34:27.443  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Waiting for lock...
2024-02-19 09:34:27.443  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Updating CameraSession Configuration... Difference(deviceChanged=false, outputsChanged=true, sidePropsChanged=true, isActiveChanged=true)
2024-02-19 09:34:27.443  9065-9119  CameraSession           com.rncameratest                     I  Destroying previous outputs...
2024-02-19 09:34:27.443  9065-9119  CameraSession           com.rncameratest                     I  Creating outputs for Camera #0...
2024-02-19 09:34:27.444  9065-9119  CameraSession           com.rncameratest                     I  Adding 1280x960 Preview Output...
2024-02-19 09:34:27.445  9065-9065  SurfaceHolder           com.rncameratest                     I  Resizing SurfaceHolder to 1280 x 960...
2024-02-19 09:34:27.455  9065-9065  PreviewView             com.rncameratest                     I  Surface Size changed: 1920x1080 -> 1280x960
2024-02-19 09:34:27.455  9065-9065  CameraSession           com.rncameratest                     I  PreviewView Surface updated! Surface(name=null)/@0xa97d9dd 1280 x 960
2024-02-19 09:34:27.455  9065-9065  SurfaceHolder           com.rncameratest                     I  Resized SurfaceHolder to 1280 x 960!
2024-02-19 09:34:27.462  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setOutputs([PREVIEW (1280 x 960)])
2024-02-19 09:34:27.462  9065-9119  CameraSession           com.rncameratest                     I  Successfully configured Session with 1 outputs for Camera #0!
2024-02-19 09:34:27.462  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setRepeatingRequest(...)
2024-02-19 09:34:27.462  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setIsActive(true)
2024-02-19 09:34:27.463  9065-9119  Persistent...ureSession com.rncameratest                     D  Configure() with isActive: true, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@61379b4, session: null
2024-02-19 09:34:27.463  9065-9119  Persistent...ureSession com.rncameratest                     I  Creating new session...
2024-02-19 09:34:27.464  9065-9119  CreateCaptureSession    com.rncameratest                     I  Camera #0: Creating Capture Session #1... (Hardware Level: 0 | Outputs: [PREVIEW (1280 x 960)])
2024-02-19 09:34:27.464  9065-9119  CreateCaptureSession    com.rncameratest                     I  Using new API (>=28)
2024-02-19 09:34:27.477  9065-9120  CreateCaptureSession    com.rncameratest                     I  Camera #0: Successfully created CameraCaptureSession #1!
2024-02-19 09:34:27.477  9065-9119  Persistent...ureSession com.rncameratest                     D  Updating repeating request...
2024-02-19 09:34:27.489  9065-9065  CameraSession           com.rncameratest                     I  PreviewView Surface destroyed! Surface(name=null)/@0xa97d9dd
2024-02-19 09:34:27.489  9065-9065  CameraSession           com.rncameratest                     I  Destroying Preview Output...
2024-02-19 09:34:27.489  9065-9065  CameraSession           com.rncameratest                     I  configure { ... }: Waiting for lock...
2024-02-19 09:34:27.492  9065-9119  Persistent...ureSession com.rncameratest                     D  Configure() done! isActive: true, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@61379b4, session: android.hardware.camera2.impl.CameraCaptureSessionImpl@3a6b0aa
2024-02-19 09:34:27.492  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Completed CameraSession Configuration! (isActive: true, isRunning: true)
2024-02-19 09:34:27.492  9065-9119  CameraView              com.rncameratest                     I  invokeOnStarted()
2024-02-19 09:34:27.492  9065-9065  CameraSession           com.rncameratest                     I  configure { ... }: Updating CameraSession Configuration... Difference(deviceChanged=false, outputsChanged=true, sidePropsChanged=true, isActiveChanged=true)
2024-02-19 09:34:27.492  9065-9065  CameraSession           com.rncameratest                     I  Destroying previous outputs...
2024-02-19 09:34:27.492  9065-9065  CameraView              com.rncameratest                     I  invokeOnStopped()
2024-02-19 09:34:27.492  9065-9065  CameraSession           com.rncameratest                     I  Creating outputs for Camera #0...
2024-02-19 09:34:27.493  9065-9065  Persistent...ureSession com.rncameratest                     D  --> setOutputs([])
2024-02-19 09:34:27.493  9065-9065  CameraSession           com.rncameratest                     I  Successfully configured Session with 0 outputs for Camera #0!
2024-02-19 09:34:27.493  9065-9065  Persistent...ureSession com.rncameratest                     D  --> setRepeatingRequest(...)
2024-02-19 09:34:27.493  9065-9065  Persistent...ureSession com.rncameratest                     D  --> setIsActive(false)
2024-02-19 09:34:27.493  9065-9065  Persistent...ureSession com.rncameratest                     D  Configure() with isActive: false, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@61379b4, session: null
2024-02-19 09:34:27.494  9065-9065  CameraSession           com.rncameratest                     I  configure { ... }: Completed CameraSession Configuration! (isActive: true, isRunning: false)
2024-02-19 09:34:27.494  9065-9065  CameraSession           com.rncameratest                     I  Preview Output destroyed!
2024-02-19 09:34:27.494  9065-9065  CameraView              com.rncameratest                     I  Updating CameraSession...
2024-02-19 09:34:27.494  9065-9065  CameraView              com.rncameratest                     I  Updating CameraSession...
2024-02-19 09:34:27.497  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Waiting for lock...
2024-02-19 09:34:27.497  9065-9119  CameraSession           com.rncameratest                     I  Nothing changed, aborting configure { ... }
2024-02-19 09:34:27.497  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Waiting for lock...
2024-02-19 09:34:27.497  9065-9119  CameraSession           com.rncameratest                     I  Nothing changed, aborting configure { ... }
2024-02-19 09:34:27.500  9065-9065  CameraSession           com.rncameratest                     I  PreviewView Surface created! Surface(name=null)/@0xa97d9dd
2024-02-19 09:34:27.500  9065-9065  CameraSession           com.rncameratest                     I  Setting Preview Output...
2024-02-19 09:34:27.500  9065-9065  CameraSession           com.rncameratest                     I  PreviewView Surface updated! Surface(name=null)/@0xa97d9dd 1280 x 960
2024-02-19 09:34:27.500  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Waiting for lock...
2024-02-19 09:34:27.500  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Updating CameraSession Configuration... Difference(deviceChanged=false, outputsChanged=true, sidePropsChanged=true, isActiveChanged=true)
2024-02-19 09:34:27.501  9065-9119  CameraSession           com.rncameratest                     I  Destroying previous outputs...
2024-02-19 09:34:27.501  9065-9119  CameraSession           com.rncameratest                     I  Creating outputs for Camera #0...
2024-02-19 09:34:27.502  9065-9119  CameraSession           com.rncameratest                     I  Adding 1280x960 Preview Output...
2024-02-19 09:34:27.510  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setOutputs([PREVIEW (1280 x 960)])
2024-02-19 09:34:27.510  9065-9119  CameraSession           com.rncameratest                     I  Successfully configured Session with 1 outputs for Camera #0!
2024-02-19 09:34:27.510  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setRepeatingRequest(...)
2024-02-19 09:34:27.510  9065-9119  Persistent...ureSession com.rncameratest                     D  --> setIsActive(true)
2024-02-19 09:34:27.510  9065-9119  Persistent...ureSession com.rncameratest                     D  Configure() with isActive: true, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@61379b4, session: null
2024-02-19 09:34:27.511  9065-9119  Persistent...ureSession com.rncameratest                     I  Creating new session...
2024-02-19 09:34:27.511  9065-9119  CreateCaptureSession    com.rncameratest                     I  Camera #0: Creating Capture Session #2... (Hardware Level: 0 | Outputs: [PREVIEW (1280 x 960)])
2024-02-19 09:34:27.512  9065-9119  CreateCaptureSession    com.rncameratest                     I  Using new API (>=28)
2024-02-19 09:34:27.935  9065-9081  BufferQueueProducer     com.rncameratest                     E  [SurfaceView[com.rncameratest/com.rncameratest.MainActivity]#2(BLAST Consumer)2](id:236900000002,api:4,p:461,c:9065) queueBuffer: BufferQueue has been abandoned
2024-02-19 09:34:27.941  9065-9120  CreateCaptureSession    com.rncameratest                     I  Camera #0: Successfully created CameraCaptureSession #2!
2024-02-19 09:34:27.941  9065-9119  Persistent...ureSession com.rncameratest                     D  Updating repeating request...
2024-02-19 09:34:27.944  9065-9119  Persistent...ureSession com.rncameratest                     D  Configure() done! isActive: true, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@61379b4, session: android.hardware.camera2.impl.CameraCaptureSessionImpl@240ab02
2024-02-19 09:34:27.944  9065-9119  CameraSession           com.rncameratest                     I  configure { ... }: Completed CameraSession Configuration! (isActive: true, isRunning: true)
2024-02-19 09:34:27.944  9065-9119  CameraView              com.rncameratest                     I  invokeOnStarted()
2024-02-19 09:34:27.946  9065-9120  CreateCaptureSession    com.rncameratest                     I  Camera #0: CameraCaptureSession #1 has been closed.
2024-02-19 09:34:27.946  9065-9120  Persistent...ureSession com.rncameratest                     I  Session android.hardware.camera2.impl.CameraCaptureSessionImpl@3a6b0aa closed!

Camera Device

{
  "formats": [],
  "sensorOrientation": "landscape-left",
  "hardwareLevel": "limited",
  "maxZoom": 10,
  "minZoom": 1,
  "maxExposure": 9,
  "supportsLowLightBoost": false,
  "neutralZoom": 1,
  "physicalDevices": [
    "telephoto-camera"
  ],
  "supportsFocus": true,
  "supportsRawCapture": false,
  "isMultiCam": false,
  "minFocusDistance": 0,
  "minExposure": -9,
  "name": "BACK (0)",
  "hasFlash": false,
  "hasTorch": false,
  "position": "back",
  "id": "0"
}

Device

Android Emulator (Pixel 7 Pro API 33), OnePlus 10R (CPH2411 Android 13))

VisionCamera Version

3.9.0

Can you reproduce this issue in the VisionCamera Example app?

Yes, I can reproduce the same issue in the Example app here

Additional information

@grevtsovna grevtsovna added the 🐛 bug Something isn't working label Feb 19, 2024
@carabj
Copy link

carabj commented Feb 19, 2024

We've also noticed this when running on Android emulator. On the emulator the preview is stretched and also the co-ordinates (when using the barcode scanner) is off in x. Only have one real Android device and there the preview is not stretched.

@Georg7
Copy link

Georg7 commented Feb 19, 2024

Same here. I have a stretched and zoomed preview on Android that makes it unusable.

"react-native-vision-camera": "3.9.0",
"expo": "~50.0.6",
const device = useCameraDevice("back");

const format = useCameraFormat(device, [{ photoResolution: "max" }]);

const focus = useCallback((point) => {
	const c = cameraRef.current;
	if (c == null) return;
	c.focus(point);
}, []);

const gesture = Gesture.Tap().onEnd(({ x, y }) => {
	runOnJS(setFocusPoint)({ x, y });
	runOnJS(focus)({ x, y });
});

const { props: cameraProps } = useBarcodeScanner({
	barcodeTypes: ["ean-13", "ean-8"],
	onBarcodeScanned: (barcodes) => {
		"worklet";
		updateBarcodesStateWorklet(barcodes);
	},
});

<GestureDetector gesture={gesture}>
	<Camera
		ref={cameraRef}
		photo={true}
		style={StyleSheet.absoluteFill}
		device={device}
		isActive={cameraIsActive}
		format={format}
		fps={30}
		{... cameraProps }
	/>
</GestureDetector>

On Android:
IMG_1247

On iOS
IMG_1248

@boiboif

This comment was marked as off-topic.

@Pelasua
Copy link

Pelasua commented Feb 19, 2024

I'm experiencing the same issue. I upgraded to version 3.9.0 hoping to address this problem: #2519

Previously, the stretching was vertical, but now it is horizontal.

@mrousavy
Copy link
Owner

  1. This is weird, on all my test devices (Samsung, Huawei, Google Pixel) the preview looks good. I can take another look but if the issue cannot be reproduced on my devices then I don't know what to do. If anyone of you guys wants to play around with the code in PreviewView.kt that would of course be a huge help.
  2. As mentioned in the first pinned issue here in this repo, orientation is not yet supported. It's quite a large effort to implement it, so I'm crowdfunding the effort. ✨ Implement Orientation ($3,000) #1891

@Pelasua
Copy link

Pelasua commented Feb 19, 2024

  1. This is weird, on all my test devices (Samsung, Huawei, Google Pixel) the preview looks good. I can take another look but if the issue cannot be reproduced on my devices then I don't know what to do. If anyone of you guys wants to play around with the code in PreviewView.kt that would of course be a huge help.
  2. As mentioned in the first pinned issue here in this repo, orientation is not yet supported. It's quite a large effort to implement it, so I'm crowdfunding the effort. ✨ Implement Orientation ($8,000) #1891

Sorry, I would like to help more with Kotlin, but I don't have any idea.

I've tried changing the resizeMode prop from 'cover' to 'contain,' and this is the result (picture). I don't know why I have these measurements (the container has 600 height x 300 width). Are these the default preview measurements? Anyway, the preview still shows a stretched capture.

Samsung Galaxy J6+

EDIT:
Ok, my sensorOrientation is always 'landscape-left' and I can't change it...

So @mrousavy this is not supported in this release?

image

@bruno-centanaro
Copy link

bruno-centanaro commented Feb 19, 2024

Hello. I've looked into the PreviewView.kt.
One thing I do not understand is why the CameraDeviceDetails.getMaximumPreviewSize() is used for the aspect ratio in getSize.
Using the contentAspectRatio instead of containerAspectRatio fixes the stretching issue on my galaxy S22, but I might be missing something and might not work on all phones, please let me know what you think Marc

@mrousavy
Copy link
Owner

@bruno-centanaro can you submit a PR? I can take a look and others can test this.

@mrousavy
Copy link
Owner

One thing I do not understand is why the CameraDeviceDetails.getMaximumPreviewSize() is used for the aspect ratio in getSize.

This is just the default value. It will be updated later by the surfaceChanged event where the actual Surface size gets assigned to PreviewView.size, causing onMeasure to re-calculate the aspect ratio (at least that's the plan).

@bruno-centanaro
Copy link

bruno-centanaro commented Feb 19, 2024

Sorry, I messed up, as for my first message, it was containerAspectRatio instead of contentAspectRatio and not vice-versa. Nevertheless now that i get the intended use I think that's correct
As for the surfaceChanged, you are correct it modifies the size variable but this is not causing the onMeasure to run again, at least on my phone.
The PR I can try to do it after work today, I'll link it here

@mrousavy
Copy link
Owner

As for the surfaceChanged, you are correct it modifies the size variable but this is not causing the onMeasure to run again, at least on my phone.

Interesting - I think this PR fixes that: #2588

@mrousavy
Copy link
Owner

I believe that the aspect ratio calculation is correct, are you sure that swapping the aspect ratios is right? Can you just quickly post your diff or what exactly you changed so I can take a look now?

Otherwise a PR after work is also much appreciated. Before and after screenshots are all I need

@bruno-centanaro
Copy link

bruno-centanaro commented Feb 19, 2024

That PR does cause the onMeasure to re-run, but it is strange because the preview is still stretched. This are the logs without my aspect ratio change

2024-02-19 10:19:08.709 26373-26373 PreviewView BUNDLE_ID I Creating PreviewView...
2024-02-19 10:19:08.710 26373-26373 PreviewView BUNDLE_ID I PreviewView is 0x0, rendering 1080x1920 content (LANDSCAPE_LEFT). Resizing to: 0x0 (COVER)
2024-02-19 10:19:08.878 26373-26373 SurfaceView@8057685 BUNDLE_ID I onWindowVisibilityChanged(0) true com.mrousavy.camera.core.PreviewView{8057685 V.E...... ......I. 0,0-0,0} of ViewRootImpl@a077172[MainActivity]
2024-02-19 10:19:08.883 26373-26373 PreviewView BUNDLE_ID I PreviewView is 1080x1440, rendering 1080x1920 content (LANDSCAPE_LEFT). Resizing to: 1080x1920 (COVER)
2024-02-19 10:19:08.931 26373-26373 SurfaceView@8057685 BUNDLE_ID I surfaceCreated 2 #8 com.mrousavy.camera.core.PreviewView{8057685 V.E...... ......ID 0,-240-1080,1680}
2024-02-19 10:19:08.931 26373-26373 CameraSession BUNDLE_ID I PreviewView Surface created! Surface(name=null)/@0xf56b2aa
2024-02-19 10:19:08.932 26373-26373 SurfaceView@8057685 BUNDLE_ID I surfaceChanged (1920,1080) 2 #8 com.mrousavy.camera.core.PreviewView{8057685 V.E...... ......ID 0,-240-1080,1680}
2024-02-19 10:19:08.932 26373-26373 PreviewView BUNDLE_ID I Surface changed: 1920 x 1080
2024-02-19 10:19:08.932 26373-26373 CameraSession BUNDLE_ID I PreviewView Surface updated! Surface(name=null)/@0xf56b2aa 1920 x 1080
2024-02-19 10:19:09.101 26373-26373 PreviewView BUNDLE_ID I Input Orientation changed: LANDSCAPE_LEFT -> LANDSCAPE_RIGHT
2024-02-19 10:19:09.120 26373-26373 PreviewView BUNDLE_ID I PreviewView is 1080x1920, rendering 1080x1920 content (LANDSCAPE_RIGHT). Resizing to: 1080x1920 (COVER)
2024-02-19 10:19:09.311 26373-26373 PreviewView BUNDLE_ID I PreviewView is 1080x1920, rendering 1080x1920 content (LANDSCAPE_RIGHT). Resizing to: 1080x1920 (COVER)
2024-02-19 10:19:09.311 26373-26373 BLASTBufferQueue_Java BUNDLE_ID I update, w= 640 h= 480 mName = null mNativeObject= 0xb400007d19803210 sc.mNativeObject= 0xb400007c4962f9d0 format= 4 caller= android.view.SurfaceView.setBufferSize:1432 android.view.SurfaceView.performSurfaceTransaction:988 android.view.SurfaceView.updateSurface:1204 android.view.SurfaceView.setFrame:559 android.view.View.layout:25731 com.mrousavy.camera.core.PreviewView.requestLayout$lambda$1:100
2024-02-19 10:19:09.313 26373-26373 SurfaceView@8057685 BUNDLE_ID I surfaceChanged (640,480) 3 #5 com.mrousavy.camera.core.PreviewView{8057685 V.E...... ......I. 0,-240-1080,1680}
2024-02-19 10:19:09.313 26373-26373 PreviewView BUNDLE_ID I Surface changed: 640 x 480
2024-02-19 10:19:09.313 26373-26373 PreviewView BUNDLE_ID I Surface Size changed: 1920x1080 -> 640x480
2024-02-19 10:19:09.313 26373-26373 CameraSession BUNDLE_ID I PreviewView Surface updated! Surface(name=null)/@0xf56b2aa 640 x 480
2024-02-19 10:19:09.324 26373-26373 PreviewView BUNDLE_ID I PreviewView is 1080x1920, rendering 480x640 content (LANDSCAPE_RIGHT). Resizing to: 1440x1920 (COVER)

I'm not sure if swapping the aspect ratio's is the correct way to do it, it works on my phone. This is the code

private fun getSize(contentSize: Size, containerSize: Size, resizeMode: ResizeMode): Size {
    val contentAspectRatio = contentSize.width.toDouble() / contentSize.height
    val containerAspectRatio = containerSize.width.toDouble() / containerSize.height

    val widthOverHeight = when (resizeMode) {
      ResizeMode.COVER -> contentAspectRatio > containerAspectRatio
      ResizeMode.CONTAIN -> contentAspectRatio < containerAspectRatio
    }

    Log.i(TAG, "Content Aspect Ratio: $contentAspectRatio, Container Aspect Ratio: $containerAspectRatio widthOverHeight: $widthOverHeight ($resizeMode)")

    return if (widthOverHeight) {
      // Scale by width to cover height
      val scaledWidth = containerSize.height * containerAspectRatio
      Size(scaledWidth.roundToInt(), containerSize.height)
    } else {
      val scaledHeight = if (containerAspectRatio.isNaN()) containerSize.width / contentAspectRatio else containerSize.width / containerAspectRatio
      Log.i(TAG, "Scaled Height: $scaledHeight, containerSize: $containerSize, contentAspectRatio: $contentAspectRatio")
      Size(containerSize.width, scaledHeight.roundToInt())
    }
  }

@mrousavy
Copy link
Owner

Uhm well this code:

val scaledWidth = containerSize.height * contentAspectRatio
val scaledWidth = containerSize.height * containerAspectRatio
Size(scaledWidth.roundToInt(), containerSize.height)

Effectively does nothing, it's the same as

containerSize

(1080 / 1920 * 1080 = 1920, so both width and height always stay the same values as before)

And then the second part:

val scaledHeight = if (containerAspectRatio.isNaN()) containerSize.width / contentAspectRatio else containerSize.width / containerAspectRatio

containerAspectRatio could be NaN on the first render, true, in that case I think an early return makes more sense though.

@bruno-centanaro
Copy link

Yes, to be honest the widthOverHeight I did not test it as its false for me

@bglgwyng
Copy link
Sponsor Contributor

I tried this PR #2588, but the preview is still stretched.

@swamywiz
Copy link

swamywiz commented Feb 20, 2024

For me, we were using two aspect ratio, 4:3 and 16:9, 16:9 doesn't show any stretching issue, but I do notice issue in case of 4:3. Tested on oneplus Nord, back camera

@robertyulisman
Copy link

image

there is update for this, i am still get this issue, sometime when i reload after save, the preview is normally, when go back to previous page and open camera again, this happen again

@robertyulisman
Copy link

image
this is normal preview

@seavan
Copy link

seavan commented Feb 20, 2024

@bruno-centanaro @mrousavy

I have the same issue with landscape stretching, and this is what helped me (since 3.7.1). The issue still persists on 3.9.0.

diff --git a/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt b/node_modules/react-      native-vision-camera/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt                                                            index ba3c94b..f2b140b 100644
--- a/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt
+++ b/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt
@@ -105,7 +105,7 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) :
       Size(scaledWidth.roundToInt(), containerSize.height)
     } else {
       // Scale by height to cover width
-      val scaledHeight = containerSize.width / contentAspectRatio
+      val scaledHeight = containerSize.width * contentAspectRatio
       Size(containerSize.width, scaledHeight.roundToInt())
     }
   }

I think division operator here is not correct, it should be multiplication.

@bruno-centanaro
Copy link

The operators there are correct I think. For anyone who has issues and is sure the aspect ratio of the camera container is the same as the resolution's one this works for me

index ba3c94b..cc19356 100644
--- a/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt
+++ b/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt
@@ -94,6 +94,10 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) :
     val contentAspectRatio = contentSize.width.toDouble() / contentSize.height
     val containerAspectRatio = containerSize.width.toDouble() / containerSize.height
 
+    if (!(contentAspectRatio > 0 && containerAspectRatio > 0)) {
+      return contentSize
+    }
+
     val widthOverHeight = when (resizeMode) {
       ResizeMode.COVER -> contentAspectRatio > containerAspectRatio
       ResizeMode.CONTAIN -> contentAspectRatio < containerAspectRatio
@@ -101,11 +105,11 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) :
 
     return if (widthOverHeight) {
       // Scale by width to cover height
-      val scaledWidth = containerSize.height * contentAspectRatio
+      val scaledWidth = containerSize.height * containerAspectRatio
       Size(scaledWidth.roundToInt(), containerSize.height)
     } else {
       // Scale by height to cover width
-      val scaledHeight = containerSize.width / contentAspectRatio
+      val scaledHeight = containerSize.width / containerAspectRatio
       Size(containerSize.width, scaledHeight.roundToInt())
     }
   }

Please make sure the aspect ratio's are the same otherwise I don't think that will work

@swamywiz
Copy link

The operators there are correct I think. For anyone who has issues and is sure the aspect ratio of the camera container is the same as the resolution's one this works for me

index ba3c94b..cc19356 100644
--- a/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt
+++ b/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt
@@ -94,6 +94,10 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) :
     val contentAspectRatio = contentSize.width.toDouble() / contentSize.height
     val containerAspectRatio = containerSize.width.toDouble() / containerSize.height
 
+    if (!(contentAspectRatio > 0 && containerAspectRatio > 0)) {
+      return contentSize
+    }
+
     val widthOverHeight = when (resizeMode) {
       ResizeMode.COVER -> contentAspectRatio > containerAspectRatio
       ResizeMode.CONTAIN -> contentAspectRatio < containerAspectRatio
@@ -101,11 +105,11 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) :
 
     return if (widthOverHeight) {
       // Scale by width to cover height
-      val scaledWidth = containerSize.height * contentAspectRatio
+      val scaledWidth = containerSize.height * containerAspectRatio
       Size(scaledWidth.roundToInt(), containerSize.height)
     } else {
       // Scale by height to cover width
-      val scaledHeight = containerSize.width / contentAspectRatio
+      val scaledHeight = containerSize.width / containerAspectRatio
       Size(containerSize.width, scaledHeight.roundToInt())
     }
   }

Please make sure the aspect ratio's are the same otherwise I don't think that will work

Tested this patch, this resolves the issue we were having with 4:3 aspect ratio.

@Georg7
Copy link

Georg7 commented Feb 20, 2024

The operators there are correct I think. For anyone who has issues and is sure the aspect ratio of the camera container is the same as the resolution's one this works for me

index ba3c94b..cc19356 100644
--- a/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt
+++ b/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt
@@ -94,6 +94,10 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) :
     val contentAspectRatio = contentSize.width.toDouble() / contentSize.height
     val containerAspectRatio = containerSize.width.toDouble() / containerSize.height
 
+    if (!(contentAspectRatio > 0 && containerAspectRatio > 0)) {
+      return contentSize
+    }
+
     val widthOverHeight = when (resizeMode) {
       ResizeMode.COVER -> contentAspectRatio > containerAspectRatio
       ResizeMode.CONTAIN -> contentAspectRatio < containerAspectRatio
@@ -101,11 +105,11 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) :
 
     return if (widthOverHeight) {
       // Scale by width to cover height
-      val scaledWidth = containerSize.height * contentAspectRatio
+      val scaledWidth = containerSize.height * containerAspectRatio
       Size(scaledWidth.roundToInt(), containerSize.height)
     } else {
       // Scale by height to cover width
-      val scaledHeight = containerSize.width / contentAspectRatio
+      val scaledHeight = containerSize.width / containerAspectRatio
       Size(containerSize.width, scaledHeight.roundToInt())
     }
   }

Please make sure the aspect ratio's are the same otherwise I don't think that will work

Tried this on a Samsung Galaxy (A04e) but the preview remains stretched and zoomed.

Samsung Galaxy (A04e)
IMG_1253

iPhone 14 Pro
IMG_1252

@bruno-centanaro
Copy link

It seems as your container aspect ratio might not be the same as the video preview (set on the format prop)

@Georg7
Copy link

Georg7 commented Feb 21, 2024

It seems as your container aspect ratio might not be the same as the video preview (set on the format prop)

I believe it is the same. Here is how I set it up:

const device = useCameraDevice("back");

const screen = Dimensions.get("screen");

const format = useCameraFormat(device, [
	{ targetPhotoAspectRatio: screen.height / screen.width },
	{ autoFocusSystem: "phase-detection" },
	{ photoResolution: "max" },
	{ fps: 30 },
]);
<Camera
	ref={cameraRef}
	photo={true}
	style={StyleSheet.absoluteFill}
	device={device}
	isActive={cameraIsActive}
	format={format}
/>

@bruno-centanaro
Copy link

The aspect ratio of the preview is the same as video, not the picture one, also the fact that you use an aspect ratio in the format does not necessarily mean it is supported by the camera, maybe try console logging the format to check

@vanhoutk
Copy link

containerAspectRatio

This seems to have sorted the issue for me, was occurring on a Fairphone 4 when my camera preview was not the full size of my screen

@Georg7
Copy link

Georg7 commented Feb 22, 2024

The aspect ratio of the preview is the same as video, not the picture one, also the fact that you use an aspect ratio in the format does not necessarily mean it is supported by the camera, maybe try console logging the format to check

Here is what I've tried:

const screen = Dimensions.get("screen");
const device = useCameraDevice("back");

const format = useCameraFormat(device, [
	{ photoWidth: screen.width },
	{ photoHeight: screen.height },
	{ videoHeight: screen.height },
	{ videoWidth: screen.width },
	{ autoFocusSystem: "phase-detection" },
	{ photoResolution: "max" },
	{ fps: 30 },
]);

Is this the correct/ideal way to set the format wrt to width and height?

Logging the format to the console :

{
	autoFocusSystem: "contrast-detection",
	fieldOfView: 81.19526233755766,
	maxFps: 30,
	maxISO: 1600,
	maxZoom: 10,
	minFps: 1,
	minISO: 100,
	photoHeight: 3120,
	photoWidth: 4160,
	pixelFormats: ["yuv", "native"],
	supportsDepthCapture: false,
	supportsPhotoHdr: false,
	supportsVideoHdr: false,
	videoHeight: 1440,
	videoStabilizationModes: ["off", "standard", "off"],
	videoWidth: 1920,
}

No idea why the photo and video dimensions are not the same.

When I manually reset the width or height on the camera once it's mounted, the preview renders correctly:

<Camera
	ref={cameraRef}
	photo={true}
	style={StyleSheet.absoluteFill} // <-- commenting this out to manually reset
	// style={{ width: screen.width, height: screen.height }} <-- uncommenting this to manually reset
	device={device}
	isActive={cameraIsActive}
	format={format}
/>

But it never renders correctly on the initial mount. Tried it with @swamywiz's batch and without (same behaviour).

@nica0012
Copy link

nica0012 commented Mar 8, 2024

Hey folks, I have been keeping up with the past few updates but i cant seem to get the preview to be the same as the capture result (works fine on IOS, testing with Samsung A14 device)

My preview is either 1:1 Square or 4:3 so it is dynamic but no matter what the zoom is always slightly zoomed in compared to the result. I am using v 3.9.1 currently to test.

trim.10AEA28A-0997-44EC-BBB2-9802E37FED75.MOV

@Kaszmir
Copy link

Kaszmir commented Mar 11, 2024

Hi, guys, are you going to fix this issue with stretched preview in this version? without that this version is basically useless. I believe that the JS hacks are not the solution and the problem should be solved on the native side. Thanks for your commitment.

@boiboif
Copy link

boiboif commented Mar 11, 2024

I downgraded the version to 2.16.8, which solved all the stretch issues and also supported landscape mode.

@lucksp
Copy link

lucksp commented Mar 12, 2024

I am seeing this since updating from version "3.6.4"

@WesleyMaciel2510
Copy link

Guys, I found out something insteresting. You can test if you want.

You simply use Dimensions.get instead of 'absoluteFill':
const {width, height} = Dimensions.get('screen');

<Camera
//style={StyleSheet.absoluteFill}
style={{width: width, height: height }}
device={device}
isActive={true}
ref={camera}
photo={true}
/>

Now I reload the screen and the error persist. But when I change some value for 'width' or 'height'.
For example, I change to style={{width: width, height: height-1 }} and save.
Now it fix the problem:

Before:
image
Later:
image

Does someone knows the solution?
Also, how can I diff the node modules as said before?

diff --git a/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/CameraDeviceDetails.kt b/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/CameraDeviceDetails.kt
index a589c26..91f5b8c 100644
--- a/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/CameraDeviceDetails.kt
+++ b/node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/core/CameraDeviceDetails.kt

@WesleyMaciel2510
Copy link

2.16.8

I tried, got the error:
FAILURE: Build failed with an exception.

  • Where:
    Build file 'D:\Personal Data\Code\Mobile\node_modules\react-native-vision-camera\android\build.gradle' line: 354

  • What went wrong:
    A problem occurred evaluating project ':react-native-vision-camera'.

Cannot invoke method replace() on null object

@WesleyMaciel2510
Copy link

After hours testing, the version that worked for me is: "react-native-vision-camera": "3.8",
If you are stuck, please downgrade the version to 3.8 before anything more complex.

@Rc85
Copy link

Rc85 commented Mar 16, 2024

The only workaround I am able to accomplish right now is store the started state and apply the width and height once it has started.

const CameraContainer = () => {
  const { width, height } = useWindowDimensions();
  const device = useCameraDevice('back');
  const [started, setStarted] = useState(fales);

  // you'll need this if you're rendering Camera based on a state
  useEffect(() => {
    return () => {
      if (!open) setStarted(false);
    }
  }, [open]); // could be a global state

  return <Camera
    isActive
    device={device}
    style={{ width: started ? width : 0, height: started ? height : 0 }}
    onStarted={() => setStarted(true)}
  />
}

If you're keeping the CameraContainer around instead of conditionally rendering it, add a useEffect that returns a function to set started to false.

@mrousavy
Copy link
Owner

Hey everybody! I just released a new V4 beta (v4.0.0-beta.7) where I fixed a bunch of issues! 💪🚀 Can you test that and see if that fixes the issue for you? 😅

yarn add react-native-vision-camera@beta

You might need to increase the compileSdk to the newest Android SDK (34) if you are behind.

@mlecoq
Copy link

mlecoq commented Mar 19, 2024

On my samsung tab I have still some stretching / zoom issues

It depends on the ratio of the preview:

  • with a ratio 1, the preview is stretched with front camera (back camera looks fine)
  • with a ratio 0.625, no stretching issue but the taken picture is zoomed compared to the preview

I am forcing aspect ratio for camera format

  const format = useCameraFormat(device, [
    {
      photoAspectRatio: aspectRatio,
      videoAspectRatio: aspectRatio,
    },
  ]);

But I have no more rotated pictures with front camera

@mlecoq
Copy link

mlecoq commented Mar 19, 2024

On my redmi I have no issue with ratio 1, only 0.625 returns me a zoomed-in captured image

@programminPete
Copy link

programminPete commented Mar 19, 2024

Hey everybody! I just released a new V4 beta (v4.0.0-beta.7) where I fixed a bunch of issues! 💪🚀 Can you test that and see if that fixes the issue for you? 😅

yarn add react-native-vision-camera@beta

You might need to increase the compileSdk to the newest Android SDK (34) if you are behind.

Hi @mrousavy, On the good news side, the android preview stretching that I saw on 3.9.1 looks seems resolved for me on the new beta build.
But on the bad news side, I am using it for barcode scanning capability (code-39). I have upgraded to the beta version (4.0.0-beta.8). It resolves the stretched view, but seems to not scan at all now for android.
As a side-note, I tested the both versions on iOS and both 3.9.1 and 4.0.0-beta.8 work as expected for both scanning and the general camera view behavior.

As 4.0.0 is a major version update, is there anything I may be missing as far as an api change from 3.9.1 that I might need to know? I'm assuming not, if it's working properly on iOS

I can provide more code, but the basic usage I have is the following:

  const codeScanner = useCodeScanner({
    codeTypes: ['code-39'],
    onCodeScanned: codes => {
    // additional code, doesn't seem to enter
 }
 })
 ...
          <Camera
            ref={camera}
            style={stlyes.cameraPreview}
            device={device}
            codeScanner={codeScanner}
            isActive={true}
            photo={true}
            onError={handleError}
            torch={torchEnabled ? 'on' : 'off'}
          />

@maxxcs
Copy link

maxxcs commented Mar 20, 2024

Hey everybody! I just released a new V4 beta (v4.0.0-beta.7) where I fixed a bunch of issues! 💪🚀 Can you test that and see if that fixes the issue for you? 😅

yarn add react-native-vision-camera@beta

You might need to increase the compileSdk to the newest Android SDK (34) if you are behind.

I was about to test it in this version, but i got this error if I use <Camera orientation="landscape-right" />.

androidx.camera.core.impl.utils.CameraOrientationUtil.surfaceRotationToDegrees
CameraOrientationUtil.java, line 97
java.lang.IllegalArgumentException: Unsupported surface rotation: 270

androidx.camera.core.impl.utils.CameraOrientationUtil.surfaceRotationToDegrees CameraOrientationUtil.java:97
androidx.camera.camera2.internal.Camera2CameraInfoImpl.getSensorRotationDegrees Camera2CameraInfoImpl.java:210
androidx.camera.core.UseCase.getRelativeRotation UseCase.java:483
androidx.camera.core.UseCase.getRelativeRotation UseCase.java:472
androidx.camera.core.ImageCapture.takePictureInternal ImageCapture.java:1302
androidx.camera.core.ImageCapture.takePicture ImageCapture.java:863
androidx.camera.core.ImageCapture.lambda$takePicture$2$androidx-camera-core-ImageCapture ImageCapture.java:860
androidx.camera.core.ImageCapture$$ExternalSyntheticLambda1.run
android.os.Handler.handleCallback Handler.java:942
android.os.Handler.dispatchMessage Handler.java:99
android.os.Looper.loopOnce Looper.java:201
android.os.Looper.loop Looper.java:288
android.app.ActivityThread.main ActivityThread.java:7872
java.lang.reflect.Method.invoke Method.java
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:548
com.android.internal.os.ZygoteInit.main ZygoteInit.java:936

@lucksp
Copy link

lucksp commented Mar 20, 2024

Anyone here using Expo with Android SDK (34)?

@iagoandrei
Copy link

Hey everybody! I just released a new V4 beta (v4.0.0-beta.7) where I fixed a bunch of issues! 💪🚀 Can you test that and see if that fixes the issue for you? 😅

yarn add react-native-vision-camera@beta

You might need to increase the compileSdk to the newest Android SDK (34) if you are behind.

I was about to test it in this version, but i got this error if I use <Camera orientation="landscape-right" />.

androidx.camera.core.impl.utils.CameraOrientationUtil.surfaceRotationToDegrees
CameraOrientationUtil.java, line 97
java.lang.IllegalArgumentException: Unsupported surface rotation: 270

androidx.camera.core.impl.utils.CameraOrientationUtil.surfaceRotationToDegrees CameraOrientationUtil.java:97
androidx.camera.camera2.internal.Camera2CameraInfoImpl.getSensorRotationDegrees Camera2CameraInfoImpl.java:210
androidx.camera.core.UseCase.getRelativeRotation UseCase.java:483
androidx.camera.core.UseCase.getRelativeRotation UseCase.java:472
androidx.camera.core.ImageCapture.takePictureInternal ImageCapture.java:1302
androidx.camera.core.ImageCapture.takePicture ImageCapture.java:863
androidx.camera.core.ImageCapture.lambda$takePicture$2$androidx-camera-core-ImageCapture ImageCapture.java:860
androidx.camera.core.ImageCapture$$ExternalSyntheticLambda1.run
android.os.Handler.handleCallback Handler.java:942
android.os.Handler.dispatchMessage Handler.java:99
android.os.Looper.loopOnce Looper.java:201
android.os.Looper.loop Looper.java:288
android.app.ActivityThread.main ActivityThread.java:7872
java.lang.reflect.Method.invoke Method.java
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:548
com.android.internal.os.ZygoteInit.main ZygoteInit.java:936

Same here

@rodgomesc
Copy link
Contributor

rodgomesc commented Mar 25, 2024

@iagoandrei @maxxcs sent a fix for the Unsupported surface rotation can you guys check if it works for you?

#2683

one thing i'm really confuse is that this thread is about a "Preview stretched", the issue you guys reported is only reproduced on my side when i take a picture and orientation is other than the default value.

you should be able to validate the stretching thing for the preview without take a picture or any other action, what i'm missing here? is the preview ok for you?

@mrousavy
Copy link
Owner

Hey @programminPete - I just fixed that code scanning bug in latest V4 beta! :)

Anyways - great to hear that V4 now works perfectly! If you appreciate my work, please consider 💖 sponsoring me on GitHub 💖 so I can keep maintaining this library, fixing bugs and building new features! :)

@stefoid
Copy link

stefoid commented Mar 25, 2024

Sorry, late to this - Im completely buried in other issues right now.

Can I ask are you aware of / have fixed, the issue that I brought up in this thread above, where the field of view of the Preview screen is more narrow than the field of view of the resulting image? Its not stretching of the preview image, but more like clipping 10% of the width of either side

@mlecoq
Copy link

mlecoq commented Mar 26, 2024

@stefoid I have created a separated issue: #2690

Let me know if you are talking about the same issue

@programminPete
Copy link

Morning @mrousavy . Seems to be working now, thanks!
I added sponsor payment :)

@mrousavy
Copy link
Owner

Thanks @programminPete! much appreciated! :)

@n-ii-ma
Copy link
Contributor

n-ii-ma commented Apr 15, 2024

I'm using class component Tired of trying and trying workarounds, version changes, debugging.. Sure that after the first rendering all works well.. Switch on caveman mode:

added this style in the Camera component:

    style={{
        ...StyleSheet.absoluteFill,
        width: Dimensions.get('screen').width,
        height: Dimensions.get('screen').height + this.state.update,
      }}

and this in componentDidMount:

    let context = this;
    setTimeout(function () {
      context.setState({update: 1});
    }, 500);

In a functional component:

const [update, doUpdate] = useState(0);

return (
  <Camera
      ref={cameraRef}
      onInitialized={() => doUpdate(1)}
      style={[StyleSheet.absoluteFill, { width: width + update }]}

This is the best way to solve this issue at the moment.

// Screen width
const WIDTH = Dimensions.get("screen").width;

const Cam = () => {
  // Camera width hack
  const [updatedWidth, setUpdatedWidth] = useState(1);

  return (
    <Camera
      ...
      onInitialized={() => setUpdatedWidth(0)}
      style={[StyleSheet.absoluteFill, { width: WIDTH + updatedWidth }]}
    />
  );
};

export default Cam;

@n-ii-ma
Copy link
Contributor

n-ii-ma commented Apr 15, 2024

Hey @programminPete - I just fixed that code scanning bug in latest V4 beta! :)

Anyways - great to hear that V4 now works perfectly! If you appreciate my work, please consider 💖 sponsoring me on GitHub 💖 so I can keep maintaining this library, fixing bugs and building new features! :)

Can you please apply the fix to the current stable release as well?

With all due respect, this is a serious annoying situation and should be fixed in the current stable major version; not a beta one!
Most people installing this package will not install the beta one right away and will have to spend a lot of time debugging this issue.

@Dingenis
Copy link

@n-ii-ma I get your frustration, however do realise that this is basically a hobby project. We are incredibly lucky that we can use such a library and therefore have a very good camera experience with so little effort. There is so much what goes into building and maintaining a project like this, and @mrousavy is basically doing it by himself and for free for the most of us (which is kind of insane if you ask me, pls don't make this project private @mrousavy 😅😂). I think you should adjust your expectations according to that perspective, which is also mentioned in the README.md: "VisionCamera is provided as is, I work on it in my free time."

You do mention a good point that it can be frustrating for new people coming to the project, since this issue might be a bit hard to find. Maybe a solution for now could be to add a "Known issues" section to the "Troubleshooting" docs so that user might find this issue more easily. Maybe you could do a proposal to add such a thing?

@mrousavy
Copy link
Owner

Thanks for the nice words @Dingenis

@n-ii-ma with all due respect, I'm assuming you didn't check out the actual change/commit and the diff, but basically the entire architecture is rebuilt from scratch. I use a completely different Camera engine now under the hood.
This cannot be backported.

should be fixed in the current stable major version; not a beta one!

The whole point of the beta version is to update and improve the library. That's why it's the latest beta. If you want the fix, get the beta. On main it is still broken as you experienced, because I just fixed it in the beta.
I'm guessing you (and other users) just "want it now", but this is not how releases work - I fixed it in a new version and released a beta so you can all try this.

Also, if you really want a fix for the current stable you could pay me to fix it for you. I am no longer on V3 myself, I am on V4 already with my apps.

@lucksp
Copy link

lucksp commented May 1, 2024

This is the best way to solve this issue at the moment.

// Screen width
const WIDTH = Dimensions.get("screen").width;

const Cam = () => {
  // Camera width hack
  const [updatedWidth, setUpdatedWidth] = useState(1);

  return (
    <Camera
      ...
      onInitialized={() => setUpdatedWidth(0)}
      style={[StyleSheet.absoluteFill, { width: WIDTH + updatedWidth }]}
    />
  );
};

export default Cam;

After all the attempts to fix on Android, this is the only one that worked.

On v4.0.1

@wuvinotre
Copy link

I had similar problems with "torch" as well, but this only happened after the stack navigation, I believe that the real problem lies in this "process" and not in the vision-camera.
When I use the vision-camera on single screens, everything works perfectly.
That said, thank you very much for the work you're doing with vision-camera @mrousavy

@pke
Copy link

pke commented May 3, 2024

side question related to this issue: are the scan event coordinates normalized to the react coordinate system in 4.0 @mrousavy?

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