feat(pos): add editable showcase creation date for kits
- Add showcase_created_at field to ProductKit model - Display days ago as badge in product card (0 дней, 1 день, etc.) - Add date input field in edit modal - Auto-set current date/time for new showcase kits Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -158,49 +158,41 @@ class ImageProcessor:
|
||||
@staticmethod
|
||||
def _resize_image(img, size):
|
||||
"""
|
||||
Изменяет размер изображения с сохранением пропорций.
|
||||
Изменяет размер изображения с center-crop до точного квадратного размера.
|
||||
НЕ увеличивает маленькие изображения (сохраняет качество).
|
||||
Создает адаптивный квадрат по размеру реального изображения.
|
||||
Создает квадратное изображение без белых полей.
|
||||
|
||||
Args:
|
||||
img: PIL Image object
|
||||
size: Кортеж (width, height) - максимальный целевой размер
|
||||
size: Кортеж (width, height) - целевой размер (обычно квадратный)
|
||||
|
||||
Returns:
|
||||
PIL Image object - квадратное изображение с минимальным белым фоном
|
||||
PIL Image object - квадратное изображение без белых полей
|
||||
"""
|
||||
# Копируем изображение, чтобы не модифицировать оригинал
|
||||
img_copy = img.copy()
|
||||
target_width, target_height = size
|
||||
|
||||
# Вычисляем пропорции исходного изображения и целевого размера
|
||||
img_aspect = img_copy.width / img_copy.height
|
||||
target_aspect = size[0] / size[1]
|
||||
# Шаг 1: Center crop для получения квадрата
|
||||
# Определяем минимальную сторону (будет размер квадрата)
|
||||
min_side = min(img_copy.width, img_copy.height)
|
||||
|
||||
# Определяем, какой размер будет ограничивающим при масштабировании
|
||||
if img_aspect > target_aspect:
|
||||
# Изображение шире - ограничиваемый размер это ширина
|
||||
new_width = min(img_copy.width, size[0])
|
||||
new_height = int(new_width / img_aspect)
|
||||
# Вычисляем координаты для обрезки из центра
|
||||
left = (img_copy.width - min_side) // 2
|
||||
top = (img_copy.height - min_side) // 2
|
||||
right = left + min_side
|
||||
bottom = top + min_side
|
||||
|
||||
# Обрезаем до квадрата
|
||||
img_cropped = img_copy.crop((left, top, right, bottom))
|
||||
|
||||
# Шаг 2: Масштабируем до целевого размера (если исходный квадрат больше цели)
|
||||
# Не увеличиваем маленькие изображения
|
||||
if min_side > target_width:
|
||||
img_resized = img_cropped.resize((target_width, target_height), Image.Resampling.LANCZOS)
|
||||
else:
|
||||
# Изображение выше - ограничиваемый размер это высота
|
||||
new_height = min(img_copy.height, size[1])
|
||||
new_width = int(new_height * img_aspect)
|
||||
img_resized = img_cropped
|
||||
|
||||
# Масштабируем только если необходимо (не увеличиваем маленькие изображения)
|
||||
if img_copy.width > new_width or img_copy.height > new_height:
|
||||
img_copy = img_copy.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
||||
|
||||
# Создаем адаптивный квадрат по размеру реального изображения (а не по конфигурации)
|
||||
# Это позволяет избежать огромных белых полей для маленьких фото
|
||||
square_size = max(img_copy.width, img_copy.height)
|
||||
new_img = Image.new('RGB', (square_size, square_size), (255, 255, 255))
|
||||
|
||||
# Центрируем исходное изображение на белом фоне
|
||||
offset_x = (square_size - img_copy.width) // 2
|
||||
offset_y = (square_size - img_copy.height) // 2
|
||||
new_img.paste(img_copy, (offset_x, offset_y))
|
||||
|
||||
return new_img
|
||||
return img_resized
|
||||
|
||||
@staticmethod
|
||||
def _make_square_image(img, max_size):
|
||||
|
||||
Reference in New Issue
Block a user