gongxiangp2/lib/white-background-preview.ts
2026-05-07 16:37:22 +08:00

89 lines
2.5 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'
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) {
const original = await sharp(buffer)
.rotate()
.webp(WHITE_BACKGROUND_ORIGINAL_WEBP_OPTIONS)
.toBuffer()
const preview = await sharp(buffer)
.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)
}