92 lines
2.4 KiB
TypeScript
92 lines
2.4 KiB
TypeScript
import imageCompression from "browser-image-compression";
|
|
|
|
interface ImageSizeVariant {
|
|
size: "original" | "medium" | "thumbnail";
|
|
maxWidth: number;
|
|
quality: number;
|
|
suffix: string;
|
|
}
|
|
|
|
const IMAGE_VARIANTS: ImageSizeVariant[] = [
|
|
{ size: "thumbnail", maxWidth: 200, quality: 0.8, suffix: "_th" },
|
|
{ size: "medium", maxWidth: 800, quality: 0.8, suffix: "_md" },
|
|
{ size: "original", maxWidth: 4096, quality: 0.9, suffix: "" },
|
|
];
|
|
|
|
interface ResizedImage {
|
|
variant: ImageSizeVariant;
|
|
file: File;
|
|
}
|
|
|
|
/**
|
|
* Resize an image to all size variants (thumbnail, medium, original)
|
|
* Returns array of resized File objects
|
|
*/
|
|
export async function resizeImage(file: File): Promise<ResizedImage[]> {
|
|
const results: ResizedImage[] = [];
|
|
|
|
for (const variant of IMAGE_VARIANTS) {
|
|
const options = {
|
|
maxWidthOrHeight: variant.maxWidth,
|
|
useWebWorker: true,
|
|
initialQuality: variant.quality,
|
|
fileType: "image/jpeg" as const,
|
|
};
|
|
|
|
try {
|
|
const compressedFile = await imageCompression(file, options);
|
|
|
|
// Create new File with variant-specific name
|
|
const variantFile = new File(
|
|
[compressedFile],
|
|
generateVariantFilename(file.name, variant.suffix),
|
|
{ type: "image/jpeg" }
|
|
);
|
|
|
|
results.push({
|
|
variant,
|
|
file: variantFile,
|
|
});
|
|
} catch (error) {
|
|
console.error(`Failed to resize image for ${variant.size}:`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
/**
|
|
* Generate filename with variant suffix
|
|
* e.g., "photo.png" + "_th" => "photo_th.jpg"
|
|
*/
|
|
function generateVariantFilename(
|
|
originalName: string,
|
|
suffix: string
|
|
): string {
|
|
const lastDot = originalName.lastIndexOf(".");
|
|
const baseName = lastDot === -1 ? originalName : originalName.substring(0, lastDot);
|
|
return `${baseName}${suffix}.jpg`;
|
|
}
|
|
|
|
/**
|
|
* Derive S3 key for a specific variant from the base key
|
|
* e.g., "items/uuid.jpg" + "_th" => "items/uuid_th.jpg"
|
|
*/
|
|
export function getVariantKey(baseKey: string, suffix: string): string {
|
|
if (!suffix) return baseKey;
|
|
const lastDot = baseKey.lastIndexOf(".");
|
|
if (lastDot === -1) return `${baseKey}${suffix}`;
|
|
return `${baseKey.substring(0, lastDot)}${suffix}${baseKey.substring(lastDot)}`;
|
|
}
|
|
|
|
/**
|
|
* Get the suffix for a given size
|
|
*/
|
|
export function getSizeSuffix(
|
|
size: "thumbnail" | "medium" | "original"
|
|
): string {
|
|
const variant = IMAGE_VARIANTS.find((v) => v.size === size);
|
|
return variant?.suffix || "";
|
|
}
|