rn-remove-image-bg 0.0.20 → 0.0.22
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/README.md +12 -9
- package/lib/ImageProcessing.web.d.ts +2 -3
- package/lib/ImageProcessing.web.js +26 -117
- package/package.json +1 -1
- package/src/ImageProcessing.web.ts +33 -124
package/README.md
CHANGED
|
@@ -325,18 +325,21 @@ try {
|
|
|
325
325
|
> **First-time Use**: On Android, the ML Kit model downloads automatically on first use. The library waits for the download to complete (up to ~15 seconds with retries) before processing. Subsequent calls are instant.
|
|
326
326
|
|
|
327
327
|
### Web
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
328
|
+
|
|
329
|
+
1. **Add the Script**: You must add the `@imgly/background-removal` script to your web `index.html`:
|
|
330
|
+
```html
|
|
331
|
+
<script src="https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/imgly-background-removal.min.js"></script>
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
2. **Usage**: The library will automatically detect the global `imglyBackgroundRemoval` object.
|
|
335
|
+
|
|
336
|
+
- **Technology**: [@imgly/background-removal](https://github.com/imgly/background-removal-js) running in a Web Worker (managed by the library).
|
|
337
|
+
- **Performance**: Zero UI blocking.
|
|
338
|
+
- **Output**: Data URL (`data:image/png;base64,...`) or WEBP Blob.
|
|
334
339
|
- **Requirements**:
|
|
335
|
-
- **Internet Connection**: Required for the first run to download the library and assets (~10MB) from CDN.
|
|
336
340
|
- **CORS**: Images loaded from external URLs must be CORS-enabled (`Access-Control-Allow-Origin: *`).
|
|
337
|
-
- **Output**: Data URL (`data:image/png;base64,...`) or WEBP Blob.
|
|
338
341
|
|
|
339
|
-
> **Note
|
|
342
|
+
> **Note**: The first call will download the WASM model files (~10MB) from the CDN. Ensure your CSP allows `cdn.jsdelivr.net`.
|
|
340
343
|
|
|
341
344
|
---
|
|
342
345
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Web implementation using @imgly/background-removal via
|
|
3
|
-
*
|
|
4
|
-
* Loads library from CDN to bypass Metro bundler issues.
|
|
2
|
+
* Web implementation using @imgly/background-removal via Script Tag.
|
|
3
|
+
* Requires the script to be added manually to index.html.
|
|
5
4
|
*/
|
|
6
5
|
export type OutputFormat = 'PNG' | 'WEBP';
|
|
7
6
|
export interface RemoveBgImageOptions {
|
|
@@ -1,128 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Web implementation using @imgly/background-removal via
|
|
3
|
-
*
|
|
4
|
-
* Loads library from CDN to bypass Metro bundler issues.
|
|
2
|
+
* Web implementation using @imgly/background-removal via Script Tag.
|
|
3
|
+
* Requires the script to be added manually to index.html.
|
|
5
4
|
*/
|
|
6
|
-
// ==========================================
|
|
7
|
-
// INLINE WORKER CODE (Run in background)
|
|
8
|
-
// ==========================================
|
|
9
|
-
const WORKER_CODE = `
|
|
10
|
-
let removeBackground = null;
|
|
11
|
-
|
|
12
|
-
self.onmessage = async (e) => {
|
|
13
|
-
const { id, type, payload } = e.data;
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
if (type === 'init') {
|
|
17
|
-
if (typeof self.imglyBackgroundRemoval === 'undefined' || !removeBackground) {
|
|
18
|
-
// Use importScripts (Classic Worker) - most robust for Blob URLs
|
|
19
|
-
importScripts('https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/imgly-background-removal.min.js');
|
|
20
|
-
|
|
21
|
-
if (!self.imglyBackgroundRemoval) {
|
|
22
|
-
throw new Error('imglyBackgroundRemoval not loaded via importScripts');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
removeBackground = self.imglyBackgroundRemoval.removeBackground;
|
|
26
|
-
}
|
|
27
|
-
self.postMessage({ id, type: 'success', payload: true });
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (type === 'removeBg') {
|
|
32
|
-
const { uri, config } = payload;
|
|
33
|
-
|
|
34
|
-
if (!removeBackground) {
|
|
35
|
-
importScripts('https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/imgly-background-removal.min.js');
|
|
36
|
-
removeBackground = self.imglyBackgroundRemoval.removeBackground;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Run Inference
|
|
40
|
-
// CRITICAL: Must point publicPath to CDN so it finds WASM/Models
|
|
41
|
-
// otherwise it tries to load from blob: URL
|
|
42
|
-
const blob = await removeBackground(uri, {
|
|
43
|
-
publicPath: 'https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/',
|
|
44
|
-
progress: (key, current, total) => {
|
|
45
|
-
const p = current / total;
|
|
46
|
-
self.postMessage({ id, type: 'progress', payload: { progress: p } });
|
|
47
|
-
},
|
|
48
|
-
...config
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// Convert blob to DataURL for return
|
|
52
|
-
const reader = new FileReader();
|
|
53
|
-
reader.onloadend = () => {
|
|
54
|
-
self.postMessage({ id, type: 'success', payload: reader.result });
|
|
55
|
-
};
|
|
56
|
-
reader.readAsDataURL(blob);
|
|
57
|
-
}
|
|
58
|
-
} catch (err) {
|
|
59
|
-
self.postMessage({ id, type: 'error', payload: err.message || JSON.stringify(err) });
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
`;
|
|
63
|
-
// ==========================================
|
|
64
|
-
// MAIN THREAD BRIDGE
|
|
65
|
-
// ==========================================
|
|
66
|
-
let worker = null;
|
|
67
|
-
const pendingMessages = new Map();
|
|
68
|
-
function getWorker() {
|
|
69
|
-
if (!worker) {
|
|
70
|
-
const blob = new Blob([WORKER_CODE], { type: 'application/javascript' });
|
|
71
|
-
const url = URL.createObjectURL(blob);
|
|
72
|
-
worker = new Worker(url);
|
|
73
|
-
worker.onmessage = (e) => {
|
|
74
|
-
const { id, type, payload } = e.data;
|
|
75
|
-
const deferred = pendingMessages.get(id);
|
|
76
|
-
if (!deferred)
|
|
77
|
-
return;
|
|
78
|
-
if (type === 'progress') {
|
|
79
|
-
if (deferred.onProgress && payload.progress) {
|
|
80
|
-
deferred.onProgress(payload.progress * 100);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
else if (type === 'success') {
|
|
84
|
-
deferred.resolve(payload);
|
|
85
|
-
pendingMessages.delete(id);
|
|
86
|
-
}
|
|
87
|
-
else if (type === 'error') {
|
|
88
|
-
deferred.reject(new Error(payload));
|
|
89
|
-
pendingMessages.delete(id);
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
return worker;
|
|
94
|
-
}
|
|
95
|
-
function sendToWorker(type, payload, onProgress) {
|
|
96
|
-
return new Promise((resolve, reject) => {
|
|
97
|
-
const id = Math.random().toString(36).substring(7);
|
|
98
|
-
pendingMessages.set(id, { resolve, reject, onProgress });
|
|
99
|
-
getWorker().postMessage({ id, type, payload });
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
// Initialize
|
|
103
|
-
let initPromise = null;
|
|
104
|
-
async function ensureInit() {
|
|
105
|
-
if (!initPromise) {
|
|
106
|
-
initPromise = sendToWorker('init', {});
|
|
107
|
-
}
|
|
108
|
-
return initPromise;
|
|
109
|
-
}
|
|
110
5
|
export async function removeBgImage(uri, options = {}) {
|
|
111
6
|
const { onProgress, debug = false } = options;
|
|
7
|
+
// Safety check
|
|
8
|
+
if (typeof imglyBackgroundRemoval === 'undefined') {
|
|
9
|
+
throw new Error('[rn-remove-image-bg] Library not found. Please add the following script to your web index.html:\n' +
|
|
10
|
+
'<script src="https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/imgly-background-removal.min.js"></script>');
|
|
11
|
+
}
|
|
112
12
|
if (debug)
|
|
113
13
|
console.log('[rmbg] Starting...');
|
|
114
14
|
onProgress?.(1);
|
|
115
|
-
// Ensure worker is ready
|
|
116
|
-
await ensureInit();
|
|
117
15
|
// Config for imgly
|
|
118
16
|
const config = {
|
|
119
17
|
debug: debug,
|
|
120
|
-
//
|
|
121
|
-
//
|
|
18
|
+
// Point publicPath to CDN for assets (wasm/models)
|
|
19
|
+
// This is crucial for UMD build to find its dependencies on the CDN
|
|
20
|
+
publicPath: 'https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/',
|
|
21
|
+
progress: (_key, current, total) => {
|
|
22
|
+
if (onProgress && total > 0) {
|
|
23
|
+
onProgress((current / total) * 100);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
122
26
|
};
|
|
123
|
-
const
|
|
27
|
+
const blob = await imglyBackgroundRemoval.removeBackground(uri, config);
|
|
124
28
|
onProgress?.(100);
|
|
125
|
-
|
|
29
|
+
// Convert blob to DataURL
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
const reader = new FileReader();
|
|
32
|
+
reader.onloadend = () => resolve(reader.result);
|
|
33
|
+
reader.onerror = reject;
|
|
34
|
+
reader.readAsDataURL(blob);
|
|
35
|
+
});
|
|
126
36
|
}
|
|
127
37
|
export const removeBackground = removeBgImage;
|
|
128
38
|
// ==========================================
|
|
@@ -192,11 +102,10 @@ export async function generateThumbhash(imageUri, options = {}) {
|
|
|
192
102
|
}
|
|
193
103
|
}
|
|
194
104
|
export async function clearCache() {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
if (typeof imglyBackgroundRemoval !== 'undefined' && imglyBackgroundRemoval.preload) {
|
|
107
|
+
// no explicit clear cache in uMD version usually
|
|
198
108
|
}
|
|
199
|
-
initPromise = null;
|
|
200
109
|
}
|
|
201
110
|
export function getCacheSize() { return 0; }
|
|
202
111
|
export async function onLowMemory() {
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Web implementation using @imgly/background-removal via
|
|
3
|
-
*
|
|
4
|
-
* Loads library from CDN to bypass Metro bundler issues.
|
|
2
|
+
* Web implementation using @imgly/background-removal via Script Tag.
|
|
3
|
+
* Requires the script to be added manually to index.html.
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
export type OutputFormat = 'PNG' | 'WEBP';
|
|
@@ -13,115 +12,9 @@ export interface RemoveBgImageOptions {
|
|
|
13
12
|
debug?: boolean;
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
const WORKER_CODE = `
|
|
20
|
-
let removeBackground = null;
|
|
21
|
-
|
|
22
|
-
self.onmessage = async (e) => {
|
|
23
|
-
const { id, type, payload } = e.data;
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
if (type === 'init') {
|
|
27
|
-
if (typeof self.imglyBackgroundRemoval === 'undefined' || !removeBackground) {
|
|
28
|
-
// Use importScripts (Classic Worker) - most robust for Blob URLs
|
|
29
|
-
importScripts('https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/imgly-background-removal.min.js');
|
|
30
|
-
|
|
31
|
-
if (!self.imglyBackgroundRemoval) {
|
|
32
|
-
throw new Error('imglyBackgroundRemoval not loaded via importScripts');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
removeBackground = self.imglyBackgroundRemoval.removeBackground;
|
|
36
|
-
}
|
|
37
|
-
self.postMessage({ id, type: 'success', payload: true });
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (type === 'removeBg') {
|
|
42
|
-
const { uri, config } = payload;
|
|
43
|
-
|
|
44
|
-
if (!removeBackground) {
|
|
45
|
-
importScripts('https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/imgly-background-removal.min.js');
|
|
46
|
-
removeBackground = self.imglyBackgroundRemoval.removeBackground;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Run Inference
|
|
50
|
-
// CRITICAL: Must point publicPath to CDN so it finds WASM/Models
|
|
51
|
-
// otherwise it tries to load from blob: URL
|
|
52
|
-
const blob = await removeBackground(uri, {
|
|
53
|
-
publicPath: 'https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/',
|
|
54
|
-
progress: (key, current, total) => {
|
|
55
|
-
const p = current / total;
|
|
56
|
-
self.postMessage({ id, type: 'progress', payload: { progress: p } });
|
|
57
|
-
},
|
|
58
|
-
...config
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// Convert blob to DataURL for return
|
|
62
|
-
const reader = new FileReader();
|
|
63
|
-
reader.onloadend = () => {
|
|
64
|
-
self.postMessage({ id, type: 'success', payload: reader.result });
|
|
65
|
-
};
|
|
66
|
-
reader.readAsDataURL(blob);
|
|
67
|
-
}
|
|
68
|
-
} catch (err) {
|
|
69
|
-
self.postMessage({ id, type: 'error', payload: err.message || JSON.stringify(err) });
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
`;
|
|
73
|
-
|
|
74
|
-
// ==========================================
|
|
75
|
-
// MAIN THREAD BRIDGE
|
|
76
|
-
// ==========================================
|
|
77
|
-
|
|
78
|
-
let worker: Worker | null = null;
|
|
79
|
-
const pendingMessages = new Map<string, { resolve: (v: any) => void; reject: (e: any) => void; onProgress?: (p: number) => void }>();
|
|
80
|
-
|
|
81
|
-
function getWorker() {
|
|
82
|
-
if (!worker) {
|
|
83
|
-
const blob = new Blob([WORKER_CODE], { type: 'application/javascript' });
|
|
84
|
-
const url = URL.createObjectURL(blob);
|
|
85
|
-
worker = new Worker(url);
|
|
86
|
-
|
|
87
|
-
worker.onmessage = (e) => {
|
|
88
|
-
const { id, type, payload } = e.data;
|
|
89
|
-
const deferred = pendingMessages.get(id);
|
|
90
|
-
|
|
91
|
-
if (!deferred) return;
|
|
92
|
-
|
|
93
|
-
if (type === 'progress') {
|
|
94
|
-
if (deferred.onProgress && payload.progress) {
|
|
95
|
-
deferred.onProgress(payload.progress * 100);
|
|
96
|
-
}
|
|
97
|
-
} else if (type === 'success') {
|
|
98
|
-
deferred.resolve(payload);
|
|
99
|
-
pendingMessages.delete(id);
|
|
100
|
-
} else if (type === 'error') {
|
|
101
|
-
deferred.reject(new Error(payload));
|
|
102
|
-
pendingMessages.delete(id);
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
return worker;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function sendToWorker(type: string, payload: any, onProgress?: (p: number) => void): Promise<any> {
|
|
110
|
-
return new Promise((resolve, reject) => {
|
|
111
|
-
const id = Math.random().toString(36).substring(7);
|
|
112
|
-
pendingMessages.set(id, { resolve, reject, onProgress });
|
|
113
|
-
getWorker().postMessage({ id, type, payload });
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Initialize
|
|
118
|
-
let initPromise: Promise<void> | null = null;
|
|
119
|
-
async function ensureInit() {
|
|
120
|
-
if (!initPromise) {
|
|
121
|
-
initPromise = sendToWorker('init', {});
|
|
122
|
-
}
|
|
123
|
-
return initPromise;
|
|
124
|
-
}
|
|
15
|
+
// Check for global variable
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
declare const imglyBackgroundRemoval: any;
|
|
125
18
|
|
|
126
19
|
export async function removeBgImage(
|
|
127
20
|
uri: string,
|
|
@@ -129,23 +22,40 @@ export async function removeBgImage(
|
|
|
129
22
|
): Promise<string> {
|
|
130
23
|
const { onProgress, debug = false } = options;
|
|
131
24
|
|
|
25
|
+
// Safety check
|
|
26
|
+
if (typeof imglyBackgroundRemoval === 'undefined') {
|
|
27
|
+
throw new Error(
|
|
28
|
+
'[rn-remove-image-bg] Library not found. Please add the following script to your web index.html:\n' +
|
|
29
|
+
'<script src="https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/imgly-background-removal.min.js"></script>'
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
132
33
|
if (debug) console.log('[rmbg] Starting...');
|
|
133
34
|
onProgress?.(1);
|
|
134
35
|
|
|
135
|
-
// Ensure worker is ready
|
|
136
|
-
await ensureInit();
|
|
137
|
-
|
|
138
36
|
// Config for imgly
|
|
139
37
|
const config = {
|
|
140
38
|
debug: debug,
|
|
141
|
-
//
|
|
142
|
-
//
|
|
39
|
+
// Point publicPath to CDN for assets (wasm/models)
|
|
40
|
+
// This is crucial for UMD build to find its dependencies on the CDN
|
|
41
|
+
publicPath: 'https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/',
|
|
42
|
+
progress: (_key: string, current: number, total: number) => {
|
|
43
|
+
if (onProgress && total > 0) {
|
|
44
|
+
onProgress((current / total) * 100);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
143
47
|
};
|
|
144
48
|
|
|
145
|
-
const
|
|
146
|
-
|
|
49
|
+
const blob = await imglyBackgroundRemoval.removeBackground(uri, config);
|
|
147
50
|
onProgress?.(100);
|
|
148
|
-
|
|
51
|
+
|
|
52
|
+
// Convert blob to DataURL
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
const reader = new FileReader();
|
|
55
|
+
reader.onloadend = () => resolve(reader.result as string);
|
|
56
|
+
reader.onerror = reject;
|
|
57
|
+
reader.readAsDataURL(blob);
|
|
58
|
+
});
|
|
149
59
|
}
|
|
150
60
|
|
|
151
61
|
export const removeBackground = removeBgImage;
|
|
@@ -250,11 +160,10 @@ export async function generateThumbhash(
|
|
|
250
160
|
}
|
|
251
161
|
|
|
252
162
|
export async function clearCache(): Promise<void> {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
163
|
+
// @ts-ignore
|
|
164
|
+
if (typeof imglyBackgroundRemoval !== 'undefined' && imglyBackgroundRemoval.preload) {
|
|
165
|
+
// no explicit clear cache in uMD version usually
|
|
256
166
|
}
|
|
257
|
-
initPromise = null;
|
|
258
167
|
}
|
|
259
168
|
|
|
260
169
|
export function getCacheSize(): number { return 0; }
|