sp/src/components/Tools/ImageResize.jsx

133 lines
4.2 KiB
JavaScript

import React, { useState, useEffect } from "react";
import { fromBlob, blobToURL } from "image-resize-compress";
import { Button } from "../ui/button";
import {
ImageIcon,
DownloadIcon,
SlidersHorizontal,
FileImage,
} from "lucide-react";
export default function ImageResize() {
const [previewUrl, setPreviewUrl] = useState(null);
const [resizedBlob, setResizedBlob] = useState(null);
const [imgQuality, setImgQuality] = useState(80);
const [selectedFile, setSelectedFile] = useState(null);
const [originalSize, setOriginalSize] = useState(0);
const [resizedSize, setResizedSize] = useState(0);
const [originalExtension, setOriginalExtension] = useState("webp");
useEffect(() => {
const resizeImage = async () => {
if (!selectedFile) return;
try {
const width = "auto";
const height = "auto";
const ext = selectedFile.name.split(".").pop().toLowerCase();
setOriginalExtension(ext);
setOriginalSize((selectedFile.size / 1024).toFixed(2)); // KB
// Only apply quality change for JPEG or WebP
const format = ["jpg", "jpeg", "webp"].includes(ext)
? ext
: "jpeg"; // fallback to jpeg for better quality control
const resized = await fromBlob(selectedFile, imgQuality, width, height, format);
const url = await blobToURL(resized);
setResizedBlob(resized);
setResizedSize((resized.size / 1024).toFixed(2)); // KB
setPreviewUrl(url);
} catch (err) {
console.error("Image resizing failed:", err);
}
};
resizeImage();
}, [selectedFile, imgQuality]);
const handleFileChange = (event) => {
const file = event.target.files[0];
if (file) {
setSelectedFile(file);
}
};
const handleDownload = () => {
if (!resizedBlob) return;
const link = document.createElement("a");
link.href = URL.createObjectURL(resizedBlob);
link.download = `resized-image.${originalExtension}`;
link.click();
};
return (
<div className="min-h-screen text-white p-6 flex items-center justify-center">
<div className="bg-gray-800 rounded-2xl shadow-lg w-full max-w-2xl p-6 space-y-6">
<h2 className="text-2xl font-bold flex items-center gap-2 text-[#6d9e37]">
<ImageIcon className="w-6 h-6" />
Image Resizer
</h2>
<label className="flex items-center gap-2 text-sm text-gray-300 font-medium">
<FileImage className="w-4 h-4" />
Choose an image
</label>
<input
type="file"
accept="image/*"
onChange={handleFileChange}
className="w-full p-2 bg-gray-700 border border-gray-600 rounded-lg text-sm file:bg-[#6d9e37] file:text-white file:border-0 file:px-3 file:py-1"
/>
<div className="flex flex-col gap-2">
<label className="text-sm font-medium flex items-center gap-1">
<SlidersHorizontal className="w-4 h-4" />
Quality: <span className="text-[#6d9e37]">{imgQuality}%</span>
</label>
<input
type="range"
min="1"
max="100"
value={imgQuality}
onChange={(e) => setImgQuality(e.target.value)}
className="w-full accent-[#6d9e37]"
/>
</div>
{previewUrl && (
<div className="border-t border-gray-700 pt-4 space-y-3">
<div className="text-sm text-gray-300 grid grid-cols-2 gap-2">
<p>
<strong>Original Size:</strong> {originalSize} KB
</p>
<p>
<strong>Resized Size:</strong> {resizedSize} KB
</p>
</div>
<div>
<p className="text-sm font-medium text-gray-400 mb-2">Preview:</p>
<img
src={previewUrl}
alt="Resized Preview"
className="w-full h-auto max-h-96 object-contain rounded-lg border border-gray-700"
/>
</div>
<Button
onClick={handleDownload}
className="mt-4 w-full gap-2"
>
<DownloadIcon className="w-5 h-5" />
Download Resized Image
</Button>
</div>
)}
</div>
</div>
);
}