Spaces:
Paused
Paused
Ali Mohsin
commited on
Commit
·
9c8bd0b
1
Parent(s):
44897d2
more fixes
Browse files- app.py +15 -3
- utils/image_utils.py +88 -28
app.py
CHANGED
|
@@ -823,28 +823,40 @@ def gradio_recommend(
|
|
| 823 |
if not files:
|
| 824 |
return [], {"error": "No files uploaded"}
|
| 825 |
|
| 826 |
-
#
|
|
|
|
| 827 |
file_info = []
|
| 828 |
-
for f in files:
|
| 829 |
if isinstance(f, str):
|
| 830 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 831 |
else:
|
| 832 |
file_info.append(f"Type: {type(f).__name__}, Value: {str(f)[:100]}")
|
|
|
|
| 833 |
|
| 834 |
try:
|
|
|
|
| 835 |
images = _load_images_from_files(files)
|
|
|
|
| 836 |
if not images:
|
| 837 |
error_msg = "Could not load images from uploaded files.\n\n"
|
| 838 |
error_msg += f"Files received: {len(files)}\n"
|
| 839 |
error_msg += f"File details: {', '.join(file_info[:3])}\n\n"
|
| 840 |
error_msg += f"Supported formats: {', '.join(get_supported_extensions())}\n"
|
| 841 |
error_msg += "Please ensure files are valid image files (JPG, PNG, WEBP, GIF, BMP, TIFF, etc.)"
|
|
|
|
| 842 |
return [], {"error": error_msg, "files_received": len(files), "file_info": file_info[:5]}
|
| 843 |
except Exception as e:
|
|
|
|
| 844 |
error_msg = f"Error processing files: {str(e)}\n\n"
|
| 845 |
error_msg += f"Files received: {len(files)}\n"
|
| 846 |
error_msg += f"File details: {', '.join(file_info[:3])}\n\n"
|
| 847 |
error_msg += "Please check that files are valid image files."
|
|
|
|
|
|
|
| 848 |
return [], {"error": error_msg, "exception": str(e), "files_received": len(files)}
|
| 849 |
|
| 850 |
# Tag normalization: Map frontend values to backend values
|
|
|
|
| 823 |
if not files:
|
| 824 |
return [], {"error": "No files uploaded"}
|
| 825 |
|
| 826 |
+
# Enhanced debug: Log detailed file information for API troubleshooting
|
| 827 |
+
print(f"🔍 DEBUG: gradio_recommend called with {len(files)} files")
|
| 828 |
file_info = []
|
| 829 |
+
for i, f in enumerate(files):
|
| 830 |
if isinstance(f, str):
|
| 831 |
+
from pathlib import Path
|
| 832 |
+
path = Path(f)
|
| 833 |
+
file_size = path.stat().st_size if path.exists() else 0
|
| 834 |
+
file_info.append(f"File {i+1}: {path.name} ({file_size} bytes)")
|
| 835 |
+
print(f"🔍 DEBUG: File {i+1}: path={f}, exists={path.exists()}, size={file_size}, name={path.name}")
|
| 836 |
else:
|
| 837 |
file_info.append(f"Type: {type(f).__name__}, Value: {str(f)[:100]}")
|
| 838 |
+
print(f"🔍 DEBUG: File {i+1}: type={type(f).__name__}, value={str(f)[:100]}")
|
| 839 |
|
| 840 |
try:
|
| 841 |
+
print(f"🔍 DEBUG: Attempting to load {len(files)} images...")
|
| 842 |
images = _load_images_from_files(files)
|
| 843 |
+
print(f"🔍 DEBUG: Successfully loaded {len(images)} images from {len(files)} files")
|
| 844 |
if not images:
|
| 845 |
error_msg = "Could not load images from uploaded files.\n\n"
|
| 846 |
error_msg += f"Files received: {len(files)}\n"
|
| 847 |
error_msg += f"File details: {', '.join(file_info[:3])}\n\n"
|
| 848 |
error_msg += f"Supported formats: {', '.join(get_supported_extensions())}\n"
|
| 849 |
error_msg += "Please ensure files are valid image files (JPG, PNG, WEBP, GIF, BMP, TIFF, etc.)"
|
| 850 |
+
print(f"🔍 DEBUG: ERROR - No images loaded. Files: {len(files)}, Images: {len(images)}")
|
| 851 |
return [], {"error": error_msg, "files_received": len(files), "file_info": file_info[:5]}
|
| 852 |
except Exception as e:
|
| 853 |
+
import traceback
|
| 854 |
error_msg = f"Error processing files: {str(e)}\n\n"
|
| 855 |
error_msg += f"Files received: {len(files)}\n"
|
| 856 |
error_msg += f"File details: {', '.join(file_info[:3])}\n\n"
|
| 857 |
error_msg += "Please check that files are valid image files."
|
| 858 |
+
print(f"🔍 DEBUG: EXCEPTION during image loading: {e}")
|
| 859 |
+
traceback.print_exc()
|
| 860 |
return [], {"error": error_msg, "exception": str(e), "files_received": len(files)}
|
| 861 |
|
| 862 |
# Tag normalization: Map frontend values to backend values
|
utils/image_utils.py
CHANGED
|
@@ -98,8 +98,13 @@ def load_image_from_file(
|
|
| 98 |
"""
|
| 99 |
Load an image from a file path, supporting all major formats.
|
| 100 |
|
| 101 |
-
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
Args:
|
| 105 |
filepath: Path to the image file
|
|
@@ -118,46 +123,101 @@ def load_image_from_file(
|
|
| 118 |
raise FileNotFoundError(f"Image file not found: {filepath}")
|
| 119 |
return None
|
| 120 |
|
| 121 |
-
#
|
| 122 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
try:
|
| 124 |
-
# Open image
|
| 125 |
test_img = Image.open(path)
|
| 126 |
-
|
| 127 |
test_img.close()
|
| 128 |
|
| 129 |
-
#
|
| 130 |
-
if
|
| 131 |
-
if detected_format
|
| 132 |
-
#
|
| 133 |
-
if
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
|
| 145 |
# Verify it's actually a valid image
|
| 146 |
with Image.open(path) as img:
|
| 147 |
img.verify()
|
| 148 |
|
| 149 |
except UnidentifiedImageError:
|
| 150 |
-
#
|
| 151 |
-
if
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
if raise_on_error:
|
| 153 |
raise ValueError(f"Cannot identify image format and no valid extension: {filepath}")
|
| 154 |
print(f"⚠️ Cannot identify image format: {filepath}")
|
| 155 |
return None
|
| 156 |
-
# Extension suggests it's an image, but PIL can't read it - might be corrupted
|
| 157 |
-
if raise_on_error:
|
| 158 |
-
raise ValueError(f"File has image extension but cannot be read: {filepath}")
|
| 159 |
-
print(f"⚠️ File has image extension but cannot be read: {filepath}")
|
| 160 |
-
return None
|
| 161 |
|
| 162 |
# Re-open for actual use (verify() closes the file)
|
| 163 |
img = Image.open(path)
|
|
|
|
| 98 |
"""
|
| 99 |
Load an image from a file path, supporting all major formats.
|
| 100 |
|
| 101 |
+
Enhanced to handle files without extensions (e.g., Gradio blob files)
|
| 102 |
+
by detecting format from file content (magic bytes).
|
| 103 |
+
|
| 104 |
+
Detection priority:
|
| 105 |
+
1. File extension (if present)
|
| 106 |
+
2. Magic byte detection (file content)
|
| 107 |
+
3. PIL format detection (fallback)
|
| 108 |
|
| 109 |
Args:
|
| 110 |
filepath: Path to the image file
|
|
|
|
| 123 |
raise FileNotFoundError(f"Image file not found: {filepath}")
|
| 124 |
return None
|
| 125 |
|
| 126 |
+
# Step 1: Check file extension first
|
| 127 |
+
detected_format = None
|
| 128 |
+
if is_image_file(path):
|
| 129 |
+
detected_format = get_image_format(path)
|
| 130 |
+
if detected_format:
|
| 131 |
+
print(f"🔍 Detected format from extension: {detected_format} (file: {path.name})")
|
| 132 |
+
|
| 133 |
+
# Step 2: If no extension, detect from magic bytes (file content)
|
| 134 |
+
# This is critical for Gradio blob files which have no extension
|
| 135 |
+
if not detected_format:
|
| 136 |
+
try:
|
| 137 |
+
with open(path, 'rb') as f:
|
| 138 |
+
header = f.read(12) # Read first 12 bytes for format detection
|
| 139 |
+
|
| 140 |
+
# JPEG: FF D8 (JPEG files start with these bytes, third byte can vary)
|
| 141 |
+
if len(header) >= 2 and header[:2] == b'\xff\xd8':
|
| 142 |
+
detected_format = 'JPEG'
|
| 143 |
+
# PNG: 89 50 4E 47 0D 0A 1A 0A (PNG signature)
|
| 144 |
+
elif len(header) >= 8 and header[:8] == b'\x89PNG\r\n\x1a\n':
|
| 145 |
+
detected_format = 'PNG'
|
| 146 |
+
# GIF: 47 49 46 38 (GIF8 or GIF9)
|
| 147 |
+
elif len(header) >= 4 and header[:4] in [b'GIF8', b'GIF9']:
|
| 148 |
+
detected_format = 'GIF'
|
| 149 |
+
# WEBP: RIFF ... WEBP (RIFF container with WEBP format)
|
| 150 |
+
elif len(header) >= 12 and header[:4] == b'RIFF' and header[8:12] == b'WEBP':
|
| 151 |
+
detected_format = 'WEBP'
|
| 152 |
+
# BMP: 42 4D (BM - Windows bitmap)
|
| 153 |
+
elif len(header) >= 2 and header[:2] == b'BM':
|
| 154 |
+
detected_format = 'BMP'
|
| 155 |
+
# TIFF: 49 49 2A 00 (little-endian) or 4D 4D 00 2A (big-endian)
|
| 156 |
+
elif len(header) >= 4 and header[:4] in [b'II*\x00', b'MM\x00*']:
|
| 157 |
+
detected_format = 'TIFF'
|
| 158 |
+
|
| 159 |
+
if detected_format:
|
| 160 |
+
print(f"🔍 Detected format from magic bytes: {detected_format} (file: {path.name})")
|
| 161 |
+
except Exception as e:
|
| 162 |
+
print(f"⚠️ Error reading file header for format detection: {e}")
|
| 163 |
+
|
| 164 |
+
# Step 3: Try PIL format detection as fallback
|
| 165 |
try:
|
| 166 |
+
# Open image - PIL can also detect format from content
|
| 167 |
test_img = Image.open(path)
|
| 168 |
+
pil_format = test_img.format
|
| 169 |
test_img.close()
|
| 170 |
|
| 171 |
+
# Use PIL format if we didn't detect from extension/magic bytes, or verify consistency
|
| 172 |
+
if pil_format:
|
| 173 |
+
if detected_format:
|
| 174 |
+
# Both methods detected format - verify they match
|
| 175 |
+
if pil_format.upper() != detected_format.upper():
|
| 176 |
+
print(f"⚠️ Format mismatch: extension/magic bytes={detected_format}, PIL={pil_format}, using PIL format")
|
| 177 |
+
detected_format = pil_format # Prefer PIL format as it's more reliable
|
| 178 |
+
else:
|
| 179 |
+
# Only PIL detected format
|
| 180 |
+
detected_format = pil_format
|
| 181 |
+
print(f"🔍 Detected format from PIL: {detected_format} (file: {path.name})")
|
| 182 |
+
elif not detected_format:
|
| 183 |
+
# Neither method detected format
|
| 184 |
+
if raise_on_error:
|
| 185 |
+
raise ValueError(f"Cannot identify image format and no valid extension: {filepath}")
|
| 186 |
+
print(f"⚠️ Cannot identify image format: {filepath}")
|
| 187 |
+
return None
|
| 188 |
+
|
| 189 |
+
# Check if format is supported
|
| 190 |
+
if detected_format and detected_format.upper() not in SUPPORTED_FORMATS:
|
| 191 |
+
if raise_on_error:
|
| 192 |
+
raise ValueError(f"Unsupported image format: {detected_format} (file: {filepath})")
|
| 193 |
+
print(f"⚠️ Skipping unsupported format: {detected_format} (file: {filepath})")
|
| 194 |
+
return None
|
| 195 |
|
| 196 |
# Verify it's actually a valid image
|
| 197 |
with Image.open(path) as img:
|
| 198 |
img.verify()
|
| 199 |
|
| 200 |
except UnidentifiedImageError:
|
| 201 |
+
# PIL can't identify it - but we might have detected from magic bytes
|
| 202 |
+
if detected_format:
|
| 203 |
+
# We detected format from magic bytes, try to open anyway
|
| 204 |
+
print(f"⚠️ PIL couldn't identify format, but magic bytes suggest {detected_format}, attempting to open...")
|
| 205 |
+
try:
|
| 206 |
+
# Try opening with PIL (it might still work)
|
| 207 |
+
test_img = Image.open(path)
|
| 208 |
+
test_img.verify()
|
| 209 |
+
test_img.close()
|
| 210 |
+
except Exception as e:
|
| 211 |
+
if raise_on_error:
|
| 212 |
+
raise ValueError(f"File detected as {detected_format} but cannot be read: {filepath} ({str(e)})")
|
| 213 |
+
print(f"⚠️ File detected as {detected_format} but cannot be read: {filepath} ({str(e)})")
|
| 214 |
+
return None
|
| 215 |
+
else:
|
| 216 |
+
# No format detected from any method
|
| 217 |
if raise_on_error:
|
| 218 |
raise ValueError(f"Cannot identify image format and no valid extension: {filepath}")
|
| 219 |
print(f"⚠️ Cannot identify image format: {filepath}")
|
| 220 |
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
|
| 222 |
# Re-open for actual use (verify() closes the file)
|
| 223 |
img = Image.open(path)
|