by3axap commited on
Commit
628e6e4
·
verified ·
1 Parent(s): 94348f1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +21 -47
app.py CHANGED
@@ -1,24 +1,18 @@
 
1
  import math
2
  import re
3
  import tempfile
4
-
5
-
6
  from flask import Flask, render_template, request, send_file, Response
7
- from PIL import Image, ImageOps, ImageDraw, ImageColor
8
  import numpy as np
9
 
10
  # Проверка наличия MoviePy
11
-
12
  try:
13
  from moviepy.editor import VideoFileClip
14
  MOVIEPY_AVAILABLE = True
15
  except ImportError:
16
  MOVIEPY_AVAILABLE = False
17
 
18
-
19
-
20
-
21
-
22
  app = Flask(__name__)
23
 
24
  # --- Вспомогательные функции ---
@@ -34,13 +28,11 @@ def prepare_svg_content(file_storage):
34
  inner = re.sub(r'</svg>', '', inner, flags=re.I)
35
  inner = re.sub(r'<\?xml[^>]*\?>|<!DOCTYPE[^>]*>', '', inner, flags=re.I)
36
 
37
- # Удаляем явные заливки, чтобы управлять цветом через группу
38
- # (Опционально, но помогает для монохромных иконок)
39
- # inner = re.sub(r'fill="[^"]*"', '', inner)
40
-
41
  return inner, vbox
42
  except:
43
- return '<rect width="100" height="100" />', "0 0 100 100"
44
 
45
  def calculate_grid_items(width, height, density, gap_x, gap_y, shift, base_scale, growth, growth_type, invert, pixel_data=None):
46
  """Математическое ядро расчета сетки"""
