react-native-nitro-pose-exercises 1.1.2 → 1.1.3
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.
- package/android/CMakeLists.txt +7 -0
- package/android/src/main/cpp/frame_helper.cpp +37 -0
- package/android/src/main/java/com/margelo/nitro/nitroposeexercises/FrameHelper.kt +12 -0
- package/android/src/main/java/com/margelo/nitro/nitroposeexercises/NitroPoseExercises.kt +5 -21
- package/ios/NitroPoseExercises.swift +2 -2
- package/package.json +1 -1
package/android/CMakeLists.txt
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#include <jni.h>
|
|
2
|
+
#include <android/hardware_buffer_jni.h>
|
|
3
|
+
|
|
4
|
+
extern "C"
|
|
5
|
+
JNIEXPORT jobject JNICALL
|
|
6
|
+
Java_com_margelo_nitro_nitroposeexercises_FrameHelper_hardwareBufferToBitmap(
|
|
7
|
+
JNIEnv *env,
|
|
8
|
+
jclass clazz,
|
|
9
|
+
jlong pointer
|
|
10
|
+
) {
|
|
11
|
+
AHardwareBuffer *buffer = reinterpret_cast<AHardwareBuffer *>(pointer);
|
|
12
|
+
if (!buffer) return nullptr;
|
|
13
|
+
|
|
14
|
+
// Convert AHardwareBuffer* to Java HardwareBuffer
|
|
15
|
+
jobject hardwareBuffer = AHardwareBuffer_toHardwareBuffer(env, buffer);
|
|
16
|
+
if (!hardwareBuffer) return nullptr;
|
|
17
|
+
|
|
18
|
+
// Call Bitmap.wrapHardwareBuffer(hardwareBuffer, null) to create a hardware-backed Bitmap
|
|
19
|
+
jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
|
|
20
|
+
jmethodID wrapMethod = env->GetStaticMethodID(
|
|
21
|
+
bitmapClass,
|
|
22
|
+
"wrapHardwareBuffer",
|
|
23
|
+
"(Landroid/hardware/HardwareBuffer;Landroid/graphics/ColorSpace;)Landroid/graphics/Bitmap;"
|
|
24
|
+
);
|
|
25
|
+
jobject hwBitmap = env->CallStaticObjectMethod(bitmapClass, wrapMethod, hardwareBuffer, nullptr);
|
|
26
|
+
if (!hwBitmap) return nullptr;
|
|
27
|
+
|
|
28
|
+
// Copy to a software ARGB_8888 Bitmap (ML Kit needs software bitmap)
|
|
29
|
+
jclass configClass = env->FindClass("android/graphics/Bitmap$Config");
|
|
30
|
+
jfieldID argbField = env->GetStaticFieldID(configClass, "ARGB_8888", "Landroid/graphics/Bitmap$Config;");
|
|
31
|
+
jobject argbConfig = env->GetStaticObjectField(configClass, argbField);
|
|
32
|
+
|
|
33
|
+
jmethodID copyMethod = env->GetMethodID(bitmapClass, "copy", "(Landroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;");
|
|
34
|
+
jobject softBitmap = env->CallObjectMethod(hwBitmap, copyMethod, argbConfig, JNI_FALSE);
|
|
35
|
+
|
|
36
|
+
return softBitmap;
|
|
37
|
+
}
|
|
@@ -190,34 +190,21 @@ class HybridPoseExercise : HybridNitroPoseExercisesSpec() {
|
|
|
190
190
|
// Frame Processing (ML Kit — async with cached results)
|
|
191
191
|
// ═══════════════════════════════════════════════════════════
|
|
192
192
|
|
|
193
|
-
|
|
193
|
+
override fun processFrame(frame: HybridFrameSpec) {
|
|
194
194
|
if (_status != SessionStatus.ACTIVE && _status != SessionStatus.COUNTDOWN) return
|
|
195
195
|
if (!isInitialized || poseDetector == null) return
|
|
196
196
|
|
|
197
|
-
// Frame throttle
|
|
198
197
|
frameCount++
|
|
199
198
|
if (frameCount % processEveryNFrames != 0) return
|
|
200
199
|
|
|
201
200
|
try {
|
|
202
|
-
// Get raw buffer from VisionCamera frame
|
|
203
201
|
val nativeBuffer = frame.getNativeBuffer()
|
|
204
|
-
val
|
|
205
|
-
val height = frame.getHeight()
|
|
206
|
-
val bytesPerRow = frame.getBytesPerRow()
|
|
207
|
-
|
|
208
|
-
// Create Bitmap from the native buffer
|
|
209
|
-
val buffer = java.nio.ByteBuffer.allocateDirect(height * bytesPerRow)
|
|
210
|
-
val pointer = nativeBuffer.pointer
|
|
211
|
-
// Copy from native pointer to ByteBuffer
|
|
212
|
-
NativeBufferHelper.copyToByteBuffer(pointer, buffer, height * bytesPerRow)
|
|
213
|
-
|
|
214
|
-
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
215
|
-
buffer.rewind()
|
|
216
|
-
bitmap.copyPixelsFromBuffer(buffer)
|
|
202
|
+
val bitmap = FrameHelper.hardwareBufferToBitmap(nativeBuffer.pointer) ?: return
|
|
217
203
|
|
|
218
204
|
val inputImage = InputImage.fromBitmap(bitmap, 0)
|
|
205
|
+
val imageWidth = bitmap.width.toDouble()
|
|
206
|
+
val imageHeight = bitmap.height.toDouble()
|
|
219
207
|
|
|
220
|
-
// ML Kit is async — fire detection, cache result
|
|
221
208
|
poseDetector!!.process(inputImage)
|
|
222
209
|
.addOnSuccessListener { pose ->
|
|
223
210
|
val poseLandmarks = pose.allPoseLandmarks
|
|
@@ -230,9 +217,6 @@ class HybridPoseExercise : HybridNitroPoseExercisesSpec() {
|
|
|
230
217
|
|
|
231
218
|
val landmarkArray = Array(34) { Landmark(x = 0.0, y = 0.0, z = 0.0, visibility = 0.0) }
|
|
232
219
|
|
|
233
|
-
val imageWidth = width.toDouble()
|
|
234
|
-
val imageHeight = height.toDouble()
|
|
235
|
-
|
|
236
220
|
for (poseLandmark in poseLandmarks) {
|
|
237
221
|
val mediaPipeIndex = mlKitToMediaPipeMap[poseLandmark.landmarkType] ?: continue
|
|
238
222
|
if (mediaPipeIndex >= 34) continue
|
|
@@ -265,7 +249,7 @@ class HybridPoseExercise : HybridNitroPoseExercisesSpec() {
|
|
|
265
249
|
bitmap.recycle()
|
|
266
250
|
}
|
|
267
251
|
|
|
268
|
-
// Use cached landmarks
|
|
252
|
+
// Use cached landmarks from previous frame
|
|
269
253
|
val currentLandmarks: Array<Landmark>
|
|
270
254
|
synchronized(landmarkLock) {
|
|
271
255
|
currentLandmarks = cachedLandmarks.copyOf()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ios/
|
|
1
|
+
// ios/NitroPoseExercises.swift
|
|
2
2
|
|
|
3
3
|
import Foundation
|
|
4
4
|
import NitroModules
|
|
@@ -6,7 +6,7 @@ import VisionCamera
|
|
|
6
6
|
import AVFoundation
|
|
7
7
|
import Vision
|
|
8
8
|
|
|
9
|
-
class
|
|
9
|
+
class NitroPoseExercises: HybridNitroPoseExercisesSpec {
|
|
10
10
|
|
|
11
11
|
// ─── Vision Framework ───────────────────────────────────────
|
|
12
12
|
private var isInitialized = false
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nitro-pose-exercises",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Real-time on-device exercise tracking for React Native. Rep counting, form validation, and skeleton overlay powered by Apple Vision (iOS) and Google ML Kit (Android) with VisionCamera v5 via Nitro Modules.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|