Skip to content

Ultra-wide-angle effect on Android physical device using React Native and QuickPose AI #3

@crm33287-arch

Description

@crm33287-arch

After unsuccessful attempts to find a solution to this problem, I decided to raise the issue.

The problem is that the camera from the QuickPose AI package on an Android device stretches the camera mirror vertically.

For reproduce the issue I share the code:

MainApplication.kt

package com.dzenapp

import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.soloader.OpenSourceMergedSoMapping
import com.facebook.soloader.SoLoader
import com.dzenapp.quickpose.QuickPosePackage

class MainApplication : Application(), ReactApplication {

  override val reactNativeHost: ReactNativeHost =
    object : DefaultReactNativeHost(this) {
      override fun getPackages(): List<ReactPackage> =
        PackageList(this).packages.apply {
          // Manually add packages that aren't autolinked
          add(QuickPosePackage())
        }

      override fun getJSMainModuleName() = "index"
      override fun getUseDeveloperSupport() = BuildConfig.DEBUG
      override val isNewArchEnabled = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
      override val isHermesEnabled = BuildConfig.IS_HERMES_ENABLED
    }

  override val reactHost: ReactHost
    get() = getDefaultReactHost(applicationContext, reactNativeHost)

  override fun onCreate() {
    super.onCreate()
    SoLoader.init(this, OpenSourceMergedSoMapping)
    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
      load()
    }
  }
}

QuickPosePackage.kt

package com.dzenapp.quickpose

import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager

class QuickPosePackage : ReactPackage {
  override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
    emptyList()

  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> =
    listOf(QuickPoseViewManager())
}

QuickPoseViewManager.kt

package com.dzenapp.quickpose

import android.util.Log
import androidx.annotation.Nullable
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.annotations.ReactProp

class QuickPoseViewManager : ViewGroupManager<QuickPoseView>() {

  companion object {
    const val REACT_CLASS = "QuickPoseView"
    const val CMD_UPDATE_FROM_MANAGER = 1
    const val CMD_CLEANUP = 2
    private const val TAG = "QuickPoseBridge"

  }

  override fun getName() = REACT_CLASS

  override fun createViewInstance(reactContext: ThemedReactContext): QuickPoseView {
    return QuickPoseView(reactContext)
  }

  @ReactProp(name = "pose")
  fun setPose(view: QuickPoseView, pose: String) {
    view.pose = pose
    view.update()
  }

  override fun getCommandsMap() = mapOf(
    "updateFromManager" to CMD_UPDATE_FROM_MANAGER,
    "cleanup" to CMD_CLEANUP
  )

  override fun receiveCommand(view: QuickPoseView, commandId: Int, args: ReadableArray?) {
    when (commandId) {
      CMD_UPDATE_FROM_MANAGER -> {
        val pose = args?.getArray(0)?.getString(0) ?: ""
        view.pose = pose
        view.update()
      }
      CMD_CLEANUP -> view.cleanup()
    }
  }

  override fun getExportedCustomDirectEventTypeConstants() = mapOf(
    "onUpdate" to mapOf("registrationName" to "onUpdate")
  )
}

And piece of code which is responsible for drawing of quickpose camera:

import ai.quickpose.camera.QuickPoseCameraSwitchView

private fun ensureCameraView() {
        if (switchView != null) return
        val qp = quickPose ?: return

        val target = Size(1080, 1920)
        val v = QuickPoseCameraSwitchView(context, qp, null, 0, target)
        addView(v, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
        switchView = v

        post { fixPreviewZIssues(v) }

        if (!cameraStarted) {
            val useFront = QuickPoseCameraWrapper.isFrontCameraActive()
            viewScope.launch {
                try {
                    val ar = v.start(useFront)
                    cameraStarted = true
                    previewAspect = ar
                    post {
                        fixPreviewZIssues(v)
                        applyCenterCropToAllSurfaces(v, previewAspect, viewZoom)
                    }
                    overlayView?.setPreviewAspect(ar, mirrorX = useFront)
                } catch (_: Throwable) {}
            }
        }
    }

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions