mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix(image-engine): support sharp 0.35 types
This commit is contained in:
@@ -34,6 +34,7 @@ import type {
|
||||
Sharp,
|
||||
SharpenAdvancedOptions,
|
||||
SharpenOptions,
|
||||
SharpFormat,
|
||||
StripMetadataOptions,
|
||||
} from "./types.js";
|
||||
import { getImageInfo } from "./utils/metadata.js";
|
||||
@@ -109,7 +110,7 @@ export async function processImage(
|
||||
if (!sharpFormat) {
|
||||
throw new Error(`Unsupported output format: ${outputFormat}`);
|
||||
}
|
||||
image = image.toFormat(sharpFormat as keyof sharp.FormatEnum);
|
||||
image = image.toFormat(sharpFormat as SharpFormat);
|
||||
}
|
||||
|
||||
const buffer = await image.toBuffer();
|
||||
|
||||
@@ -5,6 +5,8 @@ import type {
|
||||
CorrectionParams,
|
||||
EnhancementMode,
|
||||
Sharp,
|
||||
SharpChannelStats,
|
||||
SharpMetadata,
|
||||
} from "../types.js";
|
||||
|
||||
/**
|
||||
@@ -123,9 +125,9 @@ export async function analyzeImage(buffer: Buffer): Promise<AnalysisResult> {
|
||||
}
|
||||
|
||||
function computeScores(
|
||||
rCh: sharp.ChannelStats,
|
||||
gCh: sharp.ChannelStats,
|
||||
bCh: sharp.ChannelStats,
|
||||
rCh: SharpChannelStats,
|
||||
gCh: SharpChannelStats,
|
||||
bCh: SharpChannelStats,
|
||||
meanLum: number,
|
||||
stdevLum: number,
|
||||
isGrayscale: boolean,
|
||||
@@ -200,7 +202,7 @@ function detectIssues(scores: AnalysisScores): string[] {
|
||||
return issues;
|
||||
}
|
||||
|
||||
function suggestMode(scores: AnalysisScores, _meta: sharp.Metadata): EnhancementMode {
|
||||
function suggestMode(scores: AnalysisScores, _meta: SharpMetadata): EnhancementMode {
|
||||
if (scores.exposure < 30) return "low-light";
|
||||
if (scores.contrast > 60 && scores.saturation < 30) return "document";
|
||||
return "auto";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import sharp from "sharp";
|
||||
import type { CompressOptions, Sharp } from "../types.js";
|
||||
import type { CompressOptions, Sharp, SharpFormat } from "../types.js";
|
||||
|
||||
const FORMAT_MAP: Record<string, string> = {
|
||||
const FORMAT_MAP: Record<string, SharpFormat> = {
|
||||
jpg: "jpeg",
|
||||
jpeg: "jpeg",
|
||||
png: "png",
|
||||
@@ -16,7 +16,7 @@ const FORMAT_MAP: Record<string, string> = {
|
||||
/** Formats that Sharp cannot encode — fall back to PNG for output. */
|
||||
const NO_ENCODER = new Set(["svg", "raw", "tga", "psd", "exr", "hdr"]);
|
||||
|
||||
function formatOpts(format: string, quality: number): Record<string, unknown> {
|
||||
function formatOpts(format: SharpFormat, quality: number): Record<string, unknown> {
|
||||
const opts: Record<string, unknown> = { quality };
|
||||
if (format === "avif") opts.effort = 4;
|
||||
return opts;
|
||||
@@ -31,7 +31,7 @@ export async function compress(image: Sharp, options: CompressOptions): Promise<
|
||||
const safeDetected = NO_ENCODER.has(detected) ? "png" : detected;
|
||||
const outputFormat = (FORMAT_MAP[format ?? ""] ??
|
||||
FORMAT_MAP[safeDetected] ??
|
||||
safeDetected) as keyof sharp.FormatEnum;
|
||||
safeDetected) as SharpFormat;
|
||||
|
||||
if (targetSizeBytes !== undefined) {
|
||||
if (targetSizeBytes <= 0) {
|
||||
@@ -52,7 +52,7 @@ export async function compress(image: Sharp, options: CompressOptions): Promise<
|
||||
async function findBestQuality(
|
||||
inputBuffer: Buffer,
|
||||
resize: { width: number; height: number } | null,
|
||||
format: keyof sharp.FormatEnum,
|
||||
format: SharpFormat,
|
||||
targetBytes: number,
|
||||
): Promise<number | null> {
|
||||
let low = 1;
|
||||
@@ -82,7 +82,7 @@ async function findBestQuality(
|
||||
|
||||
async function compressToTargetSize(
|
||||
inputBuffer: Buffer,
|
||||
format: keyof sharp.FormatEnum,
|
||||
format: SharpFormat,
|
||||
targetBytes: number,
|
||||
): Promise<Sharp> {
|
||||
const quality = await findBestQuality(inputBuffer, null, format, targetBytes);
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import type sharp from "sharp";
|
||||
import type { ConvertOptions, Sharp } from "../types.js";
|
||||
import type { ConvertOptions, Sharp, SharpFormat } from "../types.js";
|
||||
|
||||
/**
|
||||
* Maps user-facing format names to Sharp format strings.
|
||||
* Note: HEIC is excluded because Sharp cannot encode HEVC.
|
||||
* HEIC encoding is handled at the API route level via heif-enc.
|
||||
*/
|
||||
const FORMAT_MAP: Record<string, string> = {
|
||||
const FORMAT_MAP: Partial<Record<ConvertOptions["format"], SharpFormat>> = {
|
||||
jpg: "jpeg",
|
||||
png: "png",
|
||||
webp: "webp",
|
||||
@@ -32,5 +31,5 @@ export async function convert(image: Sharp, options: ConvertOptions): Promise<Sh
|
||||
formatOptions.quality = quality;
|
||||
}
|
||||
|
||||
return image.toFormat(sharpFormat as keyof sharp.FormatEnum, formatOptions);
|
||||
return image.toFormat(sharpFormat, formatOptions);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type sharp from "sharp";
|
||||
import type { ChannelStats, FormatEnum, Metadata, Sharp as SharpInstance } from "sharp";
|
||||
|
||||
export type Sharp = sharp.Sharp;
|
||||
export type Sharp = SharpInstance;
|
||||
export type SharpFormat = Extract<keyof FormatEnum, string> | "avif";
|
||||
export type SharpChannelStats = ChannelStats;
|
||||
export type SharpMetadata = Metadata;
|
||||
|
||||
export interface ImageInfo {
|
||||
width: number;
|
||||
|
||||
Reference in New Issue
Block a user