mrousavy / react-native-vision-camera

📸 A powerful, high-performance React Native Camera library.
https://react-native-vision-camera.com
MIT License
6.72k stars 1k forks source link

🐛 Preview looks stretched on Android #2583

Closed grevtsovna closed 2 months ago

grevtsovna commented 3 months ago

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

carabj commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

My situation is that there is no stretching in the simulator, but it will stretch in the actual machine (landscape mode).

Pelasua commented 3 months ago

I'm experiencing the same issue. I upgraded to version 3.9.0 hoping to address this problem: https://github.com/mrousavy/react-native-vision-camera/pull/2519

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

mrousavy commented 3 months ago
  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. https://github.com/mrousavy/react-native-vision-camera/issues/1891
Pelasua commented 3 months ago
  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 commented 3 months ago

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 commented 3 months ago

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

mrousavy commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

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: https://github.com/mrousavy/react-native-vision-camera/pull/2588

mrousavy commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

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

bglgwyng commented 3 months ago

I tried this PR https://github.com/mrousavy/react-native-vision-camera/pull/2588, but the preview is still stretched.

swamywiz commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

image this is normal preview

seavan commented 3 months ago

@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 commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

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

Georg7 commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago
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 commented 3 months ago

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).

stevenmathers commented 3 months ago

Hi @mrousavy

I have an issue where the preview image is slightly more zoomed in than the captured image, in one axis only. For instance if I am taking a portrait image, the preview is , lets say, 20% less field of view in the horizontal axis than the resultant image. And if I rotate to landscape, then the field of view of the preview is less in the vertical axis.

This seems consistent across versions that I have tried from 3.6.4 -> 3.8.2

The mode is set to 'contain' and I have tried various styles such as absoluteFill, and an absolute top, left, width, height to ensure there is a large margin around the preview area to ensure the view is not running off the edge of the screen somehow

This appears to be device specific. Some android devices have the issue, but my iphone SE does not

Is there a trick I am missing?

jhau commented 3 months ago

@stevenmathers I have the same issue but it happens in both axes. Tried on 3 android devices (2 Xiaomi, 1 Pixel), this does not happen on any iOS device.

stevenmathers commented 3 months ago

@jhau are you sure its both axis? thats weird if so

stevenmathers commented 3 months ago

update, this appears to be android only, and I really think its only in one axis - horizontal, regardless of what orientation you are holding the device. And it does not affect the android emulator, presuambly some implemntation issue of the emulator as opposed to a physical camera. the 1st image of the pair shows the preview window, and the second is the actual image returned from the camera. NOTE: as I said, the image is not being drawn off the screen. even if I reduce the window size so that it is less than the screen dimenstions, the same thing occurs screenshot_20240223-112905_720 image-20240223112900_720 screenshot_20240223-113022_720 image-20240223113014_720

Pelasua commented 3 months ago

Well, after conducting multiple tests, this is the trick I propose:

Play with re-renders. I mean, if you set a negligible size initially for the camera component, and after 1 second, you update it to the full size of the container, it seems that the re-render corrects the issue.

 const [sizeWithDelay, setSizeWithDelay] = useState<ViewStyle>({
    width: 1,
    height: 1,
  });

  useLayoutEffect(() => {
    !photo &&
      setTimeout(() => {
        setSizeWithDelay({
          width: '100%',
          height: '100%',
        });
      }, 1000);

    return () => {
      photo &&
        setSizeWithDelay({
          width: 1,
          height: 1,
        });
    };
  }, [photo]);

And in the component:

<Camera
            ref={camera}
            photo={true}
            style={[
              styles.camera,
              { height: sizeWithDelay.height, width: sizeWithDelay.width },
            ]}
            .../>

Note that if you leave the sizes at 0, it doesn't work well, which is why I had to set it to 1.

What I do is, if there's no photo, I use the preview and give it a 100% width and height, but it reverts to 1 if we already have the photo.

Depending on the delay set by the developer, it might be better to include some type of activity indicator to enhance the user experience or not.

I'm sure there's a more correct way to implement it, and I'm open to improvements until the error is fixed. I hope it also helps identify why the problem might be occurring.

Samsung Galaxy J6+: image image

mlecoq commented 3 months ago

the sizeWithDelay helps me for stretch issue on redmi but I had also to modify the native code to have a correct preview (on samsung device)

see patch below

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
@@ -47,6 +47,13 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, val cameraId

       return if (isHighResScreen) display1080p else displaySize
     }
