Files
rentall-app/frontend/src/utils/imageResizer.ts

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 || "";
}