Esmaill1 commited on
Commit
2faaae6
·
1 Parent(s): abcb567

Fix IndentationErrors and optimize image loading performance

Browse files
Files changed (2) hide show
  1. web/server.py +27 -14
  2. web/web_storage/index.html +6 -3
web/server.py CHANGED
@@ -115,19 +115,19 @@ async def upload_image(file: UploadFile = File(...)):
115
  from PIL import ImageOps
116
  # FIX: Handle EXIF orientation (rotation)
117
  img = ImageOps.exif_transpose(img)
118
-
119
  # Get original dimensions after transposition for the web cropper
120
  width, height = img.size
121
-
122
- img.thumbnail((800, 800), Image.LANCZOS)
 
123
  thumb_path = UPLOAD_DIR / f"{file_id}_thumb.jpg"
124
  if img.mode in ("RGBA", "LA"):
125
  bg = Image.new("RGB", img.size, (255, 255, 255))
126
  bg.paste(img, mask=img.split()[-1])
127
- bg.save(thumb_path, "JPEG")
128
  else:
129
- img.convert("RGB").save(thumb_path, "JPEG")
130
-
131
  return {
132
  "id": file_id,
133
  "filename": file.filename,
@@ -216,19 +216,32 @@ async def process_image(
216
 
217
  print(f"Pipeline: Generating final layout for {file_id}...")
218
  final_layout = generate_layout(
219
- final_processed, name, id_number,
220
- add_studio_name=add_studio_name,
221
- add_logo=add_logo,
222
  add_date=add_date
223
  )
224
-
225
  result_path = RESULT_DIR / f"{file_id}_layout.jpg"
226
  final_layout.save(result_path, "JPEG", quality=95, dpi=(300, 300))
227
-
 
 
 
 
 
 
 
 
 
 
228
  if temp_crop.exists(): temp_crop.unlink()
229
-
230
- return {"id": file_id, "result_url": f"/static/results/{file_id}_layout.jpg"}
231
-
 
 
 
232
  except Exception as e:
233
  import traceback
234
  traceback.print_exc()
 
115
  from PIL import ImageOps
116
  # FIX: Handle EXIF orientation (rotation)
117
  img = ImageOps.exif_transpose(img)
118
+
119
  # Get original dimensions after transposition for the web cropper
120
  width, height = img.size
121
+
122
+ # Create a faster, smaller thumbnail for the UI (400x400 is plenty for the queue)
123
+ img.thumbnail((400, 400), Image.BILINEAR)
124
  thumb_path = UPLOAD_DIR / f"{file_id}_thumb.jpg"
125
  if img.mode in ("RGBA", "LA"):
126
  bg = Image.new("RGB", img.size, (255, 255, 255))
127
  bg.paste(img, mask=img.split()[-1])
128
+ bg.save(thumb_path, "JPEG", quality=85)
129
  else:
130
+ img.convert("RGB").save(thumb_path, "JPEG", quality=85)
 
131
  return {
132
  "id": file_id,
133
  "filename": file.filename,
 
216
 
217
  print(f"Pipeline: Generating final layout for {file_id}...")
218
  final_layout = generate_layout(
219
+ final_processed, name, id_number,
220
+ add_studio_name=add_studio_name,
221
+ add_logo=add_logo,
222
  add_date=add_date
223
  )
224
+
225
  result_path = RESULT_DIR / f"{file_id}_layout.jpg"
226
  final_layout.save(result_path, "JPEG", quality=95, dpi=(300, 300))
227
+
228
+ # 5. Generate a lightweight WEB PREVIEW (max 1200px width) for the UI
229
+ preview_path = RESULT_DIR / f"{file_id}_preview.jpg"
230
+ pw, ph = final_layout.size
231
+ p_scale = 1200 / pw if pw > 1200 else 1.0
232
+ if p_scale < 1.0:
233
+ preview_img = final_layout.resize((int(pw * p_scale), int(ph * p_scale)), Image.BILINEAR)
234
+ preview_img.save(preview_path, "JPEG", quality=80)
235
+ else:
236
+ final_layout.save(preview_path, "JPEG", quality=80)
237
+
238
  if temp_crop.exists(): temp_crop.unlink()
239
+
240
+ return {
241
+ "id": file_id,
242
+ "result_url": f"/static/results/{file_id}_layout.jpg",
243
+ "preview_url": f"/static/results/{file_id}_preview.jpg"
244
+ }
245
  except Exception as e:
246
  import traceback
247
  traceback.print_exc()
web/web_storage/index.html CHANGED
@@ -850,7 +850,7 @@
850
 
851
  return `
852
  <div onclick="selectImage(${idx})" class="queue-slide ${currentIndex === idx ? 'active' : ''}">
853
- <img src="${img.result_url ? img.result_url + '?t=' + t : img.thumb_url}" alt="">
854
  <div class="slide-status">${statusIcon}</div>
855
  <button onclick="deleteImage(event, ${idx})" class="slide-delete" title="حذف"><i class="fa-solid fa-xmark"></i></button>
856
  <div class="slide-name">${img.filename}</div>
@@ -895,7 +895,9 @@
895
  reprocessBtn.disabled = !data.result_url;
896
 
897
  const previewSkeleton = document.getElementById('preview-skeleton');
898
- const url = data.result_url ? data.result_url + '?t=' + Date.now() : data.thumb_url;
 
 
899
 
900
  // Reset the image completely before loading the new one
901
  mainPreview.classList.add('hidden');
@@ -950,7 +952,7 @@
950
  mainPreview.src = data.thumb_url;
951
  label.textContent = 'النتيجة';
952
  } else {
953
- mainPreview.src = data.result_url + '?t=' + t;
954
  label.textContent = 'الأصلية';
955
  }
956
  mainPreview.onload = () => {
@@ -1042,6 +1044,7 @@
1042
  const result = await res.json();
1043
  if (result.error) throw new Error(result.error);
1044
  imageData[idx].result_url = result.result_url;
 
1045
  imageData[idx].status = 'done';
1046
  imageData[idx].steps = {
1047
  rmbg: document.getElementById('step-rmbg').checked,
 
850
 
851
  return `
852
  <div onclick="selectImage(${idx})" class="queue-slide ${currentIndex === idx ? 'active' : ''}">
853
+ <img src="${img.preview_url ? img.preview_url + '?t=' + t : img.thumb_url}" alt="">
854
  <div class="slide-status">${statusIcon}</div>
855
  <button onclick="deleteImage(event, ${idx})" class="slide-delete" title="حذف"><i class="fa-solid fa-xmark"></i></button>
856
  <div class="slide-name">${img.filename}</div>
 
895
  reprocessBtn.disabled = !data.result_url;
896
 
897
  const previewSkeleton = document.getElementById('preview-skeleton');
898
+ const url = data.preview_url ? data.preview_url + '?t=' + Date.now() :
899
+ data.result_url ? data.result_url + '?t=' + Date.now() :
900
+ data.thumb_url;
901
 
902
  // Reset the image completely before loading the new one
903
  mainPreview.classList.add('hidden');
 
952
  mainPreview.src = data.thumb_url;
953
  label.textContent = 'النتيجة';
954
  } else {
955
+ mainPreview.src = (data.preview_url || data.result_url) + '?t=' + t;
956
  label.textContent = 'الأصلية';
957
  }
958
  mainPreview.onload = () => {
 
1044
  const result = await res.json();
1045
  if (result.error) throw new Error(result.error);
1046
  imageData[idx].result_url = result.result_url;
1047
+ imageData[idx].preview_url = result.preview_url;
1048
  imageData[idx].status = 'done';
1049
  imageData[idx].steps = {
1050
  rmbg: document.getElementById('step-rmbg').checked,