DxrkMonteva commited on
Commit
9d36e86
·
verified ·
1 Parent(s): eed4f57

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -61
app.py CHANGED
@@ -2,97 +2,89 @@ import gradio as gr
2
  from huggingface_hub import InferenceClient
3
  from PIL import Image
4
  import os
5
- import io
6
 
7
- # Берем токен из секретов
8
  hf_token = os.getenv("HF_TOKEN")
9
- # Используем мощную модель SDXL
10
  client = InferenceClient("stabilityai/stable-diffusion-xl-base-1.0", token=hf_token)
11
 
12
- def generate_core(prompt, resolution, pixelate):
13
- """Основная функция генерации"""
14
- if not hf_token:
15
- return None
16
 
17
- # Промпт заточен под Minecraft
18
- full_prompt = f"minecraft asset, {prompt}, 2d flat game texture, simple background, high contrast, sharp edges"
19
- neg_prompt = "shading, realistic, 3d, shadow, blurry, text, watermark, photo, messy"
 
 
 
 
 
 
 
 
 
20
 
21
  try:
22
- # Сама генерация
23
- image = client.text_to_image(full_prompt, negative_prompt=neg_prompt, guidance_scale=8.0)
 
 
 
 
24
 
25
- # Разрешение
26
  res_map = {"16x16": 16, "32x32": 32, "64x64": 64, "128x128": 128, "512x512": 512}
27
  size = res_map[resolution]
 
 
 
 
 
28
 
29
- if pixelate:
30
- image = image.resize((size, size), Image.Resampling.NEAREST)
31
- else:
32
- image = image.resize((size, size), Image.Resampling.LANCZOS)
33
-
34
- return image
35
  except Exception as e:
36
  print(f"Error: {e}")
37
- return None
38
 
39
- def forge_single(prompt, resolution, pixelate):
40
- img = generate_core(prompt, resolution, pixelate)
41
- if img is None:
42
- # Создаем картинку-ошибку, если API не ответил
43
- err = Image.new('RGB', (512, 512), color=(40, 0, 0))
44
- return err
45
- return img
46
 
47
- def forge_set(prompt, resolution, pixelate):
48
- """Генерирует сразу блок и предмет"""
49
- block = generate_core(f"block of {prompt} texture", resolution, pixelate)
50
- item = generate_core(f"item icon of {prompt} sword or tool", resolution, pixelate)
51
-
52
- if block is None: block = Image.new('RGB', (512, 512), color=(20, 20, 20))
53
- if item is None: item = Image.new('RGB', (512, 512), color=(20, 20, 20))
54
-
55
- return block, item
56
-
57
- # Красивый темный интерфейс
58
- css = """
59
- .gradio-container { background-color: #0a0a0a !important; color: #d8b4fe !important; }
60
- .btn-primary { background: linear-gradient(to right, #7c3aed, #db2777) !important; border: none !important; }
61
- footer { display: none !important; }
62
- """
63
 
64
  with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
65
- gr.Markdown("# 🌌 The Cursed: Texture Forge v3.0")
66
 
67
- if not hf_token:
68
- gr.HTML("<div style='background: red; padding: 10px; color: white;'>⚠️ ОШИБКА: HF_TOKEN не найден! Добавьте его в Settings -> Secrets</div>")
69
-
70
  with gr.Tabs():
71
  with gr.TabItem("Одиночная текстура"):
72
  with gr.Row():
73
  with gr.Column():
74
- p_in = gr.Textbox(label="Описание (English)", placeholder="e.g. cursed soul sand with screaming faces")
75
- r_in = gr.Dropdown(["16x16", "32x32", "64x64", "128x128", "512x512"], value="128x128", label="Разрешение")
 
 
76
  px_in = gr.Checkbox(label="Pixel Art Mode", value=True)
77
- btn_p = gr.Button("🔥 ВЫКОВАТЬ", variant="primary")
 
78
  with gr.Column():
79
- out_p = gr.Image(label="Результат", type="pil")
80
- gr.Markdown("📥 *Чтобы скачать в .png: Нажми на иконку загрузки в углу картинки или ПКМ -> Сохранить как.*")
81
 
82
- with gr.TabItem("📦 ГЕНЕРАЦИЯ СЕТА"):
83
- gr.Markdown("Создает одновременно текстуру блока и иконку предмета в едином стиле.")
84
  with gr.Row():
85
  with gr.Column():
86
- s_in = gr.Textbox(label="Тема сета", placeholder="e.g. void amethyst crystal")
87
- s_res = gr.Dropdown(["16x16", "32x32", "64x64", "128x128", "512x512"], value="128x128", label="Разрешение")
88
- s_px = gr.Checkbox(label="Pixel Art Mode", value=True)
89
  btn_s = gr.Button("⚒️ СОЗДАТЬ СЕТ", variant="primary")
90
  with gr.Column():
91
  with gr.Row():
92
- out_s_block = gr.Image(label="Блок", type="pil")
93
- out_s_item = gr.Image(label="Предмет", type="pil")
 
94
 
