Politrees commited on
Commit
d03debd
·
verified ·
1 Parent(s): 18f4b74

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +143 -0
app.py ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from PIL import Image
3
+ import io
4
+
5
+ # ─── Доступные размеры для даунскейла ───
6
+ SIZES = ["8×8", "16×16", "32×32", "64×64", "128×128"]
7
+
8
+ def parse_size(label: str) -> tuple[int, int]:
9
+ """'16×16' → (16, 16)"""
10
+ w, h = label.split("×")
11
+ return int(w), int(h)
12
+
13
+
14
+ def downscale(
15
+ image: Image.Image,
16
+ target_size: str,
17
+ preview_scale: int,
18
+ ) -> tuple[Image.Image, Image.Image, str]:
19
+ """
20
+ 1) Даунскейлит входное изображение до target_size методом NEAREST.
21
+ 2) Апскейлит результат обратно (preview) чтобы пиксели были видны.
22
+ Возвращает (маленькое, превью, инфо-строку).
23
+ """
24
+ if image is None:
25
+ raise gr.Error("Загрузи изображение!")
26
+
27
+ # Принудительно RGBA (текстуры Minecraft часто с альфой)
28
+ image = image.convert("RGBA")
29
+ tw, th = parse_size(target_size)
30
+
31
+ # ── Nearest-Neighbor даунскейл ──
32
+ small = image.resize((tw, th), resample=Image.NEAREST)
33
+
34
+ # ── Превью: масштабируем обратно, чтобы пиксели были чётко видны ──
35
+ preview_w = tw * preview_scale
36
+ preview_h = th * preview_scale
37
+ preview = small.resize((preview_w, preview_h), resample=Image.NEAREST)
38
+
39
+ info = (
40
+ f"Оригинал: {image.size[0]}×{image.size[1]}\n"
41
+ f"Результат: {tw}×{th}\n"
42
+ f"Превью: {preview_w}×{preview_h} (×{preview_scale})"
43
+ )
44
+
45
+ return small, preview, info
46
+
47
+
48
+ # ─── Интерфейс ───────────────────────────────────────────────
49
+ with gr.Blocks(
50
+ title="Minecraft Texture Downscaler",
51
+ theme=gr.themes.Soft(),
52
+ css="""
53
+ /* чёткие пиксели при зуме в браузере */
54
+ .pixelated img {
55
+ image-rendering: pixelated !important;
56
+ image-rendering: -moz-crisp-edges !important;
57
+ image-rendering: crisp-edges !important;
58
+ }
59
+ """,
60
+ ) as demo:
61
+
62
+ gr.Markdown(
63
+ """
64
+ # 🟩 Minecraft Texture Downscaler
65
+ Загрузи текстуру любого размера — получи чёткий **Nearest Neighbor**
66
+ даунскейл без размытия (без bilinear / bicubic).
67
+
68
+ > Идеально для конвертации HD-текстур (128×, 256×, 512×)
69
+ > в ванильный формат 16×16.
70
+ """
71
+ )
72
+
73
+ with gr.Row():
74
+ # ── Левая колонка: входные параметры ──
75
+ with gr.Column(scale=1):
76
+ img_input = gr.Image(
77
+ label="📥 Входная текстура",
78
+ type="pil",
79
+ image_mode="RGBA",
80
+ sources=["upload", "clipboard"],
81
+ )
82
+ target_size = gr.Dropdown(
83
+ label="🎯 Целевой размер",
84
+ choices=SIZES,
85
+ value="16×16",
86
+ )
87
+ preview_scale = gr.Slider(
88
+ label="🔍 Множитель превью",
89
+ minimum=1,
90
+ maximum=32,
91
+ step=1,
92
+ value=16,
93
+ info="Во сколько раз увеличить для наглядности",
94
+ )
95
+ btn = gr.Button("⚡ Даунскейлить", variant="primary", size="lg")
96
+
97
+ # ── Правая колонка: результаты ──
98
+ with gr.Column(scale=2):
99
+ with gr.Row():
100
+ img_small = gr.Image(
101
+ label="📤 Результат (реальный размер)",
102
+ type="pil",
103
+ image_mode="RGBA",
104
+ show_download_button=True,
105
+ elem_classes=["pixelated"],
106
+ )
107
+ img_preview = gr.Image(
108
+ label="🔎 Превью (увеличенное)",
109
+ type="pil",
110
+ image_mode="RGBA",
111
+ elem_classes=["pixelated"],
112
+ )
113
+ info_box = gr.Textbox(
114
+ label="ℹ️ Информация",
115
+ interactive=False,
116
+ lines=3,
117
+ )
118
+
119
+ # ── Обработчик ──
120
+ btn.click(
121
+ fn=downscale,
122
+ inputs=[img_input, target_size, preview_scale],
123
+ outputs=[img_small, img_preview, info_box],
124
+ )
125
+
126
+ # ── Примеры (необязательно, можно убрать) ──
127
+ gr.Markdown(
128
+ """
129
+ ---
130
+ ### Как использовать
131
+ 1. Загрузи PNG-текстуру (например `diamond_ore.png` 128×128).
132
+ 2. Выбери целев��й размер — по умолчанию **16×16**.
133
+ 3. Нажми **⚡ Даунскейлить**.
134
+ 4. Скачай результат (кнопка ⬇️ на картинке).
135
+
136
+ **Nearest Neighbor** сохраняет резкие границы пикселей —
137
+ никакого мыла, как при Bilinear/Lanczos.
138
+ """
139
+ )
140
+
141
+ # Запуск
142
+ if __name__ == "__main__":
143
+ demo.launch()