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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions