feat: store original EXIF-stripped image for debugging

- Save original image before crop/rotation with '_debug_original' variant
- Store original_photo_path in labels_data.image_processing for debug access
- Update DebugRotationPanel to display original image instead of processed
- Update ItemDetailModal to pass original image path to debug panel
- Enables accurate crop/rotation visualization with true original image
This commit is contained in:
2026-04-22 11:13:09 +03:00
parent 9f65d427a0
commit c46c8414b8
3 changed files with 57 additions and 2 deletions

View File

@@ -7,6 +7,7 @@ import { X } from 'lucide-react';
interface DebugRotationPanelProps {
item: Item;
imageUrl: string;
originalPhotoPath?: string;
originalCropBounds?: { x: number; y: number; width: number; height: number };
originalRotation?: number;
imageProcessing?: any;
@@ -16,6 +17,7 @@ interface DebugRotationPanelProps {
export function DebugRotationPanel({
item,
imageUrl,
originalPhotoPath,
originalCropBounds,
originalRotation = 0,
imageProcessing,
@@ -28,6 +30,9 @@ export function DebugRotationPanel({
const [imageLoaded, setImageLoaded] = useState(false);
const [scaledDimensions, setScaledDimensions] = useState({ width: 0, height: 0, scale: 1 });
// Use original photo path if available, otherwise fall back to processed image URL
const displayImageUrl = originalPhotoPath ? originalPhotoPath : imageUrl;
const commonAngles = [
{ label: '0°', value: 0 },
{ label: '+22°', value: 22 },
@@ -61,8 +66,8 @@ export function DebugRotationPanel({
addLog(`📐 Scaled to fit: ${scaledW.toFixed(0)}×${scaledH.toFixed(0)}px (scale ${scale.toFixed(2)}x)`);
};
img.onerror = () => addLog('❌ Failed to load image');
img.src = imageUrl;
}, [imageUrl]);
img.src = displayImageUrl;
}, [displayImageUrl]);
useEffect(() => {
if (!imageLoaded || !imageRef.current || !canvasRef.current || !originalCropBounds) return;

View File

@@ -198,6 +198,19 @@ export default function ItemDetailModal({
<DebugRotationPanel
item={item}
imageUrl={buildPhotoUrl(backendUrl, currentPhoto.full_url)}
originalPhotoPath={
item.labels_data
? (() => {
try {
const parsed = JSON.parse(item.labels_data);
const origPath = parsed.image_processing?.original_photo_path;
return origPath ? buildPhotoUrl(backendUrl, origPath) : undefined;
} catch {
return undefined;
}
})()
: undefined
}
originalCropBounds={item.labels_data ? JSON.parse(item.labels_data).image_processing?.crop_bounds : undefined}
originalRotation={item.labels_data ? JSON.parse(item.labels_data).image_processing?.rotation_degrees : undefined}
imageProcessing={item.labels_data ? JSON.parse(item.labels_data).image_processing : undefined}