Untitled
unknown
plain_text
a year ago
4.7 kB
3
Indexable
import React, { useState, useRef } from 'react'; import { AlertCircle } from 'lucide-react'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; const ImageProcessor = () => { const [originalImage, setOriginalImage] = useState(null); const [processedImage, setProcessedImage] = useState(null); const [scaleFactor, setScaleFactor] = useState(0.5); const [error, setError] = useState(null); const canvasRef = useRef(null); const handleImageUpload = (event) => { const file = event.target.files[0]; const reader = new FileReader(); reader.onload = (e) => { const img = new Image(); img.onload = () => { setOriginalImage(img); setProcessedImage(null); setError(null); }; img.src = e.target.result; }; reader.readAsDataURL(file); }; const processImage = () => { if (!originalImage) { setError("Please upload an image first."); return; } const canvas = canvasRef.current; const ctx = canvas.getContext('2d'); // Set canvas size to match original image canvas.width = originalImage.width; canvas.height = originalImage.height; // Draw original image ctx.drawImage(originalImage, 0, 0); // Get image data const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const data = imageData.data; // Calculate dimensions for downscaled image const pixelSize = Math.ceil(1 / scaleFactor); const scaledWidth = Math.floor(canvas.width / pixelSize); const scaledHeight = Math.floor(canvas.height / pixelSize); // Create a temporary canvas for the downscaled image const tempCanvas = document.createElement('canvas'); tempCanvas.width = scaledWidth; tempCanvas.height = scaledHeight; const tempCtx = tempCanvas.getContext('2d'); tempCtx.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight); // Get the downscaled image data const scaledImageData = tempCtx.getImageData(0, 0, scaledWidth, scaledHeight); const scaledData = scaledImageData.data; // Process the image with large pixel effect for (let y = 0; y < canvas.height; y++) { for (let x = 0; x < canvas.width; x++) { const srcX = Math.floor(x / pixelSize); const srcY = Math.floor(y / pixelSize); const srcIndex = (srcY * scaledWidth + srcX) * 4; const destIndex = (y * canvas.width + x) * 4; data[destIndex] = scaledData[srcIndex]; data[destIndex + 1] = scaledData[srcIndex + 1]; data[destIndex + 2] = scaledData[srcIndex + 2]; data[destIndex + 3] = scaledData[srcIndex + 3]; } } // Put the processed image data back on the canvas ctx.putImageData(imageData, 0, 0); // Set processed image setProcessedImage(canvas.toDataURL()); }; return ( <div className="max-w-2xl mx-auto p-4"> <h1 className="text-2xl font-bold mb-4">Image Processor (Large Pixel Effect)</h1> <div className="mb-4"> <input type="file" accept="image/*" onChange={handleImageUpload} className="mb-2" /> <div className="flex items-center"> <label htmlFor="scaleFactor" className="mr-2">Scale Factor:</label> <input type="number" id="scaleFactor" min="0.1" max="1" step="0.1" value={scaleFactor} onChange={(e) => setScaleFactor(parseFloat(e.target.value))} className="border rounded px-2 py-1 w-20" /> </div> </div> <button onClick={processImage} className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" > Process Image </button> {error && ( <Alert variant="destructive" className="mt-4"> <AlertCircle className="h-4 w-4" /> <AlertTitle>Error</AlertTitle> <AlertDescription>{error}</AlertDescription> </Alert> )} <div className="mt-4 flex flex-wrap"> {originalImage && ( <div className="mr-4 mb-4"> <h2 className="text-lg font-semibold mb-2">Original Image</h2> <img src={originalImage.src} alt="Original" className="max-w-full h-auto" /> </div> )} {processedImage && ( <div> <h2 className="text-lg font-semibold mb-2">Processed Image (Large Pixel Effect)</h2> <img src={processedImage} alt="Processed" className="max-w-full h-auto" /> </div> )} </div> <canvas ref={canvasRef} style={{ display: 'none' }} /> </div> ); }; export default ImageProcessor;
Editor is loading...
Leave a Comment