diff --git a/packages/builder/src/image/blurhash.ts b/packages/builder/src/image/blurhash.ts index 8bfe89aa..aee11754 100644 --- a/packages/builder/src/image/blurhash.ts +++ b/packages/builder/src/image/blurhash.ts @@ -4,11 +4,14 @@ import { rgbaToThumbHash } from 'thumbhash' import { logger } from '../logger/index.js' // 生成 blurhash(基于缩略图数据,保持长宽比) -export async function generateBlurhash(thumbnailBuffer: Buffer): Promise { +export async function generateBlurhash( + thumbnailBuffer: Buffer, + limitInputPixels?: number | boolean, +): Promise { try { // 复用缩略图的 Sharp 实例来生成 blurhash // 确保转换为 raw RGBA 格式 - const { data, info } = await sharp(thumbnailBuffer) + const { data, info } = await sharp(thumbnailBuffer, { limitInputPixels }) .resize(100, 100, { fit: 'inside' }) .raw() .ensureAlpha() diff --git a/packages/builder/src/image/thumbnail.ts b/packages/builder/src/image/thumbnail.ts index 561f8ce9..f439649b 100644 --- a/packages/builder/src/image/thumbnail.ts +++ b/packages/builder/src/image/thumbnail.ts @@ -79,7 +79,11 @@ async function processExistingThumbnail(photoId: string): Promise { +async function generateNewThumbnail( + imageBuffer: Buffer, + photoId: string, + limitInputPixels?: number | boolean, +): Promise { const { thumbnailPath, thumbnailUrl } = getThumbnailPaths(photoId) const log = getGlobalLoggers().thumbnail @@ -88,7 +92,7 @@ async function generateNewThumbnail(imageBuffer: Buffer, photoId: string): Promi try { // 创建 Sharp 实例,复用于缩略图和 blurhash 生成 - const sharpInstance = sharp(imageBuffer).rotate() // 自动根据 EXIF 旋转 + const sharpInstance = sharp(imageBuffer, { limitInputPixels }).rotate() // 自动根据 EXIF 旋转 // 生成缩略图 const thumbnailBuffer = await sharpInstance @@ -122,6 +126,7 @@ export async function generateThumbnailAndBlurhash( imageBuffer: Buffer, photoId: string, forceRegenerate = false, + limitInputPixels?: number | boolean, ): Promise { const thumbnailLog = getGlobalLoggers().thumbnail @@ -139,7 +144,7 @@ export async function generateThumbnailAndBlurhash( } // 生成新的缩略图 - return await generateNewThumbnail(imageBuffer, photoId) + return await generateNewThumbnail(imageBuffer, photoId, limitInputPixels) } catch (error) { thumbnailLog.error(`处理失败:${photoId}`, error) return createFailureResult() diff --git a/packages/builder/src/photo/data-processors.ts b/packages/builder/src/photo/data-processors.ts index 181c8520..6ee429f9 100644 --- a/packages/builder/src/photo/data-processors.ts +++ b/packages/builder/src/photo/data-processors.ts @@ -10,6 +10,7 @@ import { extractExifData } from '../image/exif.js' import { calculateHistogramAndAnalyzeTone } from '../image/histogram.js' import { generateThumbnailAndBlurhash, thumbnailExists } from '../image/thumbnail.js' import { workdir } from '../path.js' +import { getPhotoExecutionContext } from './execution-context.js' import { getGlobalLoggers } from './logger-adapter.js' import type { PhotoProcessorOptions } from './processor.js' @@ -30,6 +31,8 @@ export async function processThumbnailAndBlurhash( options: PhotoProcessorOptions, ): Promise { const loggers = getGlobalLoggers() + const { builder } = getPhotoExecutionContext() + const { limitInputPixels } = builder.getConfig().system.processing // 检查是否可以复用现有数据 if ( @@ -62,6 +65,7 @@ export async function processThumbnailAndBlurhash( imageBuffer, photoId, options.isForceMode || options.isForceThumbnails, + limitInputPixels, ) return { diff --git a/packages/builder/src/photo/image-pipeline.ts b/packages/builder/src/photo/image-pipeline.ts index 865019b4..26a766de 100644 --- a/packages/builder/src/photo/image-pipeline.ts +++ b/packages/builder/src/photo/image-pipeline.ts @@ -83,10 +83,12 @@ export async function preprocessImage( */ export async function processImageWithSharp(imageBuffer: Buffer, photoKey: string): Promise { const loggers = getGlobalLoggers() + const { builder } = getPhotoExecutionContext() + const { limitInputPixels } = builder.getConfig().system.processing try { // 创建 Sharp 实例,复用于多个操作 - let sharpInstance = sharp(imageBuffer) + let sharpInstance = sharp(imageBuffer, { limitInputPixels }) let processedBuffer = imageBuffer // 处理 BMP diff --git a/packages/builder/src/types/config.ts b/packages/builder/src/types/config.ts index 477648dd..0188676a 100644 --- a/packages/builder/src/types/config.ts +++ b/packages/builder/src/types/config.ts @@ -20,6 +20,14 @@ export interface SystemProcessingSettings { enableLivePhotoDetection: boolean supportedFormats?: Set digestSuffixLength?: number + /** + * Do not process input images where the number of pixels (width x height) exceeds this limit. + * - `number`: An integral Number of pixels as the limit + * - `false` or `0`: Remove limit entirely + * - `true` or `undefined`: Use sharp's default limit of 268402689 (0x3FFF x 0x3FFF) + * @default undefined (uses sharp's default: 268402689) + */ + limitInputPixels?: number | boolean } export interface SystemObservabilitySettings {