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) : 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 => { 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((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 | undefined, options: DocumentOptions & { _nativeWidth: number; _nativeHeight: number }, filename: string, overwriteDoc?: Doc): Promise { return new Promise((resolve, reject) => { if (!blob) return reject('No image blob provided'); convertImgBlobToDataURL(blob) .then(durl => { ClientUtils.convertDataUri(durl as string, filename) .then(url => { const imageSnapshot = Docs.Create.ImageDocument(url, options, overwriteDoc); Doc.SetNativeWidth(imageSnapshot[DocData], options._nativeWidth); Doc.SetNativeHeight(imageSnapshot[DocData], options._nativeHeight); resolve(imageSnapshot); }) .catch(reject); }) .catch(reject); }); } let backgroundRemovalWorker: Worker | undefined; const workerCallbackMap = new Map unknown; rej: () => unknown }>(); function getBackgroundRemovalWorker() { if (backgroundRemovalWorker) return backgroundRemovalWorker; backgroundRemovalWorker = new Worker('/image.worker.js', { type: 'module' }); backgroundRemovalWorker.onerror = (e: ErrorEvent) => { const docId = (e as ErrorEvent & { docId: string }).docId; const map = workerCallbackMap.get(docId); map?.rej(); workerCallbackMap.delete(docId); // worker.terminate(); }; backgroundRemovalWorker.onmessage = async (event: MessageEvent) => { if (event.data.type === 'progress') { // Handle progress updates if needed console.log(`Progress for docId ${event.data.docId}: ${event.data.progress}`); } else { const map = workerCallbackMap.get(event.data.docId); event.data.success ? map?.res(event.data.result) : map?.rej(); workerCallbackMap.delete(event.data.docId); // worker.terminate(); } }; return backgroundRemovalWorker; } export function removeImgBackground(docId: string, imagePath: string) { return new Promise((res, rej) => { if (!imagePath) return rej('No image path provided'); workerCallbackMap.set(docId, { res, rej }); // Store the callback by docId (or use a unique requestId) getBackgroundRemovalWorker().postMessage({ imagePath, docId, config: { output: { quality: 0.8, // The quality. (Default: 0.8) }, }, }); }); } export function maskForeground(docId: string, imagePath: string) { return new Promise((res, rej) => { if (!imagePath) return rej('No image path provided'); workerCallbackMap.set(docId, { res, rej }); // Store the callback by docId (or use a unique requestId) getBackgroundRemovalWorker().postMessage({ imagePath, docId, config: { //publicPath: string; // The public path used for model and wasm files. Default: 'https://staticimgly.com/${PACKAGE_NAME}-data/${PACKAGE_VERSION}/dist/' //debug: bool; // enable or disable useful console.log outputs //device: 'gpu', // 'cpu' | 'gpu'; // choose the execution device. gpu will use webgpu if available //model: 'isnet' | 'isnet_fp16' | 'isnet_quint8'; // The model to use. (Default "isnet_fp16") output: { //format: 'image/png' | 'image/jpeg' | 'image/webp'; // The output format. (Default "image/png") quality: 0.8, // The quality. (Default: 0.8) type: 'mask', // 'foreground' | 'background' | 'mask'; // The output type. (Default "foreground") }, }, }); }); } }