rn-remove-image-bg 0.0.19 → 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 +15 -10
- 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
|
@@ -326,14 +326,20 @@ try {
|
|
|
326
326
|
|
|
327
327
|
### Web
|
|
328
328
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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.
|
|
333
335
|
|
|
334
|
-
|
|
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.
|
|
339
|
+
- **Requirements**:
|
|
340
|
+
- **CORS**: Images loaded from external URLs must be CORS-enabled (`Access-Control-Allow-Origin: *`).
|
|
335
341
|
|
|
336
|
-
|
|
342
|
+
> **Note**: The first call will download the WASM model files (~10MB) from the CDN. Ensure your CSP allows `cdn.jsdelivr.net`.
|
|
337
343
|
|
|
338
344
|
---
|
|
339
345
|
|
|
@@ -416,10 +422,9 @@ If you don't need web support, you can tree-shake the `@imgly/background-removal
|
|
|
416
422
|
|
|
417
423
|
### Web Not Working?
|
|
418
424
|
|
|
419
|
-
1.
|
|
420
|
-
2.
|
|
421
|
-
3.
|
|
422
|
-
4. CORS may block model download - check network tab
|
|
425
|
+
1. **CSP Errors**: If you see "Content Security Policy" errors, ensure your app allows loading scripts/workers from `https://cdn.jsdelivr.net` and `blob:` URLs.
|
|
426
|
+
2. **CORS Errors**: If loading an image from a URL, the server *must* return `Access-Control-Allow-Origin: *`. If not, download the image to a Blob first or use a proxy.
|
|
427
|
+
3. **Data URL**: Remember that the web result is a `data:` URL. You can use it directly in `<Image source={{ uri: result }} />`.
|
|
423
428
|
|
|
424
429
|
### Native Module Not Found?
|
|
425
430
|
|
|
@@ -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; }
|