mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat(image-engine): add Sharp wrapper with 14 image operations
Operations: resize, crop, rotate, flip, convert, compress, strip-metadata, brightness, contrast, saturation, color-channels, grayscale, sepia, invert. Includes format detection, MIME mapping, metadata parsing, and engine orchestrator.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import sharp from "sharp";
|
||||
import type { ImageInfo } from "../types.js";
|
||||
|
||||
/**
|
||||
* Extract comprehensive image metadata from a buffer.
|
||||
*/
|
||||
export async function getImageInfo(buffer: Buffer): Promise<ImageInfo> {
|
||||
const metadata = await sharp(buffer).metadata();
|
||||
|
||||
return {
|
||||
width: metadata.width ?? 0,
|
||||
height: metadata.height ?? 0,
|
||||
format: metadata.format ?? "unknown",
|
||||
channels: metadata.channels ?? 0,
|
||||
size: buffer.length,
|
||||
hasAlpha: metadata.hasAlpha ?? false,
|
||||
metadata: {
|
||||
space: metadata.space,
|
||||
density: metadata.density,
|
||||
isProgressive: metadata.isProgressive,
|
||||
hasProfile: metadata.hasProfile,
|
||||
orientation: metadata.orientation,
|
||||
exif: metadata.exif ? true : false,
|
||||
icc: metadata.icc ? true : false,
|
||||
xmp: metadata.xmp ? true : false,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
const EXT_TO_MIME: Record<string, string> = {
|
||||
jpg: "image/jpeg",
|
||||
jpeg: "image/jpeg",
|
||||
png: "image/png",
|
||||
webp: "image/webp",
|
||||
avif: "image/avif",
|
||||
tiff: "image/tiff",
|
||||
tif: "image/tiff",
|
||||
gif: "image/gif",
|
||||
bmp: "image/bmp",
|
||||
svg: "image/svg+xml",
|
||||
ico: "image/x-icon",
|
||||
heif: "image/heif",
|
||||
heic: "image/heic",
|
||||
};
|
||||
|
||||
const MIME_TO_EXT: Record<string, string> = {
|
||||
"image/jpeg": "jpg",
|
||||
"image/png": "png",
|
||||
"image/webp": "webp",
|
||||
"image/avif": "avif",
|
||||
"image/tiff": "tiff",
|
||||
"image/gif": "gif",
|
||||
"image/bmp": "bmp",
|
||||
"image/svg+xml": "svg",
|
||||
"image/x-icon": "ico",
|
||||
"image/heif": "heif",
|
||||
"image/heic": "heic",
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the MIME type for a file extension (without dot).
|
||||
*/
|
||||
export function extToMime(ext: string): string {
|
||||
const normalized = ext.toLowerCase().replace(/^\./, "");
|
||||
return EXT_TO_MIME[normalized] ?? "application/octet-stream";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file extension for a MIME type (without dot).
|
||||
*/
|
||||
export function mimeToExt(mime: string): string {
|
||||
const normalized = mime.toLowerCase();
|
||||
return MIME_TO_EXT[normalized] ?? "bin";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MIME type for a Sharp format string.
|
||||
*/
|
||||
export function formatToMime(format: string): string {
|
||||
const normalized = format.toLowerCase();
|
||||
if (normalized === "jpeg") return "image/jpeg";
|
||||
return EXT_TO_MIME[normalized] ?? "application/octet-stream";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file extension for a Sharp format string.
|
||||
*/
|
||||
export function formatToExt(format: string): string {
|
||||
const normalized = format.toLowerCase();
|
||||
if (normalized === "jpeg") return "jpg";
|
||||
return normalized;
|
||||
}
|
||||
Reference in New Issue
Block a user