react-native-mask-segment-canvas 0.1.0

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.
Files changed (95) hide show
  1. package/README.md +904 -0
  2. package/dist/components/MaskSegmentCanvas.d.ts +6 -0
  3. package/dist/components/MaskSegmentCanvas.d.ts.map +1 -0
  4. package/dist/components/MaskSegmentCanvas.js +2012 -0
  5. package/dist/components/MaskSegmentCanvas.js.map +1 -0
  6. package/dist/components/MaskSegmentCanvas.types.d.ts +189 -0
  7. package/dist/components/MaskSegmentCanvas.types.d.ts.map +1 -0
  8. package/dist/components/MaskSegmentCanvas.types.js +2 -0
  9. package/dist/components/MaskSegmentCanvas.types.js.map +1 -0
  10. package/dist/index.d.ts +6 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +5 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/shaders/regionPaint.sksl.d.ts +3 -0
  15. package/dist/shaders/regionPaint.sksl.d.ts.map +1 -0
  16. package/dist/shaders/regionPaint.sksl.js +72 -0
  17. package/dist/shaders/regionPaint.sksl.js.map +1 -0
  18. package/dist/utils/compositePaintedImage.d.ts +44 -0
  19. package/dist/utils/compositePaintedImage.d.ts.map +1 -0
  20. package/dist/utils/compositePaintedImage.js +146 -0
  21. package/dist/utils/compositePaintedImage.js.map +1 -0
  22. package/dist/utils/exportUtils.d.ts +20 -0
  23. package/dist/utils/exportUtils.d.ts.map +1 -0
  24. package/dist/utils/exportUtils.js +32 -0
  25. package/dist/utils/exportUtils.js.map +1 -0
  26. package/dist/utils/freqLayerPrep.d.ts +23 -0
  27. package/dist/utils/freqLayerPrep.d.ts.map +1 -0
  28. package/dist/utils/freqLayerPrep.js +168 -0
  29. package/dist/utils/freqLayerPrep.js.map +1 -0
  30. package/dist/utils/maskSegmentRuntime.d.ts +43 -0
  31. package/dist/utils/maskSegmentRuntime.d.ts.map +1 -0
  32. package/dist/utils/maskSegmentRuntime.js +181 -0
  33. package/dist/utils/maskSegmentRuntime.js.map +1 -0
  34. package/dist/utils/maskSegmentation.d.ts +133 -0
  35. package/dist/utils/maskSegmentation.d.ts.map +1 -0
  36. package/dist/utils/maskSegmentation.js +1600 -0
  37. package/dist/utils/maskSegmentation.js.map +1 -0
  38. package/dist/utils/maskSemanticPalette.d.ts +31 -0
  39. package/dist/utils/maskSemanticPalette.d.ts.map +1 -0
  40. package/dist/utils/maskSemanticPalette.js +125 -0
  41. package/dist/utils/maskSemanticPalette.js.map +1 -0
  42. package/dist/utils/opencvAdapter.d.ts +116 -0
  43. package/dist/utils/opencvAdapter.d.ts.map +1 -0
  44. package/dist/utils/opencvAdapter.js +353 -0
  45. package/dist/utils/opencvAdapter.js.map +1 -0
  46. package/dist/utils/paintColorMapTexture.d.ts +5 -0
  47. package/dist/utils/paintColorMapTexture.d.ts.map +1 -0
  48. package/dist/utils/paintColorMapTexture.js +203 -0
  49. package/dist/utils/paintColorMapTexture.js.map +1 -0
  50. package/dist/utils/paintShaderRuntime.d.ts +40 -0
  51. package/dist/utils/paintShaderRuntime.d.ts.map +1 -0
  52. package/dist/utils/paintShaderRuntime.js +76 -0
  53. package/dist/utils/paintShaderRuntime.js.map +1 -0
  54. package/dist/utils/pickMapTexture.d.ts +4 -0
  55. package/dist/utils/pickMapTexture.d.ts.map +1 -0
  56. package/dist/utils/pickMapTexture.js +24 -0
  57. package/dist/utils/pickMapTexture.js.map +1 -0
  58. package/dist/utils/pngImage.d.ts +49 -0
  59. package/dist/utils/pngImage.d.ts.map +1 -0
  60. package/dist/utils/pngImage.js +438 -0
  61. package/dist/utils/pngImage.js.map +1 -0
  62. package/dist/utils/resolveAssetPath.d.ts +3 -0
  63. package/dist/utils/resolveAssetPath.d.ts.map +1 -0
  64. package/dist/utils/resolveAssetPath.js +56 -0
  65. package/dist/utils/resolveAssetPath.js.map +1 -0
  66. package/dist/utils/resolveImageUrl.d.ts +3 -0
  67. package/dist/utils/resolveImageUrl.d.ts.map +1 -0
  68. package/dist/utils/resolveImageUrl.js +51 -0
  69. package/dist/utils/resolveImageUrl.js.map +1 -0
  70. package/dist/utils/skiaImage.d.ts +4 -0
  71. package/dist/utils/skiaImage.d.ts.map +1 -0
  72. package/dist/utils/skiaImage.js +12 -0
  73. package/dist/utils/skiaImage.js.map +1 -0
  74. package/package.json +100 -0
  75. package/patches/react-native-fast-opencv+0.4.8.patch +122 -0
  76. package/src/components/MaskSegmentCanvas.tsx +2832 -0
  77. package/src/components/MaskSegmentCanvas.types.ts +216 -0
  78. package/src/globals.d.ts +19 -0
  79. package/src/index.ts +45 -0
  80. package/src/shaders/regionPaint.sksl.ts +71 -0
  81. package/src/upng-js.d.ts +33 -0
  82. package/src/utils/compositePaintedImage.ts +201 -0
  83. package/src/utils/exportUtils.ts +40 -0
  84. package/src/utils/freqLayerPrep.ts +267 -0
  85. package/src/utils/maskSegmentRuntime.ts +257 -0
  86. package/src/utils/maskSegmentation.ts +2294 -0
  87. package/src/utils/maskSemanticPalette.ts +187 -0
  88. package/src/utils/opencvAdapter.ts +539 -0
  89. package/src/utils/paintColorMapTexture.ts +239 -0
  90. package/src/utils/paintShaderRuntime.tsx +150 -0
  91. package/src/utils/pickMapTexture.ts +37 -0
  92. package/src/utils/pngImage.ts +591 -0
  93. package/src/utils/resolveAssetPath.ts +64 -0
  94. package/src/utils/resolveImageUrl.ts +63 -0
  95. package/src/utils/skiaImage.ts +25 -0
