File size: 5,932 Bytes
e74ba5a d062149 e74ba5a d062149 e74ba5a 50fd07f d062149 4dbceee d062149 e74ba5a 9c7e72f e74ba5a 9c7e72f e74ba5a 9c7e72f e74ba5a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
import React, { useState, useEffect, useRef } from 'react';
import { SlidersHorizontal, Sparkles, Brain } from 'lucide-react';
const ImagePreview = ({ imageData, fileName, onResolutionChange, onEnhanceToggle, isEnhanced, onReasoningModeToggle, useReasoning }) => {
const [resolution, setResolution] = useState(100);
const canvasRef = useRef(null);
const [originalDimensions, setOriginalDimensions] = useState({ width: 0, height: 0 });
const [currentDimensions, setCurrentDimensions] = useState({ width: 0, height: 0 });
useEffect(() => {
if (!imageData || !canvasRef.current) return;
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = () => {
if (!originalDimensions.width) {
setOriginalDimensions({ width: img.width, height: img.height });
}
// Calculate new dimensions based on resolution
const newWidth = Math.floor(img.width * (resolution / 100));
const newHeight = Math.floor(img.height * (resolution / 100));
setCurrentDimensions({ width: newWidth, height: newHeight });
// Set display size (max 400px width for preview)
const displayWidth = Math.min(400, newWidth);
const displayHeight = Math.floor(newHeight * (displayWidth / newWidth));
canvas.width = displayWidth;
canvas.height = displayHeight;
// Draw scaled image
ctx.drawImage(img, 0, 0, displayWidth, displayHeight);
// Notify parent of resolution change
if (onResolutionChange) {
const resizedCanvas = document.createElement('canvas');
resizedCanvas.width = newWidth;
resizedCanvas.height = newHeight;
const resizedCtx = resizedCanvas.getContext('2d');
resizedCtx.drawImage(img, 0, 0, newWidth, newHeight);
const resizedDataUrl = resizedCanvas.toDataURL('image/jpeg', 0.95);
onResolutionChange(resizedDataUrl, resolution);
}
};
img.src = imageData;
}, [imageData, resolution]);
const handleResolutionChange = (e) => {
const newResolution = parseInt(e.target.value);
setResolution(newResolution);
};
return (
<div className="bg-white rounded-lg shadow-md p-4 space-y-3">
<div className="flex items-center justify-between">
<h4 className="text-sm font-semibold text-gray-700">Preview: {fileName}</h4>
<span className="text-xs text-gray-500">
{currentDimensions.width} × {currentDimensions.height}px
</span>
</div>
<div className="bg-gray-50 rounded-lg p-3 flex justify-center">
<canvas ref={canvasRef} className="rounded shadow-sm" />
</div>
{/* Enhance Button */}
<button
onClick={() => onEnhanceToggle && onEnhanceToggle()}
className={`w-full py-2 px-4 rounded-lg font-medium transition-all flex items-center justify-center gap-2 ${
isEnhanced
? 'bg-purple-600 hover:bg-purple-700 text-white shadow-lg'
: 'bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white shadow-md'
}`}
>
<Sparkles className="w-4 h-4" />
{isEnhanced ? 'Enhanced ✓' : 'Enhance Image'}
</button>
{isEnhanced && (
<div className="bg-purple-50 border border-purple-200 rounded p-2 text-xs text-purple-700">
✨ Image will be enhanced with OpenCV (CLAHE, denoising, sharpening) before processing
</div>
)}
{/* Reasoning Mode Toggle */}
<button
onClick={() => onReasoningModeToggle && onReasoningModeToggle()}
className={`w-full py-2 px-4 rounded-lg font-medium transition-all flex items-center justify-center gap-2 ${
useReasoning
? 'bg-blue-600 hover:bg-blue-700 text-white shadow-lg'
: 'bg-gradient-to-r from-blue-500 to-cyan-500 hover:from-blue-600 hover:to-cyan-600 text-white shadow-md'
}`}
>
<Brain className="w-4 h-4" />
{useReasoning ? 'Reasoning ✓' : 'Simple Mode'}
</button>
{useReasoning && (
<div className="bg-blue-50 border border-blue-200 rounded p-2 text-xs text-blue-700">
🧠 VLM will use 2-step reasoning: first analyze document structure, then extract fields
</div>
)}
<div className="space-y-2">
<div className="flex items-center justify-between">
<label className="text-sm font-medium text-gray-700 flex items-center gap-2">
<SlidersHorizontal className="w-4 h-4" />
Resolution
</label>
<span className="text-sm font-bold text-primary-600">{resolution}%</span>
</div>
<input
type="range"
min="10"
max="100"
value={resolution}
onChange={handleResolutionChange}
className="w-full h-2 rounded-lg cursor-pointer"
style={{ accentColor: '#2563eb' }} // Tailwind blue-600
/>
<div className="flex justify-between text-xs text-gray-500">
<span>Low Quality</span>
<span>Original</span>
</div>
{resolution < 100 && (
<div className="bg-blue-50 border border-blue-200 rounded p-2 text-xs text-blue-700">
💡 Lower resolution = faster processing & lower cost
</div>
)}
</div>
<div className="text-xs text-gray-500 space-y-1">
<div className="flex justify-between">
<span>Original:</span>
<span className="font-medium">{originalDimensions.width} × {originalDimensions.height}px</span>
</div>
<div className="flex justify-between">
<span>Processing:</span>
<span className="font-medium text-primary-600">{currentDimensions.width} × {currentDimensions.height}px</span>
</div>
</div>
</div>
);
};
export default ImagePreview;
|