Files
Comfyui-LayerForge/js/utils/ImageUploadUtils.js
Dariusz L 7e71d3ec3e Refactor image, mask, and notification logic into utils
Extracted image upload, mask processing, notification, and preview update logic into dedicated utility modules. Updated MaskEditorIntegration and SAMDetectorIntegration to use these new utilities, reducing code duplication and improving maintainability.
2025-07-27 18:19:35 +02:00

107 lines
3.8 KiB
JavaScript

import { api } from "../../../scripts/api.js";
import { createModuleLogger } from "./LoggerUtils.js";
const log = createModuleLogger('ImageUploadUtils');
/**
* Uploads an image blob to ComfyUI server and returns image element
* @param blob - Image blob to upload
* @param options - Upload options
* @returns Promise with upload result
*/
export async function uploadImageBlob(blob, options = {}) {
const { filenamePrefix = 'layerforge', overwrite = true, type = 'temp', nodeId } = options;
// Generate unique filename
const timestamp = Date.now();
const nodeIdSuffix = nodeId ? `-${nodeId}` : '';
const filename = `${filenamePrefix}${nodeIdSuffix}-${timestamp}.png`;
log.debug('Uploading image blob:', {
filename,
blobSize: blob.size,
type,
overwrite
});
// Create FormData
const formData = new FormData();
formData.append("image", blob, filename);
formData.append("overwrite", overwrite.toString());
formData.append("type", type);
// Upload to server
const response = await api.fetchApi("/upload/image", {
method: "POST",
body: formData,
});
if (!response.ok) {
const error = new Error(`Failed to upload image: ${response.statusText}`);
log.error('Image upload failed:', error);
throw error;
}
const data = await response.json();
log.debug('Image uploaded successfully:', data);
// Create image element with proper URL
const imageUrl = api.apiURL(`/view?filename=${encodeURIComponent(data.name)}&type=${data.type}&subfolder=${data.subfolder}`);
const imageElement = new Image();
imageElement.crossOrigin = "anonymous";
// Wait for image to load
await new Promise((resolve, reject) => {
imageElement.onload = () => {
log.debug("Uploaded image loaded successfully", {
width: imageElement.width,
height: imageElement.height,
src: imageElement.src.substring(0, 100) + '...'
});
resolve();
};
imageElement.onerror = (error) => {
log.error("Failed to load uploaded image", error);
reject(new Error("Failed to load uploaded image"));
};
imageElement.src = imageUrl;
});
return {
data,
filename,
imageUrl,
imageElement
};
}
/**
* Uploads canvas content as image blob
* @param canvas - Canvas element or Canvas object with canvasLayers
* @param options - Upload options
* @returns Promise with upload result
*/
export async function uploadCanvasAsImage(canvas, options = {}) {
let blob = null;
// Handle different canvas types
if (canvas.canvasLayers && typeof canvas.canvasLayers.getFlattenedCanvasAsBlob === 'function') {
// LayerForge Canvas object
blob = await canvas.canvasLayers.getFlattenedCanvasAsBlob();
}
else if (canvas instanceof HTMLCanvasElement) {
// Standard HTML Canvas
blob = await new Promise(resolve => canvas.toBlob(resolve));
}
else {
throw new Error("Unsupported canvas type");
}
if (!blob) {
throw new Error("Failed to generate canvas blob");
}
return uploadImageBlob(blob, options);
}
/**
* Uploads canvas with mask as image blob
* @param canvas - Canvas object with canvasLayers
* @param options - Upload options
* @returns Promise with upload result
*/
export async function uploadCanvasWithMaskAsImage(canvas, options = {}) {
if (!canvas.canvasLayers || typeof canvas.canvasLayers.getFlattenedCanvasWithMaskAsBlob !== 'function') {
throw new Error("Canvas does not support mask operations");
}
const blob = await canvas.canvasLayers.getFlattenedCanvasWithMaskAsBlob();
if (!blob) {
throw new Error("Failed to generate canvas with mask blob");
}
return uploadImageBlob(blob, options);
}