rn-remove-image-bg 0.0.20 → 0.0.23
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 +16 -9
- package/lib/ImageProcessing.web.d.ts +2 -3
- package/lib/ImageProcessing.web.js +36 -117
- package/package.json +1 -1
- package/src/ImageProcessing.web.ts +45 -125
package/README.md
CHANGED
|
@@ -325,18 +325,25 @@ 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` setup to your web `index.html`.
|
|
330
|
+
Since the library is distributed as an ES Module, you need to import it and assign it to the window object:
|
|
331
|
+
```html
|
|
332
|
+
<script type="module">
|
|
333
|
+
import { removeBackground } from "https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/+esm";
|
|
334
|
+
window.imglyRemoveBackground = removeBackground;
|
|
335
|
+
</script>
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
2. **Usage**: The library will automatically detect the global `imglyRemoveBackground` function.
|
|
339
|
+
|
|
340
|
+
- **Technology**: [@imgly/background-removal](https://github.com/imgly/background-removal-js) running in a Web Worker (managed by the library).
|
|
341
|
+
- **Performance**: Zero UI blocking.
|
|
342
|
+
- **Output**: Data URL (`data:image/png;base64,...`) or WEBP Blob.
|
|
334
343
|
- **Requirements**:
|
|
335
|
-
- **Internet Connection**: Required for the first run to download the library and assets (~10MB) from CDN.
|
|
336
344
|
- **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
345
|
|
|
339
|
-
> **Note
|
|
346
|
+
> **Note**: The first call will download the WASM model files (~10MB) from the CDN. Ensure your CSP allows `cdn.jsdelivr.net`.
|
|
340
347
|
|
|
341
348
|
---
|
|
342
349
|
|
|
@@ -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,51 @@
|
|
|
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
|
-
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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;
|
|
5
|
+
export async function removeBgImage(uri, options = {}) {
|
|
6
|
+
const { onProgress, debug = false } = options;
|
|
7
|
+
// Safety check
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
if (typeof window !== 'undefined' && !window.imglyRemoveBackground) {
|
|
10
|
+
// Also check if user defined it as imglyRemoveBackground globally
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
if (typeof imglyRemoveBackground !== 'undefined') {
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
window.imglyRemoveBackground = imglyRemoveBackground;
|
|
37
15
|
}
|
|
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
16
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
};
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
if (typeof window.imglyRemoveBackground === 'undefined') {
|
|
19
|
+
throw new Error('[rn-remove-image-bg] Library not found. Please add the following script to your web index.html:\n' +
|
|
20
|
+
'<script type="module">\n' +
|
|
21
|
+
' import { removeBackground } from "https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/+esm";\n' +
|
|
22
|
+
' window.imglyRemoveBackground = removeBackground;\n' +
|
|
23
|
+
'</script>');
|
|
92
24
|
}
|
|
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
|
-
export async function removeBgImage(uri, options = {}) {
|
|
111
|
-
const { onProgress, debug = false } = options;
|
|
112
25
|
if (debug)
|
|
113
26
|
console.log('[rmbg] Starting...');
|
|
114
27
|
onProgress?.(1);
|
|
115
|
-
// Ensure worker is ready
|
|
116
|
-
await ensureInit();
|
|
117
28
|
// Config for imgly
|
|
118
29
|
const config = {
|
|
119
30
|
debug: debug,
|
|
120
|
-
//
|
|
121
|
-
|
|
31
|
+
// Point publicPath to CDN for assets (wasm/models)
|
|
32
|
+
publicPath: 'https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/',
|
|
33
|
+
progress: (_key, current, total) => {
|
|
34
|
+
if (onProgress && total > 0) {
|
|
35
|
+
onProgress((current / total) * 100);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
122
38
|
};
|
|
123
|
-
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
const blob = await window.imglyRemoveBackground(uri, config);
|
|
124
41
|
onProgress?.(100);
|
|
125
|
-
|
|
42
|
+
// Convert blob to DataURL
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
const reader = new FileReader();
|
|
45
|
+
reader.onloadend = () => resolve(reader.result);
|
|
46
|
+
reader.onerror = reject;
|
|
47
|
+
reader.readAsDataURL(blob);
|
|
48
|
+
});
|
|
126
49
|
}
|
|
127
50
|
export const removeBackground = removeBgImage;
|
|
128
51
|
// ==========================================
|
|
@@ -192,11 +115,7 @@ export async function generateThumbhash(imageUri, options = {}) {
|
|
|
192
115
|
}
|
|
193
116
|
}
|
|
194
117
|
export async function clearCache() {
|
|
195
|
-
|
|
196
|
-
worker.terminate();
|
|
197
|
-
worker = null;
|
|
198
|
-
}
|
|
199
|
-
initPromise = null;
|
|
118
|
+
// Caching is handled internally by the library
|
|
200
119
|
}
|
|
201
120
|
export function getCacheSize() { return 0; }
|
|
202
121
|
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 imglyRemoveBackground: any;
|
|
125
18
|
|
|
126
19
|
export async function removeBgImage(
|
|
127
20
|
uri: string,
|
|
@@ -129,23 +22,54 @@ export async function removeBgImage(
|
|
|
129
22
|
): Promise<string> {
|
|
130
23
|
const { onProgress, debug = false } = options;
|
|
131
24
|
|
|
25
|
+
// Safety check
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
if (typeof window !== 'undefined' && !window.imglyRemoveBackground) {
|
|
28
|
+
// Also check if user defined it as imglyRemoveBackground globally
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
if (typeof imglyRemoveBackground !== 'undefined') {
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
window.imglyRemoveBackground = imglyRemoveBackground;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
if (typeof window.imglyRemoveBackground === 'undefined') {
|
|
38
|
+
throw new Error(
|
|
39
|
+
'[rn-remove-image-bg] Library not found. Please add the following script to your web index.html:\n' +
|
|
40
|
+
'<script type="module">\n' +
|
|
41
|
+
' import { removeBackground } from "https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/+esm";\n' +
|
|
42
|
+
' window.imglyRemoveBackground = removeBackground;\n' +
|
|
43
|
+
'</script>'
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
132
47
|
if (debug) console.log('[rmbg] Starting...');
|
|
133
48
|
onProgress?.(1);
|
|
134
49
|
|
|
135
|
-
// Ensure worker is ready
|
|
136
|
-
await ensureInit();
|
|
137
|
-
|
|
138
50
|
// Config for imgly
|
|
139
51
|
const config = {
|
|
140
52
|
debug: debug,
|
|
141
|
-
//
|
|
142
|
-
|
|
53
|
+
// Point publicPath to CDN for assets (wasm/models)
|
|
54
|
+
publicPath: 'https://cdn.jsdelivr.net/npm/@imgly/background-removal@1.7.0/dist/',
|
|
55
|
+
progress: (_key: string, current: number, total: number) => {
|
|
56
|
+
if (onProgress && total > 0) {
|
|
57
|
+
onProgress((current / total) * 100);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
143
60
|
};
|
|
144
61
|
|
|
145
|
-
|
|
146
|
-
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
const blob = await window.imglyRemoveBackground(uri, config);
|
|
147
64
|
onProgress?.(100);
|
|
148
|
-
|
|
65
|
+
|
|
66
|
+
// Convert blob to DataURL
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
const reader = new FileReader();
|
|
69
|
+
reader.onloadend = () => resolve(reader.result as string);
|
|
70
|
+
reader.onerror = reject;
|
|
71
|
+
reader.readAsDataURL(blob);
|
|
72
|
+
});
|
|
149
73
|
}
|
|
150
74
|
|
|
151
75
|
export const removeBackground = removeBgImage;
|
|
@@ -250,11 +174,7 @@ export async function generateThumbhash(
|
|
|
250
174
|
}
|
|
251
175
|
|
|
252
176
|
export async function clearCache(): Promise<void> {
|
|
253
|
-
|
|
254
|
-
worker.terminate();
|
|
255
|
-
worker = null;
|
|
256
|
-
}
|
|
257
|
-
initPromise = null;
|
|
177
|
+
// Caching is handled internally by the library
|
|
258
178
|
}
|
|
259
179
|
|
|
260
180
|
export function getCacheSize(): number { return 0; }
|