Opera8 commited on
Commit
6ba6190
·
verified ·
1 Parent(s): 7857268

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +299 -141
app.py CHANGED
@@ -10,9 +10,23 @@ from gradio.themes import Soft
10
  from gradio.themes.utils import colors, fonts, sizes
11
  from deep_translator import GoogleTranslator
12
 
13
- # --- تعریف متغیرها ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
15
- dtype = torch.bfloat16
16
 
17
  # --- بارگذاری مدل ---
18
  from diffusers import FlowMatchEulerDiscreteScheduler
@@ -20,6 +34,9 @@ from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
20
  from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
21
  from qwenimage.qwen_fa3_processor import QwenDoubleStreamAttnProcessorFA3
22
 
 
 
 
23
  print("Loading pipeline...")
24
  pipe = QwenImageEditPlusPipeline.from_pretrained(
25
  "Qwen/Qwen-Image-Edit-2509",
@@ -33,27 +50,35 @@ pipe = QwenImageEditPlusPipeline.from_pretrained(
33
  ).to(device)
34
 
35
  # بارگذاری LoRA ها
36
- loras = {
37
- "anime": ("autoweeb/Qwen-Image-Edit-2509-Photo-to-Anime", "Qwen-Image-Edit-2509-Photo-to-Anime_000001000.safetensors"),
38
- "multiple-angles": ("dx8152/Qwen-Edit-2509-Multiple-angles", "镜头转换.safetensors"),
39
- "light-restoration": ("dx8152/Qwen-Image-Edit-2509-Light_restoration", "移除光影.safetensors"),
40
- "relight": ("dx8152/Qwen-Image-Edit-2509-Relight", "Qwen-Edit-Relight.safetensors"),
41
- "multi-angle-lighting": ("dx8152/Qwen-Edit-2509-Multi-Angle-Lighting", "多角度灯光-251116.safetensors"),
42
- "edit-skin": ("tlennon-ie/qwen-edit-skin", "qwen-edit-skin_1.1_000002750.safetensors"),
43
- "next-scene": ("lovis93/next-scene-qwen-image-lora-2509", "next-scene_lora-v2-3000.safetensors"),
44
- "upscale-image": ("vafipas663/Qwen-Edit-2509-Upscale-LoRA", "qwen-edit-enhance_64-v3_000001000.safetensors")
45
- }
46
-
47
- for name, (repo, weight) in loras.items():
48
- try:
49
- pipe.load_lora_weights(repo, weight_name=weight, adapter_name=name)
50
- except Exception as e:
51
- print(f"Error loading LoRA {name}: {e}")
 
 
 
 
 
 
 
 
52
 
53
  pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
54
  MAX_SEED = np.iinfo(np.int32).max
55
 
56
- # --- نگاشت نام‌های فارسی ---
57
  LORA_MAPPING = {
58
  "تبدیل عکس به انیمه": "anime",
59
  "تغییر زاویه دید": "multiple-angles",
@@ -65,47 +90,72 @@ LORA_MAPPING = {
65
  "افزایش کیفیت (Upscale)": "upscale-image"
66
  }
67
 
68
- # --- توابع کمکی ---
69
  def translate_prompt(text):
70
- if not text: return ""
 
 
71
  try:
72
- return GoogleTranslator(source='auto', target='en').translate(text)
73
- except:
 
 
74
  return text
75
 
76
  def update_dimensions_on_upload(image):
77
- if image is None: return 1024, 1024
78
- w, h = image.size
79
- if w > h:
80
- new_w = 1024
81
- new_h = int(new_w * (h / w))
 
 
 
 
82
  else:
83
- new_h = 1024
84
- new_w = int(new_h * (w / h))
85
- return (new_w // 8) * 8, (new_h // 8) * 8
 
 
 
 
 
86
 
87
  @spaces.GPU(duration=30)
88
- def infer(input_image, prompt, lora_adapter_persian, seed, randomize_seed, guidance_scale, steps, progress=gr.Progress(track_tqdm=True)):
 
 
 
 
 
 
 
 
 
89
  if input_image is None:
90
- raise gr.Error("لطفاً تصویر را بارگذاری کنید.")
91
 
92
  english_prompt = translate_prompt(prompt)
93
- adapter_name = LORA_MAPPING.get(lora_adapter_persian)
94
- if adapter_name:
95
- pipe.set_adapters([adapter_name], adapter_weights=[1.0])
 
96
 
97
  if randomize_seed:
98
  seed = random.randint(0, MAX_SEED)
99
 
100
  generator = torch.Generator(device=device).manual_seed(seed)
101
- w, h = update_dimensions_on_upload(input_image)
 
 
 
102
 
103
  result = pipe(
104
- image=input_image.convert("RGB"),
105
  prompt=english_prompt,
106
- negative_prompt="worst quality, low quality, blurry, bad anatomy",
107
- height=h,
108
- width=w,
109
  num_inference_steps=steps,
110
  generator=generator,
111
  true_cfg_scale=guidance_scale,
@@ -113,205 +163,313 @@ def infer(input_image, prompt, lora_adapter_persian, seed, randomize_seed, guida
113
 
114
  return result, seed
115
 
 
116
  def infer_example(input_image, prompt, lora_adapter):
117
- return infer(input_image, prompt, lora_adapter, 0, True, 1.0, 4)
 
 
 
 
118
 
119
- # --- کدهای سمت کلاینت (JS/CSS) ---
120
 
 
121
  js_post_message = """
122
  async (image) => {
123
- if (!image) { alert("تصویر هنوز ساخته نشده است!"); return; }
 
 
 
124
  let fileUrl = image.url;
125
  if (fileUrl && !fileUrl.startsWith('http')) {
126
  fileUrl = window.location.origin + fileUrl;
127
  } else if (!fileUrl && image.path) {
128
  fileUrl = window.location.origin + "/file=" + image.path;
129
  }
130
- window.parent.postMessage({ type: 'DOWNLOAD_REQUEST', url: fileUrl }, '*');
 
 
 
 
131
  }
132
  """
133
 
134
- html_style_and_script = """
 
135
  <style>
136
  @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
137
 
138
- /* --- تنظیمات کلی و اجبار تم روشن --- */
139
  :root, .dark, body, .gradio-container {
140
- --body-background-fill: #f0f2f5 !important;
141
  --body-text-color: #1f2937 !important;
142
  --background-fill-primary: #ffffff !important;
 
143
  --border-color-primary: #e5e7eb !important;
 
144
  --block-label-text-color: #374151 !important;
145
  --block-title-text-color: #111827 !important;
146
- font-family: 'Vazirmatn', sans-serif !important;
 
147
  }
148
 
149
  body {
150
- background-color: #f0f2f5 !important;
 
151
  margin: 0;
152
- padding: 0;
153
  }
154
 
155
- /* --- کانتینر اصلی --- */
156
  #col-container {
157
- margin: 20px auto;
158
- max-width: 1000px;
159
- background: #ffffff !important;
160
- border-radius: 24px;
161
- padding: 30px;
162
- box-shadow: 0 10px 40px rgba(0,0,0,0.06);
163
- border: 1px solid #ffffff;
164
  direction: rtl;
165
  text-align: right;
 
 
 
 
 
166
  }
167
 
168
- /* --- هدر و توضیحات --- */
169
  #main-title h1 {
170
- font-weight: 800 !important;
171
- color: #111827 !important;
172
  text-align: center;
173
- margin-bottom: 10px;
174
- font-size: 2rem !important;
 
 
 
 
175
  }
 
176
  #main-description {
177
  text-align: center;
178
- color: #6b7280 !important;
179
- margin-bottom: 30px;
180
- font-size: 1.1rem;
 
181
  }
182
 
183
- /* --- دکمه‌ها --- */
184
- button.primary {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
186
- color: white !important;
187
  border: none !important;
188
- border-radius: 12px !important;
189
- padding: 12px 20px !important;
190
  font-weight: 700 !important;
191
- font-size: 1rem !important;
 
 
192
  box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3) !important;
193
- transition: transform 0.2s, box-shadow 0.2s !important;
 
 
 
194
  }
195
- button.primary:hover {
 
196
  transform: translateY(-2px);
197
- box-shadow: 0 6px 20px rgba(16, 185, 129, 0.4) !important;
198
  }
 
 
 
 
 
199
  #download-btn {
200
  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
201
  box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3) !important;
202
- margin-top: 15px;
203
- width: 100%;
204
  }
205
-
206
- /* --- ورودی‌ها و لیبل‌ها --- */
207
- .gr-input-label {
208
- font-weight: 600;
209
- color: #374151 !important;
210
- margin-bottom: 8px;
211
- }
212
- textarea, input[type="text"], .gr-dropdown {
213
- background-color: #f9fafb !important;
214
- border: 1px solid #e5e7eb !important;
215
- border-radius: 10px !important;
216
- color: #111827 !important;
217
- box-shadow: none !important;
218
- }
219
- textarea:focus, input:focus {
220
- border-color: #10b981 !important;
221
- background-color: #ffffff !important;
222
- box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1) !important;
223
  }
224
 
225
- /* --- رفع مشکل جدول نمونه‌ها --- */
226
- .gr-samples-table {
 
 
 
 
227
  border-radius: 12px !important;
228
  overflow: hidden !important;
229
- border: 1px solid #e5e7eb !important;
 
 
 
 
 
 
 
 
 
 
230
  }
231
- .gr-samples-table tr, .gr-samples-table th, .gr-samples-table td {
 
232
  background-color: #ffffff !important;
233
- color: #1f2937 !important;
234
  border-bottom: 1px solid #f3f4f6 !important;
235
  }
236
- .gr-samples-table tr:nth-child(even) {
237
- background-color: #f9fafb !important; /* راه‌راه خیلی ملایم */
 
238
  }
239
- .gr-samples-table th {
240
- background-color: #f3f4f6 !important;
241
- font-weight: 700 !important;
 
 
 
 
 
 
 
 
242
  }
243
 
244
- /* --- مخفی کردن اضافات --- */
245
- footer, .flagging { display: none !important; }
 
 
 
 
 
 
 
 
246
  </style>
247
 
248
  <script>
249
- // اسکریپت اجباری برای حذف کلاس Dark از بدنه اصلی گرادیو
250
- function forceLight() {
251
- document.body.classList.remove('dark');
252
- document.body.style.backgroundColor = '#f0f2f5';
 
 
 
 
 
 
 
 
 
 
 
253
  }
254
- document.addEventListener('DOMContentLoaded', forceLight);
255
- const observer = new MutationObserver(() => forceLight());
256
- observer.observe(document.body, { attributes: true });
257
  </script>
258
  """
259
 
260
- # --- رابط کاربری Gradio ---
261
  with gr.Blocks() as demo:
262
- gr.HTML(html_style_and_script)
263
-
 
264
  with gr.Column(elem_id="col-container"):
265
  gr.Markdown("# **ویرایشگر هوشمند آلفا**", elem_id="main-title")
266
- gr.Markdown("با هوش مصنوعی آلفا تصاویر تونو به مدل های مختلف ویرایش کنید.", elem_id="main-description")
 
 
 
267
 
268
  with gr.Row(equal_height=True):
269
- # ستون چپ (ورودی)
270
  with gr.Column():
271
- input_image = gr.Image(label="بارگذاری تصویر", type="pil", height=300)
 
272
  prompt = gr.Text(
273
  label="دستور ویرایش (به فارسی)",
 
274
  placeholder="مثال: تصویر را به سبک انیمه تبدیل کن...",
275
- rtl=True, lines=3
 
276
  )
277
- run_btn = gr.Button("✨ شروع پردازش", variant="primary")
278
 
279
- # ستون راست (خروجی)
 
280
  with gr.Column():
281
- output_image = gr.Image(label="تصویر نهایی", interactive=False, height=350)
282
- download_btn = gr.Button("📥 دانلود و ذخیره تصویر", elem_id="download-btn", variant="primary")
283
 
284
- with gr.Row():
285
- adapter = gr.Dropdown(label="سبک ویرایش", choices=list(LORA_MAPPING.keys()), value="تبدیل عکس به انیمه")
286
 
287
- with gr.Accordion("تنظیمات پیشرفته", open=False):
288
- seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
289
- random_seed = gr.Checkbox(label="Seed تصادفی", value=True)
290
- scale = gr.Slider(label="Guidance Scale", 1.0, 10.0, step=0.1, value=1.0)
291
- steps = gr.Slider(label="Steps", 1, 50, step=1, value=4)
292
-
 
 
 
 
 
 
 
 
293
  gr.Examples(
294
  examples=[
295
  ["examples/1.jpg", "تبدیل به انیمه کن.", "تبدیل عکس به انیمه"],
296
  ["examples/5.jpg", "سایه‌ها را حذف کن و نورپردازی نرم به تصویر بده.", "اصلاح نور و سایه"],
297
  ["examples/4.jpg", "از فیلتر ساعت طلایی با پخش نور ملایم استفاده کن.", "نورپردازی مجدد (Relight)"],
298
  ["examples/2.jpeg", "دوربین را ۴۵ درجه به سمت چپ بچرخان.", "تغییر زاویه دید"],
299
- ["examples/9.jpg", "سبک سینمایی واقعی با درخشش نرم.", "صحنه بعدی (سینمایی)"],
 
 
 
 
 
 
300
  ],
301
- inputs=[input_image, prompt, adapter],
302
  outputs=[output_image, seed],
303
  fn=infer_example,
304
  cache_examples=False,
305
- label="نمونه‌های آماده"
306
  )
307
 
308
- run_btn.click(
 
309
  fn=infer,
310
- inputs=[input_image, prompt, adapter, seed, random_seed, scale, steps],
311
  outputs=[output_image, seed]
312
  )
313
-
314
- download_btn.click(None, [output_image], None, js=js_post_message)
 
 
 
 
 
 
315
 
316
  if __name__ == "__main__":
317
  demo.queue(max_size=30).launch(show_error=True)
 
10
  from gradio.themes.utils import colors, fonts, sizes
11
  from deep_translator import GoogleTranslator
12
 
13
+ # --- تعریف تم ---
14
+ colors.steel_blue = colors.Color(
15
+ name="steel_blue",
16
+ c50="#EBF3F8",
17
+ c100="#D3E5F0",
18
+ c200="#A8CCE1",
19
+ c300="#7DB3D2",
20
+ c400="#529AC3",
21
+ c500="#4682B4",
22
+ c600="#3E72A0",
23
+ c700="#36638C",
24
+ c800="#2E5378",
25
+ c900="#264364",
26
+ c950="#1E3450",
27
+ )
28
+
29
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 
30
 
31
  # --- بارگذاری مدل ---
32
  from diffusers import FlowMatchEulerDiscreteScheduler
 
34
  from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
35
  from qwenimage.qwen_fa3_processor import QwenDoubleStreamAttnProcessorFA3
36
 
37
+ dtype = torch.bfloat16
38
+ device = "cuda" if torch.cuda.is_available() else "cpu"
39
+
40
  print("Loading pipeline...")
41
  pipe = QwenImageEditPlusPipeline.from_pretrained(
42
  "Qwen/Qwen-Image-Edit-2509",
 
50
  ).to(device)
51
 
52
  # بارگذاری LoRA ها
53
+ pipe.load_lora_weights("autoweeb/Qwen-Image-Edit-2509-Photo-to-Anime",
54
+ weight_name="Qwen-Image-Edit-2509-Photo-to-Anime_000001000.safetensors",
55
+ adapter_name="anime")
56
+ pipe.load_lora_weights("dx8152/Qwen-Edit-2509-Multiple-angles",
57
+ weight_name="镜头转换.safetensors",
58
+ adapter_name="multiple-angles")
59
+ pipe.load_lora_weights("dx8152/Qwen-Image-Edit-2509-Light_restoration",
60
+ weight_name="移除光影.safetensors",
61
+ adapter_name="light-restoration")
62
+ pipe.load_lora_weights("dx8152/Qwen-Image-Edit-2509-Relight",
63
+ weight_name="Qwen-Edit-Relight.safetensors",
64
+ adapter_name="relight")
65
+ pipe.load_lora_weights("dx8152/Qwen-Edit-2509-Multi-Angle-Lighting",
66
+ weight_name="多角度灯光-251116.safetensors",
67
+ adapter_name="multi-angle-lighting")
68
+ pipe.load_lora_weights("tlennon-ie/qwen-edit-skin",
69
+ weight_name="qwen-edit-skin_1.1_000002750.safetensors",
70
+ adapter_name="edit-skin")
71
+ pipe.load_lora_weights("lovis93/next-scene-qwen-image-lora-2509",
72
+ weight_name="next-scene_lora-v2-3000.safetensors",
73
+ adapter_name="next-scene")
74
+ pipe.load_lora_weights("vafipas663/Qwen-Edit-2509-Upscale-LoRA",
75
+ weight_name="qwen-edit-enhance_64-v3_000001000.safetensors",
76
+ adapter_name="upscale-image")
77
 
78
  pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
79
  MAX_SEED = np.iinfo(np.int32).max
80
 
81
+ # --- نگاشت نام‌های فارسی به نام‌های داخلی مدل ---
82
  LORA_MAPPING = {
83
  "تبدیل عکس به انیمه": "anime",
84
  "تغییر زاویه دید": "multiple-angles",
 
90
  "افزایش کیفیت (Upscale)": "upscale-image"
91
  }
92
 
 
93
  def translate_prompt(text):
94
+ """ترجمه متن فارسی به انگلیسی"""
95
+ if not text:
96
+ return ""
97
  try:
98
+ translated = GoogleTranslator(source='auto', target='en').translate(text)
99
+ return translated
100
+ except Exception as e:
101
+ print(f"Translation Error: {e}")
102
  return text
103
 
104
  def update_dimensions_on_upload(image):
105
+ if image is None:
106
+ return 1024, 1024
107
+
108
+ original_width, original_height = image.size
109
+
110
+ if original_width > original_height:
111
+ new_width = 1024
112
+ aspect_ratio = original_height / original_width
113
+ new_height = int(new_width * aspect_ratio)
114
  else:
115
+ new_height = 1024
116
+ aspect_ratio = original_width / original_height
117
+ new_width = int(new_height * aspect_ratio)
118
+
119
+ new_width = (new_width // 8) * 8
120
+ new_height = (new_height // 8) * 8
121
+
122
+ return new_width, new_height
123
 
124
  @spaces.GPU(duration=30)
125
+ def infer(
126
+ input_image,
127
+ prompt,
128
+ lora_adapter_persian,
129
+ seed,
130
+ randomize_seed,
131
+ guidance_scale,
132
+ steps,
133
+ progress=gr.Progress(track_tqdm=True)
134
+ ):
135
  if input_image is None:
136
+ raise gr.Error("لطفاً یک تصویر برای ویرایش بارگذاری کنید.")
137
 
138
  english_prompt = translate_prompt(prompt)
139
+ adapter_internal_name = LORA_MAPPING.get(lora_adapter_persian)
140
+
141
+ if adapter_internal_name:
142
+ pipe.set_adapters([adapter_internal_name], adapter_weights=[1.0])
143
 
144
  if randomize_seed:
145
  seed = random.randint(0, MAX_SEED)
146
 
147
  generator = torch.Generator(device=device).manual_seed(seed)
148
+ negative_prompt = "worst quality, low quality, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry"
149
+
150
+ original_image = input_image.convert("RGB")
151
+ width, height = update_dimensions_on_upload(original_image)
152
 
153
  result = pipe(
154
+ image=original_image,
155
  prompt=english_prompt,
156
+ negative_prompt=negative_prompt,
157
+ height=height,
158
+ width=width,
159
  num_inference_steps=steps,
160
  generator=generator,
161
  true_cfg_scale=guidance_scale,
 
163
 
164
  return result, seed
165
 
166
+ @spaces.GPU(duration=30)
167
  def infer_example(input_image, prompt, lora_adapter):
168
+ input_pil = input_image.convert("RGB")
169
+ guidance_scale = 1.0
170
+ steps = 4
171
+ result, seed = infer(input_pil, prompt, lora_adapter, 0, True, guidance_scale, steps)
172
+ return result, seed
173
 
 
174
 
175
+ # --- جاوااسکریپت برای دکمه دانلود (PostMessage) ---
176
  js_post_message = """
177
  async (image) => {
178
+ if (!image) {
179
+ alert("لطفاً ابتدا تصویر را تولید کنید.");
180
+ return;
181
+ }
182
  let fileUrl = image.url;
183
  if (fileUrl && !fileUrl.startsWith('http')) {
184
  fileUrl = window.location.origin + fileUrl;
185
  } else if (!fileUrl && image.path) {
186
  fileUrl = window.location.origin + "/file=" + image.path;
187
  }
188
+ console.log("Sending download request for:", fileUrl);
189
+ window.parent.postMessage({
190
+ type: 'DOWNLOAD_REQUEST',
191
+ url: fileUrl
192
+ }, '*');
193
  }
194
  """
195
 
196
+ # --- تنظیمات HTML (CSS زیبا و مدرن + JS اجبار تم روشن) ---
197
+ html_code = """
198
  <style>
199
  @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
200
 
201
+ /* --- 1. تنظیمات کلی و اجبار تم روشن --- */
202
  :root, .dark, body, .gradio-container {
203
+ --body-background-fill: #f5f7fa !important;
204
  --body-text-color: #1f2937 !important;
205
  --background-fill-primary: #ffffff !important;
206
+ --background-fill-secondary: #f3f4f6 !important;
207
  --border-color-primary: #e5e7eb !important;
208
+ --block-background-fill: #ffffff !important;
209
  --block-label-text-color: #374151 !important;
210
  --block-title-text-color: #111827 !important;
211
+ --input-background-fill: #ffffff !important;
212
+ color-scheme: light !important;
213
  }
214
 
215
  body {
216
+ font-family: 'Vazirmatn', sans-serif !important;
217
+ background-color: #f5f7fa !important;
218
  margin: 0;
219
+ padding: 10px;
220
  }
221
 
222
+ /* --- 2. کانتینر اصلی --- */
223
  #col-container {
224
+ margin: 0 auto;
225
+ max-width: 980px;
 
 
 
 
 
226
  direction: rtl;
227
  text-align: right;
228
+ padding: 30px;
229
+ background: #ffffff !important;
230
+ border-radius: 24px;
231
+ box-shadow: 0 10px 40px -10px rgba(0,0,0,0.08);
232
+ border: 1px solid rgba(255,255,255,0.8);
233
  }
234
 
235
+ /* --- 3. هدر و توضیحات --- */
236
  #main-title h1 {
237
+ font-size: 2.4em !important;
 
238
  text-align: center;
239
+ color: #1a202c !important;
240
+ margin-bottom: 15px;
241
+ font-weight: 800;
242
+ background: -webkit-linear-gradient(45deg, #2563eb, #1e40af);
243
+ -webkit-background-clip: text;
244
+ -webkit-text-fill-color: transparent;
245
  }
246
+
247
  #main-description {
248
  text-align: center;
249
+ font-size: 1.15em;
250
+ color: #4b5563 !important;
251
+ margin-bottom: 40px;
252
+ line-height: 1.6;
253
  }
254
 
255
+ /* --- 4. استایل ورودی‌ها و لیبل‌ها --- */
256
+ .gr-input-label, span.label-wrap, label span {
257
+ font-weight: 700 !important;
258
+ color: #374151 !important;
259
+ font-size: 0.95em !important;
260
+ margin-bottom: 8px !important;
261
+ }
262
+
263
+ textarea, input[type="text"] {
264
+ border: 2px solid #e2e8f0 !important;
265
+ border-radius: 12px !important;
266
+ background-color: #ffffff !important;
267
+ color: #111827 !important;
268
+ padding: 12px !important;
269
+ font-family: 'Vazirmatn', sans-serif !important;
270
+ }
271
+
272
+ textarea:focus, input[type="text"]:focus {
273
+ border-color: #3b82f6 !important;
274
+ box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1) !important;
275
+ outline: none;
276
+ }
277
+
278
+ .gr-dropdown {
279
+ background: #ffffff !important;
280
+ border-radius: 12px !important;
281
+ }
282
+
283
+ /* --- 5. دکمه‌ها --- */
284
+ .primary-btn, button.primary {
285
  background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
 
286
  border: none !important;
287
+ color: white !important;
 
288
  font-weight: 700 !important;
289
+ font-size: 1.1em !important;
290
+ padding: 14px 28px !important;
291
+ border-radius: 14px !important;
292
  box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3) !important;
293
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
294
+ cursor: pointer !important;
295
+ width: 100%;
296
+ margin-top: 15px;
297
  }
298
+
299
+ .primary-btn:hover, button.primary:hover {
300
  transform: translateY(-2px);
301
+ box-shadow: 0 8px 25px rgba(16, 185, 129, 0.45) !important;
302
  }
303
+
304
+ .primary-btn:active, button.primary:active {
305
+ transform: translateY(1px);
306
+ }
307
+
308
  #download-btn {
309
  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
310
  box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3) !important;
 
 
311
  }
312
+ #download-btn:hover {
313
+ box-shadow: 0 8px 25px rgba(59, 130, 246, 0.45) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  }
315
 
316
+ /* --- 6. بخش نمونه‌ها (Examples) - رفع کامل سیاهی --- */
317
+ .gradio-container .prose table,
318
+ .gradio-container table {
319
+ background-color: #ffffff !important;
320
+ color: #111827 !important;
321
+ border: 1px solid #e5e7eb !important;
322
  border-radius: 12px !important;
323
  overflow: hidden !important;
324
+ width: 100% !important;
325
+ margin-top: 20px !important;
326
+ }
327
+
328
+ .gradio-container thead th {
329
+ background-color: #f3f4f6 !important;
330
+ color: #374151 !important;
331
+ font-weight: 700 !important;
332
+ border-bottom: 2px solid #e5e7eb !important;
333
+ padding: 12px !important;
334
+ text-align: right !important;
335
  }
336
+
337
+ .gradio-container tbody tr {
338
  background-color: #ffffff !important;
 
339
  border-bottom: 1px solid #f3f4f6 !important;
340
  }
341
+
342
+ .gradio-container tbody tr:hover {
343
+ background-color: #f9fafb !important;
344
  }
345
+
346
+ .gradio-container tbody td {
347
+ background-color: #ffffff !important;
348
+ color: #374151 !important;
349
+ padding: 10px !important;
350
+ }
351
+
352
+ .gradio-container tbody td span,
353
+ .gradio-container tbody td p,
354
+ .gradio-container tbody td div {
355
+ color: #374151 !important;
356
  }
357
 
358
+ /* --- 7. مخفی‌سازی‌ها --- */
359
+ footer { display: none !important; }
360
+ .flagging { display: none !important; }
361
+
362
+ @media (prefers-color-scheme: dark) {
363
+ body, .gradio-container, .prose, table, tr, td, th {
364
+ background-color: #ffffff !important;
365
+ color: #333333 !important;
366
+ }
367
+ }
368
  </style>
369
 
370
  <script>
371
+ function forceLightMode() {
372
+ const body = document.querySelector('body');
373
+ const gradioApp = document.querySelector('gradio-app');
374
+
375
+ if (body) {
376
+ body.classList.remove('dark');
377
+ body.style.backgroundColor = '#f5f7fa';
378
+ body.style.color = '#333333';
379
+ }
380
+ if (gradioApp) {
381
+ gradioApp.classList.remove('dark');
382
+ }
383
+ document.querySelectorAll('.dark').forEach(el => {
384
+ el.classList.remove('dark');
385
+ });
386
  }
387
+ forceLightMode();
388
+ setInterval(forceLightMode, 1000);
389
+ document.addEventListener('DOMContentLoaded', forceLightMode);
390
  </script>
391
  """
392
 
 
393
  with gr.Blocks() as demo:
394
+ # تزریق HTML (استایل و اسکریپت)
395
+ gr.HTML(html_code)
396
+
397
  with gr.Column(elem_id="col-container"):
398
  gr.Markdown("# **ویرایشگر هوشمند آلفا**", elem_id="main-title")
399
+ gr.Markdown(
400
+ "با هوش مصنوعی آلفا تصاویر تونو به مدل های مختلف ویرایش کنید.",
401
+ elem_id="main-description"
402
+ )
403
 
404
  with gr.Row(equal_height=True):
 
405
  with gr.Column():
406
+ input_image = gr.Image(label="بارگذاری تصویر", type="pil", height=320)
407
+
408
  prompt = gr.Text(
409
  label="دستور ویرایش (به فارسی)",
410
+ show_label=True,
411
  placeholder="مثال: تصویر را به سبک انیمه تبدیل کن...",
412
+ rtl=True,
413
+ lines=3
414
  )
 
415
 
416
+ run_button = gr.Button("✨ شروع پردازش و ساخت تصویر", variant="primary", elem_classes="primary-btn")
417
+
418
  with gr.Column():
419
+ output_image = gr.Image(label="تصویر نهایی", interactive=False, format="png", height=380)
 
420
 
421
+ # دکمه دانلود اختصاصی برای ارسال به Iframe
422
+ download_button = gr.Button("📥 دانلود و ذخیره تصویر", variant="secondary", elem_id="download-btn", elem_classes="primary-btn")
423
 
424
+ with gr.Row():
425
+ lora_adapter = gr.Dropdown(
426
+ label="انتخاب سبک ویرایش (LoRA)",
427
+ choices=list(LORA_MAPPING.keys()),
428
+ value="تبدیل عکس به انیمه"
429
+ )
430
+ with gr.Accordion("تنظیمات پیشرفته", open=False, visible=True):
431
+ seed = gr.Slider(label="دانه تصادفی (Seed)", minimum=0, maximum=MAX_SEED, step=1, value=0)
432
+ randomize_seed = gr.Checkbox(label="استفاده از Seed تصادفی", value=True)
433
+ # اصلاح شده: استفاده از آرگومان‌های با نام
434
+ guidance_scale = gr.Slider(label="میزان وفاداری به متن (Guidance Scale)", minimum=1.0, maximum=10.0, step=0.1, value=1.0)
435
+ steps = gr.Slider(label="تعداد مراحل پردازش (Steps)", minimum=1, maximum=50, step=1, value=4)
436
+
437
+ # تعریف نمونه‌ها (Examples)
438
  gr.Examples(
439
  examples=[
440
  ["examples/1.jpg", "تبدیل به انیمه کن.", "تبدیل عکس به انیمه"],
441
  ["examples/5.jpg", "سایه‌ها را حذف کن و نورپردازی نرم به تصویر بده.", "اصلاح نور و سایه"],
442
  ["examples/4.jpg", "از فیلتر ساعت طلایی با پخش نور ملایم استفاده کن.", "نورپردازی مجدد (Relight)"],
443
  ["examples/2.jpeg", "دوربین را ۴۵ درجه به سمت چپ بچرخان.", "تغییر زاویه دید"],
444
+ ["examples/7.jpg", "منبع نور را از سمت راست عقب قرار بده.", "نورپردازی چند زاویه‌ای"],
445
+ ["examples/10.jpeg", "کیفیت تصویر را افزایش بده (Upscale).", "افزایش کیفیت (Upscale)"],
446
+ ["examples/7.jpg", "منبع نور را از پایین بتابان.", "نورپردازی چند زاویه‌ای"],
447
+ ["examples/2.jpeg", "زاویه دوربین را به نمای بالا گوشه راست تغییر بده.", "تغییر زاویه دید"],
448
+ ["examples/9.jpg", "دوربین کمی به جلو حرکت می‌کند در حالی که نور خورشید از میان ابرها می‌تابد و درخششی نرم اطراف شبح شخصیت در مه ایجاد می‌کند. سبک سینمایی واقعی.", "صحنه بعدی (سینمایی)"],
449
+ ["examples/8.jpg", "جزئیات پوست سوژه را برجسته‌تر و طبیعی‌تر کن.", "روتوش پوست"],
450
+ ["examples/6.jpg", "دوربین را به نمای پایین به بالا تغییر بده.", "تغییر زاویه دید"],
451
  ],
452
+ inputs=[input_image, prompt, lora_adapter],
453
  outputs=[output_image, seed],
454
  fn=infer_example,
455
  cache_examples=False,
456
+ label="نمونه‌ها (برای تست کلیک کنید)"
457
  )
458
 
459
+ # اتصال دکمه اجرا
460
+ run_button.click(
461
  fn=infer,
462
+ inputs=[input_image, prompt, lora_adapter, seed, randomize_seed, guidance_scale, steps],
463
  outputs=[output_image, seed]
464
  )
465
+
466
+ # اتصال دکمه دانلود
467
+ download_button.click(
468
+ fn=None,
469
+ inputs=[output_image],
470
+ outputs=None,
471
+ js=js_post_message
472
+ )
473
 
474
  if __name__ == "__main__":
475
  demo.queue(max_size=30).launch(show_error=True)