95
- btn_p.click(forge_single, [p_in, r_in, px_in], out_p)
96
- btn_s.click(forge_set, [s_in, s_res, s_px], [out_s_block, out_s_item])
97
 
98
  demo.launch()
 
2
  from huggingface_hub import InferenceClient
3
  from PIL import Image
4
  import os
5
+ import random
6
 
7
+ # Настройка клиента
8
  hf_token = os.getenv("HF_TOKEN")
 
9
  client = InferenceClient("stabilityai/stable-diffusion-xl-base-1.0", token=hf_token)
10
 
11
+ def forge_texture(prompt, resolution, pixelate, style, seed):
12
+ if not hf_token: return None, None
 
 
13
 
14
+ # Улучшение промпта в зависимости от стиля
15
+ styles = {
16
+ "Cursed 🔮": "dark occult aesthetic, purple and black glow, twisted textures, cursed energy",
17
+ "Classic ⛏️": "minecraft vanilla style, flat colors, blocky look, simplistic",
18
+ "HD Realism ✨": "highly detailed, 8k, realistic material, sharp shadows"
19
+ }
20
+
21
+ # Если seed -1, выбираем случайный
22
+ used_seed = random.randint(0, 1000000) if seed == -1 else seed
23
+
24
+ full_prompt = f"minecraft 2d texture, {prompt}, {styles[style]}, flat game asset, white background"
25
+ neg_prompt = "lowres, text, error, cropped, worst quality, low quality, 3d render, perspective, messy"
26
 
27
  try:
28
+ image = client.text_to_image(
29
+ full_prompt,
30
+ negative_prompt=neg_prompt,
31
+ guidance_scale=8.0,
32
+ seed=used_seed
33
+ )
34
 
35
+ # Ресайз
36
  res_map = {"16x16": 16, "32x32": 32, "64x64": 64, "128x128": 128, "512x512": 512}
37
  size = res_map[resolution]
38
+ image = image.resize((size, size), Image.Resampling.NEAREST if pixelate else Image.Resampling.LANCZOS)
39
+
40
+ # Сохраняем как PNG
41
+ file_name = f"texture_{random.randint(1000, 9999)}.png"
42
+ image.save(file_name, "PNG")
43
 
44
+ return image, file_name
 
 
 
 
 
45
  except Exception as e:
46
  print(f"Error: {e}")
47
+ return None, None
48
 
49
+ def forge_set(prompt, resolution, pixelate, style):
50
+ # Генератор для сета (блок + предмет)
51
+ block_img, block_file = forge_texture(f"block of {prompt}", resolution, pixelate, style, -1)
52
+ item_img, item_file = forge_texture(f"item {prompt} ingot or tool", resolution, pixelate, style, -1)
53
+ return block_img, block_file, item_img, item_file
 
 
54
 
55
+ # UI
56
+ css = ".gradio-container {background: #050505; color: #a78bfa;} .main-btn {background: linear-gradient(90deg, #4c1d95, #7c3aed) !important;}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
59
+ gr.Markdown("# 🔮 The Cursed: Texture Forge v4.0")
60
 
 
 
 
61
  with gr.Tabs():
62
  with gr.TabItem("Одиночная текстура"):
63
  with gr.Row():
64
  with gr.Column():
65
+ p_in = gr.Textbox(label="Описание", placeholder="dark obsidian with eyes")
66
+ with gr.Row():
67
+ r_in = gr.Dropdown(["16x16", "32x32", "64x64", "128x128", "512x512"], value="128x128", label="Разрешение")
68
+ s_in = gr.Dropdown(["Cursed 🔮", "Classic ⛏️", "HD Realism ✨"], value="Cursed 🔮", label="Стиль")
69
  px_in = gr.Checkbox(label="Pixel Art Mode", value=True)
70
+ seed_in = gr.Number(label="Seed (-1 для случайного)", value=-1)
71
+ btn_p = gr.Button("🔥 ВЫКОВАТЬ", variant="primary", elem_classes="main-btn")
72
  with gr.Column():
73
+ out_img = gr.Image(label="Предпросмотр", type="pil")
74
+ out_file = gr.File(label="Скачать .PNG для Minecraft")
75
 
76
+ with gr.TabItem("📦 Генерация сета"):
 
77
  with gr.Row():
78
  with gr.Column():
79
+ set_p = gr.Textbox(label="Тема сета", placeholder="void crystal")
 
 
80
  btn_s = gr.Button("⚒️ СОЗДАТЬ СЕТ", variant="primary")
81
  with gr.Column():
82
  with gr.Row():
83
+ out_b = gr.Image(label="Блок"); out_i = gr.Image(label="Предмет")
84
+ with gr.Row():
85
+ out_b_f = gr.File(label="PNG Блока"); out_i_f = gr.File(label="PNG Предмета")
86
 
87
+ btn_p.click(forge_texture, [p_in, r_in, px_in, s_in, seed_in], [out_img, out_file])
88
+ btn_s.click(forge_set, [set_p, r_in, px_in, s_in], [out_b, out_b_f, out_i, out_i_f])
89
 
90
  demo.launch()