Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: buffer to mat support #67

Merged
merged 1 commit into from
Mar 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions cpp/react-native-fast-opencv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,70 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN
memcpy(mat.data, vec.data(), (int)rows * (int)cols * (int)channels);
auto id = FOCV_Storage::save(mat);

return FOCV_JsiObject::wrap(runtime, "mat", id);
});
} else if (propName == "bufferToMat") {
return jsi::Function::createFromHostFunction(
runtime, jsi::PropNameID::forAscii(runtime, "bufferToMat"), 4,
[=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
size_t count) -> jsi::Object {
auto type = arguments[0].asString(runtime).utf8(runtime);
auto rows = arguments[1].asNumber();
auto cols = arguments[2].asNumber();
auto channels = arguments[3].asNumber();
auto input = arguments[4].asObject(runtime);

auto modeType = -1;
auto typeSize = 1;

if(type == "uint8") {
typeSize = 1;
if (channels == 1) modeType = CV_8U;
if (channels == 3) modeType = CV_8UC3;
if (channels == 4) modeType = CV_8UC4;
} else if(type == "uint16") {
typeSize = 2;
if (channels == 1) modeType = CV_16U;
if (channels == 3) modeType = CV_16UC3;
if (channels == 4) modeType = CV_16UC4;
} else if(type == "int8") {
typeSize = 1;
if (channels == 1) modeType = CV_8S;
if (channels == 3) modeType = CV_8SC3;
if (channels == 4) modeType = CV_8SC4;
} else if(type == "int16") {
typeSize = 2;
if (channels == 1) modeType = CV_16S;
if (channels == 3) modeType = CV_16SC3;
if (channels == 4) modeType = CV_16SC4;
} else if(type == "int32") {
typeSize = 4;
if (channels == 1) modeType = CV_32S;
if (channels == 3) modeType = CV_32SC3;
if (channels == 4) modeType = CV_32SC4;
} else if(type == "float32") {
typeSize = 4;
if (channels == 1) modeType = CV_32F;
if (channels == 3) modeType = CV_32FC3;
if (channels == 4) modeType = CV_32FC4;
} else if(type == "float64") {
typeSize = 8;
if (channels == 1) modeType = CV_64F;
if (channels == 3) modeType = CV_64FC3;
if (channels == 4) modeType = CV_64FC4;
}

if (channels == -1) {
throw std::runtime_error("Fast OpenCV Error: Invalid channel count passed to frameBufferToMat!");
}

auto inputBuffer = getTypedArray(runtime, std::move(input));
auto vec = inputBuffer.toVector(runtime);

cv::Mat mat(rows, cols, modeType);
memcpy(mat.data, vec.data(), (int)rows * (int)cols * (int)channels * typeSize);
auto id = FOCV_Storage::save(mat);

return FOCV_JsiObject::wrap(runtime, "mat", id);
});
}
Expand Down
26 changes: 23 additions & 3 deletions docs/pages/apidetails.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,32 @@ Clears stored objects from memory.
clearBuffers(idsToKeep?: string[]): void;
```

### Frame Buffer to Mat
### Buffer to Mat

Creates an object of type Mat based on an array of Uint8Array.
Creates an object of type Mat based on an array of Buffer Array.

```js
frameBufferToMat(rows: number, cols: number, channels: number, input: Uint8Array): Mat;
bufferToMat<T extends keyof ImportBufferType>(
type: T,
rows: number,
cols: number,
channels: 1 | 3 | 4,
input: ImportBufferType[T]
): Mat;
```

where `ImportBufferType` is:

```ts
type ImportBufferType = {
uint8: Uint8Array;
uint16: Uint16Array;
int8: Int8Array;
int16: Int16Array;
int32: Int32Array;
float32: Float32Array;
float64: Float64Array;
};
```

### Base64 to Mat
Expand Down
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,7 @@ PODS:
- React-Mapbuffer (0.74.4):
- glog
- React-debug
- react-native-fast-opencv (0.4.0):
- react-native-fast-opencv (0.4.1):
- DoubleConversion
- FastOpenCV-iOS (= 1.0.4)
- glog
Expand Down Expand Up @@ -1633,7 +1633,7 @@ SPEC CHECKSUMS:
React-jsitracing: 7246bbdc12aa5ac7f25f5d14eb0e080038d75b00
React-logger: b4440a25b9c41b28042d289998d90b18c79ce2b0
React-Mapbuffer: fe1b4b0aa9c3fb49768dee7e322ee33d2dd6929e
react-native-fast-opencv: ec12ddebad1905298f63036fb9dfbfb5a1cfa502
react-native-fast-opencv: 933f133ed6a319c8b18e105279f9f93efd39f92f
react-native-image-picker: 6f7695f6e5aa43dc6275cbb3198cfa066a2f5be4
react-native-safe-area-context: b13be9714d9771fbde0120bc519c963484de3a71
react-native-skia: d0f075344d4e9333110c4f82dcf86d61105e90f9
Expand Down
2 changes: 1 addition & 1 deletion example/src/examples/CameraPassthrough.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export function CameraPassthrough() {
rotation: '90deg',
});

const frameMat = OpenCV.frameBufferToMat(HEIGHT, WIDTH, 4, resized);
const frameMat = OpenCV.bufferToMat('uint8', HEIGHT, WIDTH, 4, resized);
const output = OpenCV.matToBuffer(frameMat, 'uint8');
const data = Skia.Data.fromBytes(output.buffer);

Expand Down
2 changes: 1 addition & 1 deletion example/src/examples/CameraRealtimeDetection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function CameraRealtimeDetection() {
dataType: 'uint8',
});

const src = OpenCV.frameBufferToMat(height, width, 3, resized);
const src = OpenCV.bufferToMat('uint8', height, width, 3, resized);
const dst = OpenCV.createObject(ObjectType.Mat, 0, 0, DataTypes.CV_8U);

const lowerBound = OpenCV.createObject(ObjectType.Scalar, 30, 60, 60);
Expand Down
2 changes: 1 addition & 1 deletion example/src/examples/DocumentDetection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function DocumentDetection() {
},
});

const source = OpenCV.frameBufferToMat(height, width, 3, resized);
const source = OpenCV.bufferToMat('uint8', height, width, 3, resized);

OpenCV.invoke(
'cvtColor',
Expand Down
19 changes: 19 additions & 0 deletions src/utils/UtilsFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@ type BufferType = {
float64: Float64Array;
};

type ImportBufferType = Omit<BufferType, 'uint32'>;

export type UtilsFunctions = {
/**
* Clears any buffers that were allocate to back Mats on the native side.
*/
clearBuffers(idsToKeep?: string[]): void;
/**
* Converts a byte array to a Mat.
*
* @deprecated Use the new `bufferToMat` function instead.
*
* @param rows - the number of rows in the Mat
* @param cols - the number of columns in the Mat
* @param channels - the number of channels in the Mat
Expand All @@ -29,6 +34,20 @@ export type UtilsFunctions = {
channels: number,
input: Uint8Array
): Mat;
/**
* Converts a byte array to a Mat.
* @param rows - the number of rows in the Mat
* @param cols - the number of columns in the Mat
* @param channels - the number of channels in the Mat
* @param input - the byte array to convert
*/
bufferToMat<T extends keyof ImportBufferType>(
type: T,
rows: number,
cols: number,
channels: 1 | 3 | 4,
input: ImportBufferType[T]
): Mat;
/**
* Converts a base64 string to a Mat.
* @param data - the base64 string to convert
Expand Down
Loading