react-native-nitro-pose-exercises 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,9 @@
1
1
  package com.margelo.nitro.nitroposeexercises
2
2
 
3
3
  import android.graphics.Bitmap
4
- import android.graphics.Matrix
5
4
  import androidx.annotation.Keep
6
5
  import com.facebook.proguard.annotations.DoNotStrip
7
- import com.google.mediapipe.framework.image.BitmapImageBuilder
6
+ import com.google.mediapipe.framework.image.MediaImageBuilder
8
7
  import com.google.mediapipe.tasks.core.BaseOptions
9
8
  import com.google.mediapipe.tasks.vision.core.RunningMode
10
9
  import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarker
@@ -12,7 +11,7 @@ import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarkerOptions
12
11
  import com.margelo.nitro.NitroModules
13
12
  import com.margelo.nitro.core.Promise
14
13
  import com.margelo.nitro.camera.HybridFrameSpec
15
- import com.margelo.nitro.camera.NativeFrame
14
+ import com.margelo.nitro.camera.`public`.NativeFrame
16
15
  import kotlin.math.acos
17
16
  import kotlin.math.max
18
17
  import kotlin.math.min
@@ -156,59 +155,66 @@ class HybridPoseExercise : HybridNitroPoseExercisesSpec() {
156
155
  // Frame Processing
157
156
  // ═══════════════════════════════════════════════════════════
158
157
 
159
- override fun processFrame(frame: HybridFrameSpec) {
158
+ override fun processFrame(frame: HybridFrameSpec) {
160
159
  if (_status != SessionStatus.ACTIVE && _status != SessionStatus.COUNTDOWN) return
161
160
  if (!isInitialized || poseLandmarker == null) return
162
161
 
163
- // Cast to NativeFrame to get the ImageProxy
164
- val nativeFrame = frame as? NativeFrame ?: return
165
- val imageProxy = nativeFrame.image ?: return
166
-
167
162
  frameCount++
168
163
  if (frameCount % processEveryNFrames != 0) return
169
164
 
170
- try {
171
- // Convert ImageProxy to Bitmap
172
- val bitmap = imageProxyToBitmap(imageProxy)
173
- val mpImage = BitmapImageBuilder(bitmap).build()
174
-
175
- val result = poseLandmarker!!.detect(mpImage)
176
-
177
- if (result.landmarks().isNotEmpty()) {
178
- val poseLandmarks = result.landmarks()[0]
179
-
180
- if (poseWasLost) {
181
- poseWasLost = false
182
- onPoseRegained?.invoke()
183
- }
165
+ val nativeFrame = frame as? NativeFrame ?: return
166
+ val imageProxy = nativeFrame.image ?: return
184
167
 
185
- _landmarks = poseLandmarks.map { lm ->
186
- Landmark(
187
- x = lm.x().toDouble(),
188
- y = lm.y().toDouble(),
189
- z = lm.z().toDouble(),
190
- visibility = (lm.visibility().orElse(0f)).toDouble()
191
- )
192
- }.toTypedArray()
193
-
194
- if (_status == SessionStatus.ACTIVE) {
195
- processExerciseLogic()
196
- }
168
+ try {
169
+ val bitmapBuffer = Bitmap.createBitmap(
170
+ imageProxy.width,
171
+ imageProxy.height,
172
+ Bitmap.Config.ARGB_8888
173
+ )
197
174
 
198
- } else {
199
- if (!poseWasLost) {
200
- poseWasLost = true
201
- onPoseLost?.invoke()
175
+ // Use MediaPipe's BitmapImageBuilder
176
+ imageProxy.use {
177
+ val mpImage = com.google.mediapipe.framework.image.MediaImageBuilder(
178
+ imageProxy.image!!
179
+ ).build()
180
+
181
+ val result = poseLandmarker!!.detect(mpImage)
182
+
183
+ if (result.landmarks().isNotEmpty()) {
184
+ val poseLandmarks = result.landmarks()[0]
185
+
186
+ if (poseWasLost) {
187
+ poseWasLost = false
188
+ onPoseRegained?.invoke()
189
+ }
190
+
191
+ _landmarks = poseLandmarks.map { lm ->
192
+ Landmark(
193
+ x = lm.x().toDouble(),
194
+ y = lm.y().toDouble(),
195
+ z = lm.z().toDouble(),
196
+ visibility = (lm.visibility().orElse(0f)).toDouble()
197
+ )
198
+ }.toTypedArray()
199
+
200
+ if (_status == SessionStatus.ACTIVE) {
201
+ processExerciseLogic()
202
+ }
203
+ } else {
204
+ if (!poseWasLost) {
205
+ poseWasLost = true
206
+ onPoseLost?.invoke()
207
+ }
208
+ _landmarks = emptyArray()
209
+ }
202
210
  }
203
- _landmarks = emptyArray()
204
- }
205
211
 
206
- bitmap.recycle()
212
+ bitmapBuffer.recycle()
207
213
 
208
214
  } catch (e: Exception) {
209
- // MediaPipe detection failed — skip this frame
215
+ // MediaPipe detection failed — skip this frame
210
216
  }
211
- }
217
+ }
212
218
 
213
219
  // ═══════════════════════════════════════════════════════════
214
220
  // ImageProxy to Bitmap conversion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-pose-exercises",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Real-time on-device exercise tracking for React Native. Rep counting, form validation, and skeleton overlay powered by MediaPipe Pose Landmarker and VisionCamera v5 via Nitro Modules.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",