+
+    fun getActualPreviewSize(): Size {
+      return Size(
+        Resources.getSystem().displayMetrics.widthPixels,
+        Resources.getSystem().displayMetrics.heightPixels
+      )
+    }
   }

   val characteristics by lazy { cameraManager.getCameraCharacteristics(cameraId) }
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..c2b7335 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
@@ -20,7 +20,7 @@ import kotlinx.coroutines.withContext
 class PreviewView(context: Context, callback: SurfaceHolder.Callback) :
   SurfaceView(context),
   SurfaceHolder.Callback {
-  var size: Size = CameraDeviceDetails.getMaximumPreviewSize()
+  var size: Size = CameraDeviceDetails.getActualPreviewSize()
     set(value) {
       if (field != value) {
         Log.i(TAG, "Surface Size changed: $field -> $value")
@@ -92,11 +92,11 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) :

   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 containerAspectRatio = if(containerSize.height > 0) containerSize.width.toDouble() / containerSize.height else 0

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

     return if (widthOverHeight) {
vipul-azilen commented 3 months ago

@mrousavy Facing the same issue preview stretching with the following version details:

"react": "18.2.0",
"react-native": "0.73.5",
"react-native-reanimated": "^3.6.1",
"react-native-vision-camera": "^3.9.0",

IMG_3768 IMG_3769

stefoid commented 3 months ago

the sizeWithDelay helps me for stretch issue on redmi but I had also to modify the native code to have a correct preview (on samsung device)

see patch below

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
@@ -47,6 +47,13 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, val cameraId

       return if (isHighResScreen) display1080p else displaySize
     }
+
+    fun getActualPreviewSize(): Size {
+      return Size(
+        Resources.getSystem().displayMetrics.widthPixels,
+        Resources.getSystem().displayMetrics.heightPixels
+      )
+    }
   }

   val characteristics by lazy { cameraManager.getCameraCharacteristics(cameraId) }
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..c2b7335 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
@@ -20,7 +20,7 @@ import kotlinx.coroutines.withContext
 class PreviewView(context: Context, callback: SurfaceHolder.Callback) :
   SurfaceView(context),
   SurfaceHolder.Callback {
-  var size: Size = CameraDeviceDetails.getMaximumPreviewSize()
+  var size: Size = CameraDeviceDetails.getActualPreviewSize()
     set(value) {
       if (field != value) {
         Log.i(TAG, "Surface Size changed: $field -> $value")
@@ -92,11 +92,11 @@ class PreviewView(context: Context, callback: SurfaceHolder.Callback) :

   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 containerAspectRatio = if(containerSize.height > 0) containerSize.width.toDouble() / containerSize.height else 0

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

     return if (widthOverHeight) {

I am using 3.8.2 because 3.9 seems buggy in different ways (timing out trying to take photos on android device) I refactored this patch for 3.8.2 and it doesnt work, but some weird new behaviour occurs -> for a moment, the preview looks like it is the proper width (in terms of field of view) but possibly it is stretched (wrong aspect ratio?), then it snaps to the same aspect ratio/field of view which is the same as my original issue -> the field of view of the preview is less horizontally than the captured image. any thoughts?

mlecoq commented 3 months ago

You're right, I thought it was fixing my issue (did you set photoAspectRatio in useFormat hook too) but it was worse in fact

xHeinrich commented 3 months ago

Getting a similar issue to whats being described above on a moto e22i. I tried the patch in https://github.com/mrousavy/react-native-vision-camera/pull/2588 which didnt resolve the issue. The preview is stretched but only in landscape, portrait seems fine. Replicatable on the latest ShadowLense app version. Actual image capture is fine. In 3.8.2 this isn't an issue. Not sure if related to #1891 given it seems fine in previous versions.

Screenshot_20240229-012013 Screenshot_20240229-012022

AfanasievN commented 3 months ago

Same issue persists

frenbergFNX commented 2 months ago

On 3.9.1 still have the issue on some android devices, tried the hack with adjusting the style using the onInitialized hook and that is a usable work around.

logs below from when using the hack.

16:52:55.788  I  Creating PreviewView...
16:52:55.788  I  PreviewView is 0x0, rendering 1415x720 content (LANDSCAPE_LEFT). Resizing to: 1415x720 (COVER)
16:52:55.790  I  Updating CameraSession...
16:52:55.791  I  configure { ... }: Waiting for lock...
16:52:55.792  I  configure { ... }: Updating CameraSession Configuration... Difference(deviceChanged=true, outputsChanged=true, sidePropsChanged=true, isActiveChanged=true)
16:52:55.792  I  Configuring inputs for CameraSession...
16:52:55.792  D  --> setInput(0)
16:52:55.792  I  Destroying previous outputs...
16:52:55.793  I  Creating outputs for Camera #0...
16:52:55.797  I  Adding 4032x1908 Photo Output in JPEG...
16:52:55.799  I  Adding 1920x912 Video Output in YUV_420_888...
16:52:55.799  I  Initializing 1920 x 912 Video Pipeline (format: YUV)
16:52:55.799  I  Using ImageReader round-trip (format: #35)
16:52:55.799  I  Creating ImageReader with default usage flags...
16:52:55.799  I  Creating ImageWriter with format #35...
16:52:55.800  D  --> setOutputs([PHOTO (4032x1908 in JPEG), VIDEO (1920x912 in YUV)])
16:52:55.800  I  Successfully configured Session with 2 outputs for Camera #0!
16:52:55.800  I  Updating Video Outputs...
16:52:55.800  I  Removing RecordingSession Output...
16:52:55.800  D  --> setRepeatingRequest(...)
16:52:55.800  D  --> setIsActive(false)
16:52:55.800  D  Configure() with isActive: false, ID: 0, device: null, session: null
16:52:55.800  I  Creating new device...
16:52:55.800  I  Camera #0: Opening...
16:52:55.812  I  postSingleUpdate device: camera id 0 status STATUS_NOT_AVAILABLE
16:52:55.813  I  Camera 0 facing CAMERA_FACING_BACK state now CAMERA_STATE_OPEN for client se.fnx.powerup.acce API Level 2
16:52:55.813  I  Camera #0 is now unavailable.
16:52:55.826  I  Camera #0: Opened!
16:52:55.826  I  Updating CameraSession...
16:52:55.826  I  Creating new session...
16:52:55.827  I  onWindowVisibilityChanged(0) true com.mrousavy.camera.core.PreviewView{f168b99 V.E...... ......ID -707,-360-708,360} of ViewRootImpl@543e7a3[MainActivity]
16:52:55.827  I  Camera #0: Creating Capture Session #35... (Hardware Level: 1 | Outputs: [PHOTO (4032x1908 in JPEG), VIDEO (1920x912 in YUV)])
16:52:55.828  I  Using new API (>=28)
16:52:55.833  I  PreviewView is 720x1490, rendering 1415x720 content (LANDSCAPE_LEFT). Resizing to: 2928x1490 (COVER)
16:52:55.844  I  Relayout returned: old=(0,0,720,1520) new=(0,0,720,1520) req=(720,1520)0 dur=8 res=0x1 s={true 479177400320} ch=false
16:52:55.855  I  surfaceCreated 2 #8 com.mrousavy.camera.core.PreviewView{f168b99 V.E...... ......ID -1104,0-1824,1490}
16:52:55.855  I  PreviewView Surface created! Surface(name=null)/@0x8643be
16:52:55.855  I  Setting Preview Output...
16:52:55.855  I  surfaceChanged (720,1415) 2 #8 com.mrousavy.camera.core.PreviewView{f168b99 V.E...... ......ID -1104,0-1824,1490}
16:52:55.855  I  PreviewView Surface updated! Surface(name=null)/@0x8643be 720 x 1415
16:52:55.860  I  doUpdatePositionAsync is called and callVoidMethod
16:52:55.892  I  doUpdatePositionAsync is called and callVoidMethod
16:52:55.924  D  Sending lifecycle 2 to service
16:52:55.925  D  Activity backgrounding at 12606912
16:52:55.930  D  unregisterListener ::   
16:52:55.937  W  A resource failed to call release. 
16:52:55.938  I  configure { ... }: Waiting for lock...
16:52:55.938  I  Camera #0: Successfully created CameraCaptureSession #35!
16:52:55.938  I  configure { ... }: Waiting for lock...
16:52:55.939  D  Stopping repeating request...
16:52:55.939  D  Configure() done! isActive: false, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@5851b0f, session: android.hardware.camera2.impl.CameraCaptureSessionImpl@485479c
16:52:55.939  I  configure { ... }: Completed CameraSession Configuration! (isActive: false, isRunning: false)
16:52:55.939  I  invokeOnInitialized()
16:52:55.939  D  Finding view 7553...
16:52:55.940  D  Found view 7553!
16:52:55.940  I  configure { ... }: Updating CameraSession Configuration... Difference(deviceChanged=false, outputsChanged=false, sidePropsChanged=false, isActiveChanged=true)
16:52:55.940  D  --> setIsActive(false)
16:52:55.940  D  Configure() with isActive: false, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@5851b0f, session: android.hardware.camera2.impl.CameraCaptureSessionImpl@485479c
16:52:55.942  I  doUpdatePositionAsync is called and callVoidMethod
16:52:55.942  D  Stopping repeating request...
16:52:55.942  D  Configure() done! isActive: false, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@5851b0f, session: android.hardware.camera2.impl.CameraCaptureSessionImpl@485479c
16:52:55.942  I  configure { ... }: Completed CameraSession Configuration! (isActive: true, isRunning: false)
16:52:55.943  I  configure { ... }: Updating CameraSession Configuration... Difference(deviceChanged=false, outputsChanged=true, sidePropsChanged=true, isActiveChanged=true)
16:52:55.943  I  Destroying previous outputs...
16:52:55.943  I  Closing 4032x1908 PHOTO ImageReader..
16:52:55.943  I  Closing 1920x912 Video Pipeline..
16:52:55.947  I  Creating outputs for Camera #0...
16:52:55.951  I  Adding 4032x1908 Photo Output in JPEG...
16:52:55.953  I  Adding 1920x912 Video Output in YUV_420_888...
16:52:55.953  I  Initializing 1920 x 912 Video Pipeline (format: YUV)
16:52:55.954  I  Using ImageReader round-trip (format: #35)
16:52:55.954  I  Creating ImageReader with default usage flags...
16:52:55.954  I  Creating ImageWriter with format #35...
16:52:55.954  I  doUpdatePositionAsync is called and callVoidMethod
16:52:55.958  I  Adding 1280x720 Preview Output...
16:52:55.959  I  Resizing SurfaceHolder to 1280 x 720...
16:52:55.969  I  surfaceChanged (1280,720) 3 #8 com.mrousavy.camera.core.PreviewView{f168b99 V.E...... ......I. -1104,0-1824,1490}
16:52:55.969  I  Surface Size changed: 720x1415 -> 1280x720
16:52:55.969  I  PreviewView Surface updated! Surface(name=null)/@0x8643be 1280 x 720
16:52:55.969  I  Resized SurfaceHolder to 1280 x 720!
16:52:55.986  I  doUpdatePositionAsync is called and callVoidMethod
16:52:55.987  I  PreviewView is 2928x1490, rendering 720x1280 content (LANDSCAPE_LEFT). Resizing to: 2928x5205 (COVER)
16:52:55.991  D  --> setOutputs([PHOTO (4032x1908 in JPEG), VIDEO (1920x912 in YUV), PREVIEW (1280 x 720)])
16:52:55.991  I  Successfully configured Session with 3 outputs for Camera #0!
16:52:55.991  I  Updating Video Outputs...
16:52:55.991  I  Removing RecordingSession Output...
16:52:55.991  D  --> setRepeatingRequest(...)
16:52:55.991  D  --> setIsActive(true)
16:52:55.991  D  Configure() with isActive: true, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@5851b0f, session: null
16:52:55.997  I  Creating new session...
16:52:55.998  I  doUpdatePositionAsync is called and callVoidMethod
16:52:55.998  I  PreviewView is 2928x1490, rendering 720x1280 content (LANDSCAPE_LEFT). Resizing to: 2928x5205 (COVER)
16:52:55.999  I  Camera #0: Creating Capture Session #36... (Hardware Level: 1 | Outputs: [PHOTO (4032x1908 in JPEG), VIDEO (1920x912 in YUV), PREVIEW (1280 x 720)])
16:52:56.002  I  Using new API (>=28)
16:52:56.002  I  Camera #0: CameraCaptureSession #35 has been closed.
16:52:56.002  I  Session android.hardware.camera2.impl.CameraCaptureSessionImpl@485479c closed!
16:52:56.010  I  doUpdatePositionAsync is called and callVoidMethod
16:52:56.010  I  MSG_WINDOW_FOCUS_CHANGED 0 1
16:52:56.011  D  prepareNavigationBarInfo() DecorView@374ecbe[MainActivity]
16:52:56.011  D  getNavigationBarColor() -855310
16:52:56.020  I  doUpdatePositionAsync is called and callVoidMethod
16:52:56.053  I  doUpdatePositionAsync is called and callVoidMethod
16:52:56.054  I  Updating CameraSession...
16:52:56.054  I  PreviewView is 722x1490, rendering 720x1280 content (LANDSCAPE_LEFT). Resizing to: 838x1490 (COVER)
16:52:56.061  I  Camera #0: Successfully created CameraCaptureSession #36!
16:52:56.061  I  configure { ... }: Waiting for lock...
16:52:56.061  D  Updating repeating request...
16:52:56.070  D  Configure() done! isActive: true, ID: 0, device: android.hardware.camera2.impl.CameraDeviceImpl@5851b0f, session: android.hardware.camera2.impl.CameraCaptureSessionImpl@ba9745d
16:52:56.070  I  doUpdatePositionAsync is called and callVoidMethod
16:52:56.071  I  configure { ... }: Completed CameraSession Configuration! (isActive: true, isRunning: true)
16:52:56.071  I  invokeOnStarted()
16:52:56.072  I  Nothing changed, aborting configure { ... }
16:52:56.086  I  doUpdatePositionAsync is called and callVoidMethod
16:52:56.107  I  stopped(false) old=false
16:52:56.111  D  Sending lifecycle 1 to service
16:52:56.111  D  Activity foregrounding at 12607099.
16:52:56.116  D  registerListener :: 1, LSM6DSO Acceleration Sensor, 66667, 0,  
16:52:56.119  I  MSG_WINDOW_FOCUS_CHANGED 1 1
16:52:56.119  D  prepareNavigationBarInfo() DecorView@374ecbe[MainActivity]
16:52:56.119  D  getNavigationBarColor() -855310
16:52:56.121  W  Couldn't connect to "ws://localhost:8081/message?device=SM-G973F%20-%2010%20-%20API%2029&app=se.fnx.powerup.acce&clientid=BridgeDevSupportManager", will silently retry
16:52:56.124  I  Relayout returned: old=(0,0,720,1520) new=(0,0,720,1520) req=(720,1520)0 dur=2 res=0x1 s={true 479177400320} ch=false
16:52:56.172  I  Relayout returned: old=(0,0,720,1520) new=(0,0,720,1520) req=(720,1520)0 dur=3 res=0x1 s={true 479177400320} ch=false
16:52:56.372  I  Camera 0 facing CAMERA_FACING_BACK state now CAMERA_STATE_ACTIVE for client se.fnx.powerup.acce API Level 2
16:52:56.391  I  ImageReader::onImageAvailable!
16:52:56.426  I  ImageReader::onImageAvailable!
xHeinrich commented 2 months ago

Example of the code in react-native-camera, it takes into account the current screen orientation. When the screen is in landscape it flips the divide and multiply calculation. In RN Vision Camera its static I think(assumes you're always portrait) no matter the rotation passed via the prop. Flipping the calculation if your camera is in landscape fixes the issue, at least on my test device.

https://github.com/react-native-camera/react-native-camera/blob/master/android/src/main/java/org/reactnative/camera/RNCameraView.java#L231-L247

https://github.com/mrousavy/react-native-vision-camera/blob/main/package/android/src/main/java/com/mrousavy/camera/core/PreviewView.kt#L116-L124

    return if(inputOrientation == Orientation.LANDSCAPE_LEFT || inputOrientation == Orientation.LANDSCAPE_RIGHT) {
      if (widthOverHeight) {
        // Scale by width to cover height
        val scaledWidth = containerSize.height / contentAspectRatio
        Size(scaledWidth.roundToInt(), containerSize.height)
      } else {
        // Scale by height to cover width
        val scaledHeight = containerSize.width * contentAspectRatio
        Size(containerSize.width, scaledHeight.roundToInt())
      }
    } else {
      if (widthOverHeight) {
        // Scale by width to cover height
        val scaledWidth = containerSize.height * contentAspectRatio
        Size(scaledWidth.roundToInt(), containerSize.height)
      } else {
        // Scale by height to cover width
        val scaledHeight = containerSize.width / contentAspectRatio
        Size(containerSize.width, scaledHeight.roundToInt())
      }
    }
vincenzoiacovone commented 2 months ago

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 }]}
nica0012 commented 2 months ago

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.

https://github.com/mrousavy/react-native-vision-camera/assets/8635153/980d38d0-bec2-4d3c-b3db-9655199a7eef

Kaszmir commented 2 months ago

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 commented 2 months ago

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

lucksp commented 2 months ago

I am seeing this since updating from version "3.6.4"

WesleyMaciel2510 commented 2 months ago

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 commented 2 months ago

2.16.8

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

WesleyMaciel2510 commented 2 months ago

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 commented 2 months ago

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.