aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-08-14 13:02:53 -0400
committerbobzel <zzzman@gmail.com>2025-08-14 13:02:53 -0400
commitcabd82bea8eb4c69f60c8b5d4f987cf484123ecd (patch)
tree00430ea11b9eaa0dc032a8f7941849bbb9e0bf44
parent467f1c2543626a50d48c84669cd408571260f147 (diff)
moved background removal code into ImageUtils
-rw-r--r--src/client/util/Import & Export/ImageUtils.ts48
-rw-r--r--src/client/views/nodes/ImageBox.tsx61
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx2
-rw-r--r--src/workers/image.worker.ts5
4 files changed, 65 insertions, 51 deletions
diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts
index eae3460b3..e2eab9010 100644
--- a/src/client/util/Import & Export/ImageUtils.ts
+++ b/src/client/util/Import & Export/ImageUtils.ts
@@ -1,9 +1,11 @@
import { ClientUtils } from '../../../ClientUtils';
import { Doc } from '../../../fields/Doc';
+import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { Upload } from '../../../server/SharedMediaTypes';
+import { Docs, DocumentOptions } from '../../documents/Documents';
import { Networking } from '../../Network';
export namespace ImageUtils {
@@ -31,4 +33,50 @@ export namespace ImageUtils {
a.download = `Dash Export [${StrCast(collection.title)}].zip`;
a.click();
};
+
+ export function convertImgBlobToDataURL(blob: unknown) {
+ return new Promise<string | ArrayBuffer | null>((resolve, reject) => {
+ const reader = new FileReader();
+ reader.onload = () => resolve(reader.result);
+ reader.onerror = e => reject(e);
+ reader.readAsDataURL(blob as Blob);
+ });
+ };
+ export function createImageDocFromBlob(blob: Blob, options: DocumentOptions, docId: string, nativeWidth: number, nativeHeight: number): Promise<Doc> {
+ return new Promise((resolve, reject) => {
+ convertImgBlobToDataURL(blob).then(durl => {
+ ClientUtils.convertDataUri(durl as string, docId + '_noBgd').then(url => {
+ const imageSnapshot = Docs.Create.ImageDocument(url, options);
+ Doc.SetNativeWidth(imageSnapshot[DocData], nativeWidth);
+ Doc.SetNativeHeight(imageSnapshot[DocData], nativeHeight);
+ resolve(imageSnapshot);
+ }).catch(reject);
+ }).catch(reject);
+ });
+ }
+ let backgroundRemovalWorker: Worker|undefined;
+ const workerCallbackMap = new Map<string, (result: Doc) => void>();
+ function getBackgroundRemovalWorker() {
+ if (backgroundRemovalWorker) return backgroundRemovalWorker;
+ backgroundRemovalWorker = new Worker('/image.worker.js', { type: 'module' });
+ backgroundRemovalWorker.onerror = (e: ErrorEvent) => console.error('Worker failed:', e); // worker.terminate();
+ backgroundRemovalWorker.onmessage = async (event: MessageEvent) => {
+ if (event.data.success) {
+ createImageDocFromBlob(event.data.result, event.data.options, event.data.docId, event.data.nativeWidth, event.data.nativeHeight)
+ .then(imageSnapshot => {
+ workerCallbackMap.get(event.data.docId)?.(imageSnapshot);
+ workerCallbackMap.delete(event.data.docId);
+ })
+ } else {
+ console.error('Error in background removal:', event.data.error);
+ }
+ // worker.terminate();
+ };
+ return backgroundRemovalWorker;
+
+ }
+ export function removeImgBackground(options:DocumentOptions, cb: (result: Doc) => void, docId: string, nativeWidth:number, nativeHeight:number, docImgPath: string) {
+ workerCallbackMap.set(docId, cb); // Store the callback by docId (or use a unique requestId)
+ getBackgroundRemovalWorker().postMessage({ imagePath: docImgPath, options, docId, nativeWidth, nativeHeight });
+ };
}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index cc747eb32..c4a731078 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -46,6 +46,7 @@ import { FieldView, FieldViewProps } from './FieldView';
import { FocusViewOptions } from './FocusViewOptions';
import './ImageBox.scss';
import { OpenWhere } from './OpenWhere';
+import { ImageUtils } from '../../util/Import & Export/ImageUtils';
const DefaultPath = '/assets/unknown-file-icon-hi.png';
export class ImageEditorData {
@@ -388,56 +389,22 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._props.bringToFront?.(cropping);
return cropping;
};
-
- static _worker?: Worker;
- static removeImgBackground = (doc: Doc, addDoc: (doc: Doc | Doc[], annotationKey?: string) => boolean, docImgPath: string) => {
- ImageEditorData.AddDoc = addDoc;
- ImageEditorData.RootDoc = doc;
- if (ImageBox._worker) return ImageBox._worker;
- const worker = new Worker('/image.worker.js', { type: 'module' });
- worker.onmessage = async (event: MessageEvent) => {
- const { success, result, error } = event.data;
- if (success) {
- const blobToDataURL = (blob: any) => {
- return new Promise<string | ArrayBuffer | null>((resolve, reject) => {
- const reader = new FileReader();
- reader.onload = () => resolve(reader.result);
- reader.onerror = error => reject(error);
- reader.readAsDataURL(blob);
- });
- };
- blobToDataURL(result).then(durl => {
- ClientUtils.convertDataUri(durl as string, doc[Id] + '_noBgd').then(url => {
- const width = NumCast(doc._width) || 1;
- const height = NumCast(doc._height);
- const imageSnapshot = Docs.Create.ImageDocument(url, {
- _nativeWidth: Doc.NativeWidth(doc),
- _nativeHeight: Doc.NativeHeight(doc),
- x: NumCast(doc.x) + width,
- y: NumCast(doc.y),
- _width: 150,
- _height: (height / width) * 150,
- title: 'bgremoved:' + doc.title,
- });
- Doc.SetNativeWidth(imageSnapshot[DocData], Doc.NativeWidth(doc));
- Doc.SetNativeHeight(imageSnapshot[DocData], Doc.NativeHeight(doc));
- addDoc?.(imageSnapshot);
- });
- });
- } else {
- console.error('Error in background removal:', error);
- }
- // worker.terminate();
- };
- worker.onerror = (e: ErrorEvent) => console.error('Worker failed:', e); // worker.terminate();
-
- worker.postMessage({ imagePath: docImgPath });
- return worker;
- };
removeBackground = () => {
const field = ImageCast(this.dataDoc[this.fieldKey]);
if (field && this._props.addDocument) {
- ImageBox.removeImgBackground(this.rootDoc, this._props.addDocument, this.choosePath(field.url));
+ const doc = this.Document;
+ const width = NumCast(doc._width) || 1;
+ const height = NumCast(doc._height);
+ const options ={
+ _nativeWidth: Doc.NativeWidth(doc),
+ _nativeHeight: Doc.NativeHeight(doc),
+ x: NumCast(doc.x) + width,
+ y: NumCast(doc.y),
+ _width: 150,
+ _height: (height / width) * 150,
+ title: 'bgremoved:' + doc.title,
+ }
+ ImageUtils.removeImgBackground(options, this._props.addDocument, this.Document[Id], Doc.NativeWidth(doc), Doc.NativeHeight(doc), this.choosePath(field.url));
}
};
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 6e3bdc5e8..5b95ac127 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -29,7 +29,6 @@ import { FormattedTextBox } from './FormattedTextBox';
@observer
export class DashFieldViewMenu extends AntimodeMenu<AntimodeMenuProps> {
- // eslint-disable-next-line no-use-before-define
static Instance: DashFieldViewMenu;
static createFieldView: (e: React.MouseEvent) => void = emptyFunction;
static toggleFieldHide: () => void = emptyFunction;
@@ -262,7 +261,6 @@ export class DashFieldViewInternal extends ObservableReactComponent<IDashFieldVi
render() {
return (
<div
- // eslint-disable-next-line no-use-before-define
className={`dashFieldView${this.isRowActive() ? '-active' : ''}`}
ref={this._fieldRef}
style={{
diff --git a/src/workers/image.worker.ts b/src/workers/image.worker.ts
index d069742f3..c6db44d03 100644
--- a/src/workers/image.worker.ts
+++ b/src/workers/image.worker.ts
@@ -1,16 +1,17 @@
import { removeBackground } from '@imgly/background-removal';
self.onmessage = async (event: MessageEvent) => {
- const { imagePath, doc, addDoc } = event.data;
+ const { imagePath, options, nativeWidth, nativeHeight, docId } = event.data;
try {
// Perform the background removal
const result = await removeBackground(imagePath);
// Send the result back to the main thread
- self.postMessage({ success: true, result, doc, addDoc });
+ self.postMessage({ success: true, result, options, nativeWidth, nativeHeight, docId });
} catch (error) {
// Send the error back to the main thread
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
self.postMessage({ success: false, error: (error as any).message });
}
};