aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/Import & Export/ImageUtils.ts
blob: e2eab9010b6d414a283a04110ec0193f3fc98904 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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 {
    export const ExtractImgInfo = async (document: Doc) => {
        const field = Cast(document.data, ImageField);
        return field ? (Networking.PostToServer('/inspectImage', { source: field.url.href }) as Promise<Upload.InspectionResults>) : undefined;
    };

    export const AssignImgInfo = (document: Doc, data?: Upload.InspectionResults) => {
        if (data) {
            data.nativeWidth && (document._height = (NumCast(document._width) * data.nativeHeight) / data.nativeWidth);
            const field = '$' + Doc.LayoutDataKey(document);
            document[`${field}_nativeWidth`] = data.nativeWidth;
            document[`${field}_nativeHeight`] = data.nativeHeight;
            document[`${field}_path`] = data.source;
            document[`${field}_exif`] = JSON.stringify(data.exifData.data);
            document[`${field}_contentSize`] = data.contentSize ? data.contentSize : undefined;
        }
        return document;
    };

    export const ExportHierarchyToFileSystem = async (collection: Doc): Promise<void> => {
        const a = document.createElement('a');
        a.href = ClientUtils.prepend(`/imageHierarchyExport/${collection[Id]}`);
        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 });
    };
}