import { existsSync } from 'fs' import path from 'path' import sharp from 'sharp' import { buildPublicDisplayUrl, buildWhiteBackgroundPublicDisplayPathFromAssetPath, } from '@/lib/public-display' import { getWhiteBackgroundPreviewRelativePathFromAssetPath } from '@/lib/standard-model-white-background' import { withImageProcessingSlot } from '@/lib/image-processing-limiter' import { configureSharpRuntime } from '@/lib/sharp-runtime' import { STANDARD_MODEL_WHITE_BG_UPLOAD_LIMITS } from '@/lib/standard-model-white-background-upload-guard' configureSharpRuntime() export const WHITE_BACKGROUND_PREVIEW_MAX_DIMENSION = 1500 const WHITE_BACKGROUND_ORIGINAL_WEBP_OPTIONS = { quality: 92, alphaQuality: 100, } const WHITE_BACKGROUND_PREVIEW_WEBP_OPTIONS = { quality: 82, alphaQuality: 100, } function isHttpUrl(url?: string | null): boolean { return /^https?:\/\//i.test(String(url || '').trim()) } function normalizeRootRelativePath(fileUrl: string): string { const normalized = fileUrl.trim().replace(/\\/g, '/').replace(/^\.?\//, '') return normalized ? `/${normalized}` : '' } function resolveAbsoluteLocalPath(fileUrl: string): string { const normalized = fileUrl.trim().replace(/\\/g, '/') if (path.isAbsolute(normalized)) { return normalized } return path.join(process.cwd(), normalized.replace(/^\/+/, '')) } export async function buildWhiteBackgroundWebpVariants(buffer: Buffer) { return withImageProcessingSlot(async () => { const sharpOptions = { limitInputPixels: STANDARD_MODEL_WHITE_BG_UPLOAD_LIMITS.maxPixelsPerImage, sequentialRead: true, failOn: 'error' as const, } const original = await sharp(buffer, sharpOptions) .rotate() .webp(WHITE_BACKGROUND_ORIGINAL_WEBP_OPTIONS) .toBuffer() const preview = await sharp(buffer, sharpOptions) .rotate() .resize({ width: WHITE_BACKGROUND_PREVIEW_MAX_DIMENSION, height: WHITE_BACKGROUND_PREVIEW_MAX_DIMENSION, fit: 'inside', withoutEnlargement: true, }) .webp(WHITE_BACKGROUND_PREVIEW_WEBP_OPTIONS) .toBuffer() return { original, preview, } }) } export function resolveWhiteBackgroundPreviewFileUrl(fileUrl?: string | null): string | null { const normalizedFileUrl = String(fileUrl || '').trim() if (!normalizedFileUrl) { return null } if (isHttpUrl(normalizedFileUrl)) { return normalizedFileUrl } const previewRelativePath = getWhiteBackgroundPreviewRelativePathFromAssetPath(normalizedFileUrl) if (previewRelativePath) { const previewAbsolutePath = resolveAbsoluteLocalPath(previewRelativePath) if (existsSync(previewAbsolutePath)) { return normalizeRootRelativePath(previewRelativePath) } } const publicDisplayPath = buildWhiteBackgroundPublicDisplayPathFromAssetPath(normalizedFileUrl) const publicDisplayUrl = publicDisplayPath ? buildPublicDisplayUrl(publicDisplayPath) : null if (publicDisplayUrl) { return publicDisplayUrl } return normalizeRootRelativePath(normalizedFileUrl) }