102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
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)
|
|
}
|