@@ -52,11 +44,6 @@ def calculate_grid_items(width, height, density, gap_x, gap_y, shift, base_scale
52
 
53
  items = []
54
 
55
-
56
-
57
-
58
-
59
-
60
  for r in range(rows):
61
  row_shift = (r * shift * step)
62
  # Оптимизация цикла по колонкам
@@ -68,13 +55,9 @@ def calculate_grid_items(width, height, density, gap_x, gap_y, shift, base_scale
68
  grid_y = r * step
69
 
70
  if grid_x < -step or grid_x > width:
71
-
72
  continue
73
 
74
  # Логика яркости
75
-
76
-
77
-
78
  is_visible = True
79
 
80
  if pixel_data is not None:
@@ -89,7 +72,6 @@ def calculate_grid_items(width, height, density, gap_x, gap_y, shift, base_scale
89
  except:
90
  pass
91
 
92
-
93
  if not is_visible:
94
  continue
95
 
@@ -105,11 +87,6 @@ def calculate_grid_items(width, height, density, gap_x, gap_y, shift, base_scale
105
  mod_w = 1.0 - (wave * growth)
106
  mod_w = max(0.01, min(1.0, mod_w))
107
 
108
-
109
-
110
-
111
-
112
-
113
  content_w = cell_w_max * base_scale * mod_w
114
  content_h = cell_h_max * base_scale
115
 
@@ -119,8 +96,6 @@ def calculate_grid_items(width, height, density, gap_x, gap_y, shift, base_scale
119
  items.append({
120
  'cx': cx, 'cy': cy,
121
  'w': content_w, 'h': content_h
122
-
123
-
124
  })
125
 
126
  return items, step
@@ -130,6 +105,7 @@ def calculate_grid_items(width, height, density, gap_x, gap_y, shift, base_scale
130
  @app.route('/')
131
  def index():
132
  return render_template('index.html')
 
133
  @app.route('/download_svg', methods=['POST'])
134
  def download_svg():
135
  try:
@@ -137,22 +113,21 @@ def download_svg():
137
  density = int(request.form.get('density', 40))
138
  gap_x = float(request.form.get('gap_x', 0))
139
  gap_y = float(request.form.get('gap_y', 0))
 
140
  base_scale = float(request.form.get('base_scale', 1.0))
141
  growth = float(request.form.get('growth', 0))
142
  growth_type = request.form.get('growth_type', 'sine')
143
-
144
  invert = request.form.get('invert') == 'true'
145
 
146
- # Цвета
147
- bg_color = request.form.get('bg_color', '#ffffff')
148
- fill_color = request.form.get('fill_color', '#000000')
149
-
150
  canvas_w, canvas_h = 1400, 900
151
 
152
  # SVG Symbol
153
  svg_file = request.files.get('shape_svg')
154
  if svg_file and svg_file.filename != '':
155
  symbol_content, v_box = prepare_svg_content(svg_file)
 
 
 
156
  vb_parts = [float(x) for x in v_box.split()]
157
  vb_w, vb_h = vb_parts[2], vb_parts[3]
158
 
@@ -172,10 +147,9 @@ def download_svg():
172
  sx = item['w'] / vb_w
173
  sy = item['h'] / vb_h
174
  transform = f'translate({item["cx"]:.2f} {item["cy"]:.2f}) scale({sx:.4f} {sy:.4f}) translate({-vb_w/2:.2f} {-vb_h/2:.2f})'
175
- # Применяем цвет заливки к группе
176
- body.append(f'<g transform="{transform}" fill="{fill_color}">{symbol_content}</g>')
177
 
178
- svg_str = f'<svg xmlns="http://www.w3.org/2000/svg" width="{canvas_w}" height="{canvas_h}" viewBox="0 0 {canvas_w} {canvas_h}" style="background:{bg_color};">{"".join(body)}</svg>'
179
 
180
  return Response(svg_str, mimetype="image/svg+xml", headers={"Content-disposition": "attachment; filename=pattern.svg"})
181
 
@@ -190,15 +164,13 @@ def process_video():
190
  temp_dir = tempfile.mkdtemp()
191
  try:
192
  density = int(request.form.get('density', 40))
 
 
 
193
  base_scale = float(request.form.get('base_scale', 1.0))
194
  growth = float(request.form.get('growth', 0))
195
  growth_type = request.form.get('growth_type', 'sine')
196
-
197
  invert = request.form.get('invert') == 'true'
198
-
199
- # Цвета
200
- bg_color = request.form.get('bg_color', '#ffffff')
201
- fill_color = request.form.get('fill_color', '#000000')
202
 
203
  video_file = request.files.get('video_file')
204
  if not video_file:
@@ -212,22 +184,24 @@ def process_video():
212
  img_pil = Image.fromarray(frame).convert("L")
213
  w, h = img_pil.size
214
 
215
- # Рендеринг кадра с цветом фона
216
- canvas = Image.new("RGB", (w, h), bg_color)
217
  draw = ImageDraw.Draw(canvas)
218
 
219
  # Используем ту же логику расчета
220
  items, _ = calculate_grid_items(w, h, density, gap_x, gap_y, shift, base_scale, growth, growth_type, invert, img_pil)
221
 
222
  for item in items:
 
 
223
  x0 = item['cx'] - item['w']/2
224
  y0 = item['cy'] - item['h']/2
225
- # Рисуем прямоугольники с цветом паттерна
226
- draw.rectangle([x0, y0, x0 + item['w'], y0 + item['h']], fill=fill_color)
227
 
228
  return np.array(canvas)
229
 
230
  clip = VideoFileClip(input_path)
 
231
  # clip = clip.set_fps(24)
232
 
233
  new_clip = clip.fl(process_frame)
 
1
+ import os
2
  import math
3
  import re
4
  import tempfile
 
 
5
  from flask import Flask, render_template, request, send_file, Response
6
+ from PIL import Image, ImageOps, ImageDraw
7
  import numpy as np
8
 
9
  # Проверка наличия MoviePy
 
10
  try:
11
  from moviepy.editor import VideoFileClip
12
  MOVIEPY_AVAILABLE = True
13
  except ImportError:
14
  MOVIEPY_AVAILABLE = False
15
 
 
 
 
 
16
  app = Flask(__name__)
17
 
18
  # --- Вспомогательные функции ---
 
28
  inner = re.sub(r'</svg>', '', inner, flags=re.I)
29
  inner = re.sub(r'<\?xml[^>]*\?>|<!DOCTYPE[^>]*>', '', inner, flags=re.I)
30
 
31
+ if 'fill=' not in inner:
32
+ inner = f'<g fill="black">{inner}</g>'
 
 
33
  return inner, vbox
34
  except:
35
+ return '<rect width="100" height="100" fill="black"/>', "0 0 100 100"
36
 
37
  def calculate_grid_items(width, height, density, gap_x, gap_y, shift, base_scale, growth, growth_type, invert, pixel_data=None):
38
  """Математическое ядро расчета сетки"""
 
44
 
45
  items = []
46
 
 
 
 
 
 
47
  for r in range(rows):
48
  row_shift = (r * shift * step)
49
  # Оптимизация цикла по колонкам
 
55
  grid_y = r * step
56
 
57
  if grid_x < -step or grid_x > width:
 
58
  continue
59
 
60
  # Логика яркости
 
 
 
61
  is_visible = True
62
 
63
  if pixel_data is not None:
 
72
  except:
73
  pass
74
 
 
75
  if not is_visible:
76
  continue
77
 
 
87
  mod_w = 1.0 - (wave * growth)
88
  mod_w = max(0.01, min(1.0, mod_w))
89
 
 
 
 
 
 
90
  content_w = cell_w_max * base_scale * mod_w
91
  content_h = cell_h_max * base_scale
92
 
 
96
  items.append({
97
  'cx': cx, 'cy': cy,
98
  'w': content_w, 'h': content_h
 
 
99
  })
100
 
101
  return items, step
 
105
  @app.route('/')
106
  def index():
107
  return render_template('index.html')
108
+
109
  @app.route('/download_svg', methods=['POST'])
110
  def download_svg():
111
  try:
 
113
  density = int(request.form.get('density', 40))
114
  gap_x = float(request.form.get('gap_x', 0))
115
  gap_y = float(request.form.get('gap_y', 0))
116
+ shift = float(request.form.get('shift_stagger', 0))
117
  base_scale = float(request.form.get('base_scale', 1.0))
118
  growth = float(request.form.get('growth', 0))
119
  growth_type = request.form.get('growth_type', 'sine')
 
120
  invert = request.form.get('invert') == 'true'
121
 
 
 
 
 
122
  canvas_w, canvas_h = 1400, 900
123
 
124
  # SVG Symbol
125
  svg_file = request.files.get('shape_svg')
126
  if svg_file and svg_file.filename != '':
127
  symbol_content, v_box = prepare_svg_content(svg_file)
128
+ else:
129
+ symbol_content, v_box = ('<rect width="100" height="100" fill="black"/>', "0 0 100 100")
130
+
131
  vb_parts = [float(x) for x in v_box.split()]
132
  vb_w, vb_h = vb_parts[2], vb_parts[3]
133
 
 
147
  sx = item['w'] / vb_w
148
  sy = item['h'] / vb_h
149
  transform = f'translate({item["cx"]:.2f} {item["cy"]:.2f}) scale({sx:.4f} {sy:.4f}) translate({-vb_w/2:.2f} {-vb_h/2:.2f})'
150
+ body.append(f'<g transform="{transform}">{symbol_content}</g>')
 
151
 
152
+ svg_str = f'<svg xmlns="http://www.w3.org/2000/svg" width="{canvas_w}" height="{canvas_h}" viewBox="0 0 {canvas_w} {canvas_h}" style="background:white;">{"".join(body)}</svg>'
153
 
154
  return Response(svg_str, mimetype="image/svg+xml", headers={"Content-disposition": "attachment; filename=pattern.svg"})
155
 
 
164
  temp_dir = tempfile.mkdtemp()
165
  try:
166
  density = int(request.form.get('density', 40))
167
+ gap_x = float(request.form.get('gap_x', 0))
168
+ gap_y = float(request.form.get('gap_y', 0))
169
+ shift = float(request.form.get('shift_stagger', 0))
170
  base_scale = float(request.form.get('base_scale', 1.0))
171
  growth = float(request.form.get('growth', 0))
172
  growth_type = request.form.get('growth_type', 'sine')
 
173
  invert = request.form.get('invert') == 'true'
 
 
 
 
174
 
175
  video_file = request.files.get('video_file')
176
  if not video_file:
 
184
  img_pil = Image.fromarray(frame).convert("L")
185
  w, h = img_pil.size
186
 
187
+ # Рендеринг кадра
188
+ canvas = Image.new("RGB", (w, h), "white")
189
  draw = ImageDraw.Draw(canvas)
190
 
191
  # Используем ту же логику расчета
192
  items, _ = calculate_grid_items(w, h, density, gap_x, gap_y, shift, base_scale, growth, growth_type, invert, img_pil)
193
 
194
  for item in items:
195
+ # Рисуем прямоугольники (быстро для видео)
196
+ # Если нужно SVG в видео, это сильно замедлит процесс
197
  x0 = item['cx'] - item['w']/2
198
  y0 = item['cy'] - item['h']/2
199
+ draw.rectangle([x0, y0, x0 + item['w'], y0 + item['h']], fill="black")
 
200
 
201
  return np.array(canvas)
202
 
203
  clip = VideoFileClip(input_path)
204
+ # Ограничение FPS для ускорения, если видео большое
205
  # clip = clip.set_fps(24)
206
 
207
  new_clip = clip.fl(process_frame)