react-native-nitro-pose-exercises 1.0.4 → 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
@@ -34,7 +34,6 @@ target_sources(
34
34
  ../nitrogen/generated/android/nitroposeexercisesOnLoad.cpp
35
35
  # Shared Nitrogen C++ sources
36
36
  ../nitrogen/generated/shared/c++/HybridNitroPoseExercisesSpec.cpp
37
- ../nitrogen/generated/shared/c++/HybridWorkletQueueFactorySpec.cpp
38
37
  # Android-specific Nitrogen C++ sources
39
38
  ../nitrogen/generated/android/c++/JHybridNitroPoseExercisesSpec.cpp
40
39
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-pose-exercises",
3
- "version": "1.0.4",
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",
@@ -1,22 +0,0 @@
1
- ///
2
- /// HybridWorkletQueueFactorySpec.cpp
3
- /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
- /// https://github.com/mrousavy/nitro
5
- /// Copyright © Marc Rousavy @ Margelo
6
- ///
7
-
8
- #include "HybridWorkletQueueFactorySpec.hpp"
9
-
10
- namespace margelo::nitro::camera::worklets {
11
-
12
- void HybridWorkletQueueFactorySpec::loadHybridMethods() {
13
- // load base methods/properties
14
- HybridObject::loadHybridMethods();
15
- // load custom methods/properties
16
- registerHybrids(this, [](Prototype& prototype) {
17
- prototype.registerHybridMethod("wrapThreadInQueue", &HybridWorkletQueueFactorySpec::wrapThreadInQueue);
18
- prototype.registerHybridMethod("getCurrentThreadMarker", &HybridWorkletQueueFactorySpec::getCurrentThreadMarker);
19
- });
20
- }
21
-
22
- } // namespace margelo::nitro::camera::worklets
@@ -1,66 +0,0 @@
1
- ///
2
- /// HybridWorkletQueueFactorySpec.hpp
3
- /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
- /// https://github.com/mrousavy/nitro
5
- /// Copyright © Marc Rousavy @ Margelo
6
- ///
7
-
8
- #pragma once
9
-
10
- #if __has_include(<NitroModules/HybridObject.hpp>)
11
- #include <NitroModules/HybridObject.hpp>
12
- #else
13
- #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
- #endif
15
-
16
- // Forward declaration of `HybridNativeThreadSpec` to properly resolve imports.
17
- namespace margelo::nitro::camera { class HybridNativeThreadSpec; }
18
-
19
- #include "JSIConverter+AsyncQueue.hpp"
20
- #include <memory>
21
- #include <VisionCamera/HybridNativeThreadSpec.hpp>
22
-
23
- namespace margelo::nitro::camera::worklets {
24
-
25
- using namespace margelo::nitro;
26
-
27
- /**
28
- * An abstract base class for `WorkletQueueFactory`
29
- * Inherit this class to create instances of `HybridWorkletQueueFactorySpec` in C++.
30
- * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.
31
- * @example
32
- * ```cpp
33
- * class HybridWorkletQueueFactory: public HybridWorkletQueueFactorySpec {
34
- * public:
35
- * HybridWorkletQueueFactory(...): HybridObject(TAG) { ... }
36
- * // ...
37
- * };
38
- * ```
39
- */
40
- class HybridWorkletQueueFactorySpec: public virtual HybridObject {
41
- public:
42
- // Constructor
43
- explicit HybridWorkletQueueFactorySpec(): HybridObject(TAG) { }
44
-
45
- // Destructor
46
- ~HybridWorkletQueueFactorySpec() override = default;
47
-
48
- public:
49
- // Properties
50
-
51
-
52
- public:
53
- // Methods
54
- virtual std::shared_ptr<::worklets::AsyncQueue> wrapThreadInQueue(const std::shared_ptr<margelo::nitro::camera::HybridNativeThreadSpec>& thread) = 0;
55
- virtual double getCurrentThreadMarker() = 0;
56
-
57
- protected:
58
- // Hybrid Setup
59
- void loadHybridMethods() override;
60
-
61
- protected:
62
- // Tag for logging
63
- static constexpr auto TAG = "WorkletQueueFactory";
64
- };
65
-
66
- } // namespace margelo::nitro::camera::worklets