@@ -0,0 +1,56 @@
1
+ import { Image, Platform } from 'react-native';
2
+ import RNFS from 'react-native-fs';
3
+ import { ensurePngFile, toPngFileName } from './pngImage';
4
+ /** 将 require() 资源解析为 PNG 本地路径(OpenCV / RNFS 可读) */
5
+ export async function resolveAssetPath(assetModule, cacheFileName) {
6
+ const pngCacheName = toPngFileName(cacheFileName);
7
+ const source = Image.resolveAssetSource(assetModule);
8
+ if (!source?.uri) {
9
+ throw new Error('Cannot resolve image resource');
10
+ }
11
+ const { uri } = source;
12
+ if (uri.startsWith('file://')) {
13
+ return ensurePngFile(uri, pngCacheName);
14
+ }
15
+ if (Platform.OS === 'ios' && uri.startsWith('/')) {
16
+ return ensurePngFile(uri, pngCacheName);
17
+ }
18
+ if (Platform.OS === 'ios' && uri.startsWith('/')) {
19
+ return ensurePngFile(uri, pngCacheName);
20
+ }
21
+ if (uri.startsWith('http://') || uri.startsWith('https://')) {
22
+ const tmpDest = `${RNFS.CachesDirectoryPath}/tmp_${Date.now()}_${pngCacheName}`;
23
+ const { statusCode } = await RNFS.downloadFile({
24
+ fromUrl: uri,
25
+ toFile: tmpDest,
26
+ }).promise;
27
+ if (statusCode !== 200) {
28
+ throw new Error(`Download resource failed: ${pngCacheName}`);
29
+ }
30
+ try {
31
+ return await ensurePngFile(tmpDest, pngCacheName);
32
+ }
33
+ finally {
34
+ if (await RNFS.exists(tmpDest)) {
35
+ await RNFS.unlink(tmpDest);
36
+ }
37
+ }
38
+ }
39
+ if (Platform.OS === 'android') {
40
+ const assetPath = uri
41
+ .replace('asset:/', '')
42
+ .replace('file:///android_asset/', '');
43
+ const tmpDest = `${RNFS.CachesDirectoryPath}/tmp_${Date.now()}_${pngCacheName}`;
44
+ await RNFS.copyFileAssets(assetPath, tmpDest);
45
+ try {
46
+ return await ensurePngFile(tmpDest, pngCacheName);
47
+ }
48
+ finally {
49
+ if (await RNFS.exists(tmpDest)) {
50
+ await RNFS.unlink(tmpDest);
51
+ }
52
+ }
53
+ }
54
+ return ensurePngFile(uri, pngCacheName);
55
+ }
56
+ //# sourceMappingURL=resolveAssetPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveAssetPath.js","sourceRoot":"","sources":["../../src/utils/resolveAssetPath.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,IAAI,MAAM,iBAAiB,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE1D,mDAAmD;AACnD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,WAAmB,EACnB,aAAqB;IAErB,MAAM,YAAY,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,KAAK,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;QAChB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;KAClD;IAED,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;IAEvB,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;QAC7B,OAAO,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;KACzC;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QAChD,OAAO,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;KACzC;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QAChD,OAAO,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;KACzC;IAED,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;QAC3D,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,mBAAmB,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,YAAY,EAAE,CAAC;QAChF,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC;YAC7C,OAAO,EAAE,GAAG;YACZ,MAAM,EAAE,OAAO;SAChB,CAAC,CAAC,OAAO,CAAC;QACX,IAAI,UAAU,KAAK,GAAG,EAAE;YACtB,MAAM,IAAI,KAAK,CAAC,6BAA6B,YAAY,EAAE,CAAC,CAAC;SAC9D;QACD,IAAI;YACF,OAAO,MAAM,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;SACnD;gBAAS;YACR,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;gBAC9B,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;aAC5B;SACF;KACF;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE;QAC7B,MAAM,SAAS,GAAG,GAAG;aAClB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;aACtB,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,mBAAmB,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,YAAY,EAAE,CAAC;QAChF,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC9C,IAAI;YACF,OAAO,MAAM,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;SACnD;gBAAS;YACR,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;gBAC9B,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;aAC5B;SACF;KACF;IAED,OAAO,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** 将本地路径或远程 URL 解析为 OpenCV / RNFS 可读的 PNG 本地路径 */
2
+ export declare function resolveImageUrl(source: string, cacheFileName?: string): Promise<string>;
3
+ //# sourceMappingURL=resolveImageUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveImageUrl.d.ts","sourceRoot":"","sources":["../../src/utils/resolveImageUrl.ts"],"names":[],"mappings":"AAYA,kDAAkD;AAClD,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,CAAC,CA8CjB"}
@@ -0,0 +1,51 @@
1
+ import { Platform } from 'react-native';
2
+ import RNFS from 'react-native-fs';
3
+ import { ensurePngFile, isPngPath, normalizePath, toPngFileName } from './pngImage';
4
+ function hashUrl(url) {
5
+ let hash = 0;
6
+ for (let i = 0; i < url.length; i++) {
7
+ hash = (hash * 31 + url.charCodeAt(i)) | 0;
8
+ }
9
+ return Math.abs(hash).toString(36);
10
+ }
11
+ /** 将本地路径或远程 URL 解析为 OpenCV / RNFS 可读的 PNG 本地路径 */
12
+ export async function resolveImageUrl(source, cacheFileName) {
13
+ const trimmed = source.trim();
14
+ if (!trimmed) {
15
+ throw new Error('Image URL is empty');
16
+ }
17
+ const pngCacheName = toPngFileName(cacheFileName ?? `img_${hashUrl(trimmed)}.png`);
18
+ if (trimmed.startsWith('http://') || trimmed.startsWith('https://')) {
19
+ const tmpDest = `${RNFS.CachesDirectoryPath}/tmp_${Date.now()}_${pngCacheName}`;
20
+ const { statusCode } = await RNFS.downloadFile({
21
+ fromUrl: trimmed,
22
+ toFile: tmpDest,
23
+ }).promise;
24
+ if (statusCode !== 200) {
25
+ throw new Error(`Download image failed: ${trimmed}`);
26
+ }
27
+ try {
28
+ return await ensurePngFile(tmpDest, pngCacheName);
29
+ }
30
+ finally {
31
+ if (await RNFS.exists(tmpDest)) {
32
+ await RNFS.unlink(tmpDest);
33
+ }
34
+ }
35
+ }
36
+ const normalized = normalizePath(trimmed);
37
+ if (await RNFS.exists(normalized) && isPngPath(normalized)) {
38
+ return normalized;
39
+ }
40
+ if (normalized.startsWith('file://')) {
41
+ return ensurePngFile(normalized, pngCacheName);
42
+ }
43
+ if (Platform.OS === 'ios' && normalized.startsWith('/')) {
44
+ return ensurePngFile(normalized, pngCacheName);
45
+ }
46
+ if (await RNFS.exists(normalized)) {
47
+ return ensurePngFile(normalized, pngCacheName);
48
+ }
49
+ return ensurePngFile(trimmed, pngCacheName);
50
+ }
51
+ //# sourceMappingURL=resolveImageUrl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveImageUrl.js","sourceRoot":"","sources":["../../src/utils/resolveImageUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,IAAI,MAAM,iBAAiB,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpF,SAAS,OAAO,CAAC,GAAW;IAC1B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACnC,IAAI,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;KAC5C;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,kDAAkD;AAClD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,aAAsB;IAEtB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,EAAE;QACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;KACvC;IAED,MAAM,YAAY,GAAG,aAAa,CAChC,aAAa,IAAI,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAC/C,CAAC;IAEF,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;QACnE,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,mBAAmB,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,YAAY,EAAE,CAAC;QAChF,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC;YAC7C,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,OAAO;SAChB,CAAC,CAAC,OAAO,CAAC;QACX,IAAI,UAAU,KAAK,GAAG,EAAE;YACtB,MAAM,IAAI,KAAK,CAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC;SACtD;QACD,IAAI;YACF,OAAO,MAAM,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;SACnD;gBAAS;YACR,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;gBAC9B,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;aAC5B;SACF;KACF;IAED,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,EAAE;QAC1D,OAAO,UAAU,CAAC;KACnB;IAED,IAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;QACpC,OAAO,aAAa,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;KAChD;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QACvD,OAAO,aAAa,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;KAChD;IAED,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;QACjC,OAAO,aAAa,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;KAChD;IAED,OAAO,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type SkImage } from '@shopify/react-native-skia';
2
+ /** 连续 RGBA 缓冲 → Skia 图像(高低频 / 工作分辨率原图内存直传,避免 PNG 落盘) */
3
+ export declare function rgbaBufferToSkiaImage(buffer: Uint8Array, cols: number, rows: number): SkImage | null;
4
+ //# sourceMappingURL=skiaImage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skiaImage.d.ts","sourceRoot":"","sources":["../../src/utils/skiaImage.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,OAAO,EACb,MAAM,4BAA4B,CAAC;AAEpC,wDAAwD;AACxD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,GAAG,IAAI,CAYhB"}
@@ -0,0 +1,12 @@
1
+ import { Skia, AlphaType, ColorType, } from '@shopify/react-native-skia';
2
+ /** 连续 RGBA 缓冲 → Skia 图像(高低频 / 工作分辨率原图内存直传,避免 PNG 落盘) */
3
+ export function rgbaBufferToSkiaImage(buffer, cols, rows) {
4
+ const data = Skia.Data.fromBytes(buffer);
5
+ return Skia.Image.MakeImage({
6
+ width: cols,
7
+ height: rows,
8
+ alphaType: AlphaType.Opaque,
9
+ colorType: ColorType.RGBA_8888,
10
+ }, data, cols * 4);
11
+ }
12
+ //# sourceMappingURL=skiaImage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skiaImage.js","sourceRoot":"","sources":["../../src/utils/skiaImage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,SAAS,EACT,SAAS,GAEV,MAAM,4BAA4B,CAAC;AAEpC,wDAAwD;AACxD,MAAM,UAAU,qBAAqB,CACnC,MAAkB,EAClB,IAAY,EACZ,IAAY;IAEZ,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CACzB;QACE,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,SAAS,CAAC,MAAM;QAC3B,SAAS,EAAE,SAAS,CAAC,SAAS;KAC/B,EACD,IAAI,EACJ,IAAI,GAAG,CAAC,CACT,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "react-native-mask-segment-canvas",
3
+ "version": "0.1.0",
4
+ "description": "React Native 掩码分区交互库:OpenCV 语义分割 + SkSL Shader 上色",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "src",
17
+ "patches",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "android": "react-native run-android",
22
+ "ios": "react-native run-ios",
23
+ "lint": "eslint .",
24
+ "pod:check": "bash ios/scripts/setup_vendor_pods.sh",
25
+ "pod:install": "cd ios && pod install",
26
+ "postinstall": "patch-package",
27
+ "start": "react-native start",
28
+ "test": "jest",
29
+ "build": "tsc -p tsconfig.build.json",
30
+ "prepare": "npm run build"
31
+ },
32
+ "dependencies": {
33
+ "buffer": "^6.0.3",
34
+ "upng-js": "^2.1.0"
35
+ },
36
+ "peerDependencies": {
37
+ "@shopify/react-native-skia": ">=2.0.0",
38
+ "react": ">=18",
39
+ "react-native": ">=0.74",
40
+ "react-native-fast-opencv": ">=0.4.8",
41
+ "react-native-fs": ">=2.20.0",
42
+ "react-native-gesture-handler": ">=2.16.0",
43
+ "react-native-image-picker": ">=7.0.0",
44
+ "react-native-reanimated": ">=3.0.0",
45
+ "react-native-safe-area-context": ">=4.0.0"
46
+ },
47
+ "peerDependenciesMeta": {
48
+ "react-native-image-picker": {
49
+ "optional": true
50
+ },
51
+ "react-native-safe-area-context": {
52
+ "optional": true
53
+ }
54
+ },
55
+ "devDependencies": {
56
+ "@babel/core": "^7.25.2",
57
+ "@babel/preset-env": "^7.25.3",
58
+ "@babel/runtime": "^7.25.0",
59
+ "@react-native-community/cli": "18.0.0",
60
+ "@react-native-community/cli-platform-android": "18.0.0",
61
+ "@react-native-community/cli-platform-ios": "18.0.0",
62
+ "@react-native/babel-preset": "0.79.4",
63
+ "@react-native/eslint-config": "0.79.4",
64
+ "@react-native/metro-config": "0.79.4",
65
+ "@react-native/typescript-config": "0.79.4",
66
+ "@shopify/react-native-skia": "^2.6.4",
67
+ "@types/jest": "^29.5.13",
68
+ "@types/react": "^19.0.0",
69
+ "@types/react-test-renderer": "^19.0.0",
70
+ "eslint": "^8.19.0",
71
+ "jest": "^29.6.3",
72
+ "patch-package": "^8.0.1",
73
+ "prettier": "2.8.8",
74
+ "react": "19.0.0",
75
+ "react-native": "0.79.4",
76
+ "react-native-fast-opencv": "^0.4.8",
77
+ "react-native-fs": "^2.20.0",
78
+ "react-native-gesture-handler": "^2.16.0",
79
+ "react-native-image-picker": "^8.2.1",
80
+ "react-native-reanimated": "^3.19.5",
81
+ "react-native-safe-area-context": "^5.8.0",
82
+ "react-test-renderer": "19.0.0",
83
+ "typescript": "5.0.4"
84
+ },
85
+ "engines": {
86
+ "node": ">=18"
87
+ },
88
+ "keywords": [
89
+ "react-native",
90
+ "mask-segmentation",
91
+ "semantic-segmentation",
92
+ "opencv",
93
+ "skia",
94
+ "shader",
95
+ "image-editing",
96
+ "canvas",
97
+ "paint"
98
+ ],
99
+ "license": "MIT"
100
+ }
@@ -0,0 +1,122 @@
1
+ diff --git a/node_modules/react-native-fast-opencv/cpp/ConvertImage.cpp b/node_modules/react-native-fast-opencv/cpp/ConvertImage.cpp
2
+ index ea50bc0..729d648 100644
3
+ --- a/node_modules/react-native-fast-opencv/cpp/ConvertImage.cpp
4
+ +++ b/node_modules/react-native-fast-opencv/cpp/ConvertImage.cpp
5
+ @@ -149,6 +149,39 @@ string ImageConverter::mat2str(const Mat& m, std::string &format)
6
+
7
+ }
8
+
9
+ +Mat ImageConverter::ensure8U(const Mat& img)
10
+ +{
11
+ + if (img.empty() || img.depth() == CV_8U) {
12
+ + return img;
13
+ + }
14
+ +
15
+ + // Semantic mask PNG: 16-bit RGB stores 8-bit labels as value×257.
16
+ + if (img.depth() == CV_16U && img.channels() >= 3) {
17
+ + cv::Mat img8;
18
+ + if (img.channels() == 4) {
19
+ + cv::Mat bgr16;
20
+ + cv::cvtColor(img, bgr16, cv::COLOR_BGRA2BGR);
21
+ + bgr16.convertTo(img8, CV_8U, 1.0 / 257.0);
22
+ + } else {
23
+ + img.convertTo(img8, CV_8U, 1.0 / 257.0);
24
+ + }
25
+ + return img8;
26
+ + }
27
+ +
28
+ + Mat dst;
29
+ + const int outType = CV_MAKETYPE(CV_8U, img.channels());
30
+ + double alpha = 1.0;
31
+ +
32
+ + if (img.depth() == CV_16U || img.depth() == CV_16S) {
33
+ + alpha = 255.0 / 65535.0;
34
+ + } else if (img.depth() == CV_32F || img.depth() == CV_64F) {
35
+ + alpha = 255.0;
36
+ + }
37
+ +
38
+ + img.convertTo(dst, outType, alpha);
39
+ + return dst;
40
+ +}
41
+ +
42
+ Mat ImageConverter::str2mat(const string& s)
43
+ {
44
+ // Decode data
45
+ @@ -157,5 +190,5 @@ Mat ImageConverter::str2mat(const string& s)
46
+
47
+ cv::Mat img = cv::imdecode(data, IMREAD_UNCHANGED);
48
+
49
+ - return img;
50
+ + return ensure8U(img);
51
+ }
52
+ diff --git a/node_modules/react-native-fast-opencv/cpp/ConvertImage.hpp b/node_modules/react-native-fast-opencv/cpp/ConvertImage.hpp
53
+ index 79df697..9bd84f2 100644
54
+ --- a/node_modules/react-native-fast-opencv/cpp/ConvertImage.hpp
55
+ +++ b/node_modules/react-native-fast-opencv/cpp/ConvertImage.hpp
56
+ @@ -23,6 +23,8 @@ class ImageConverter {
57
+ public:
58
+ static cv::Mat str2mat(const string& imageBase64);
59
+ static string mat2str(const Mat& img, std::string &format);
60
+ + /** 16-bit / float PNG 等非常规 depth 统一缩放到 8-bit,避免 matToBuffer(uint8) 误读 */
61
+ + static cv::Mat ensure8U(const Mat& img);
62
+
63
+ private:
64
+ static std::string base64_encode(uchar const* bytesToEncode, unsigned int inLen);
65
+ diff --git a/node_modules/react-native-fast-opencv/cpp/FOCV_Object.cpp b/node_modules/react-native-fast-opencv/cpp/FOCV_Object.cpp
66
+ index e83166d..5d3268e 100644
67
+ --- a/node_modules/react-native-fast-opencv/cpp/FOCV_Object.cpp
68
+ +++ b/node_modules/react-native-fast-opencv/cpp/FOCV_Object.cpp
69
+ @@ -183,20 +183,20 @@ jsi::Object FOCV_Object::convertToJSI(jsi::Runtime& runtime, const jsi::Value* a
70
+
71
+ switch(hashString(objectType.c_str(), objectType.size())) {
72
+ case hashString("mat", 3): {
73
+ - auto mat = *FOCV_Storage::get<cv::Mat>(id);
74
+ + const cv::Mat& stored = *FOCV_Storage::get<cv::Mat>(id);
75
+ std::string format = "jpeg";
76
+
77
+ if(arguments[1].isString()) {
78
+ format = arguments[1].asString(runtime).utf8(runtime);
79
+ }
80
+
81
+ - mat.convertTo(mat, CV_8U);
82
+ + const cv::Mat exportMat = ImageConverter::ensure8U(stored);
83
+
84
+ - value.setProperty(runtime, "base64", jsi::String::createFromUtf8(runtime, ImageConverter::mat2str(mat, format)));
85
+ - value.setProperty(runtime, "size", jsi::Value(mat.size));
86
+ - value.setProperty(runtime, "cols", jsi::Value(mat.cols));
87
+ - value.setProperty(runtime, "rows", jsi::Value(mat.rows));
88
+ - value.setProperty(runtime, "type", jsi::Value(mat.type()));
89
+ + value.setProperty(runtime, "base64", jsi::String::createFromUtf8(runtime, ImageConverter::mat2str(exportMat, format)));
90
+ + value.setProperty(runtime, "size", jsi::Value(stored.size));
91
+ + value.setProperty(runtime, "cols", jsi::Value(stored.cols));
92
+ + value.setProperty(runtime, "rows", jsi::Value(stored.rows));
93
+ + value.setProperty(runtime, "type", jsi::Value(stored.type()));
94
+ } break;
95
+ case hashString("mat_vector", 10): {
96
+ auto mats = *FOCV_Storage::get<std::vector<cv::Mat>>(id);
97
+ diff --git a/node_modules/react-native-fast-opencv/cpp/react-native-fast-opencv.cpp b/node_modules/react-native-fast-opencv/cpp/react-native-fast-opencv.cpp
98
+ index f0186e5..1289d57 100644
99
+ --- a/node_modules/react-native-fast-opencv/cpp/react-native-fast-opencv.cpp
100
+ +++ b/node_modules/react-native-fast-opencv/cpp/react-native-fast-opencv.cpp
101
+ @@ -160,7 +160,8 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN
102
+ size_t count) -> jsi::Object {
103
+
104
+ auto id = FOCV_JsiObject::id_from_wrap(runtime, arguments[0]);
105
+ - auto mat = *FOCV_Storage::get<cv::Mat>(id);
106
+ + const cv::Mat& stored = *FOCV_Storage::get<cv::Mat>(id);
107
+ + cv::Mat mat = stored.isContinuous() ? stored : stored.clone();
108
+
109
+ jsi::Object value(runtime);
110
+
111
+ @@ -169,6 +170,11 @@ jsi::Value OpenCVPlugin::get(jsi::Runtime& runtime, const jsi::PropNameID& propN
112
+ value.setProperty(runtime, "channels", jsi::Value(mat.channels()));
113
+
114
+ auto type = arguments[1].asString(runtime).utf8(runtime);
115
+ +
116
+ + if(type == "uint8" && mat.depth() != CV_8U) {
117
+ + mat = ImageConverter::ensure8U(mat);
118
+ + }
119
+ +
120
+ auto size = mat.cols * mat.rows * mat.channels();
121
+
122
+ if(type == "uint8") {