|
import gradio as gr |
|
from PIL import Image, ImageFilter |
|
import numpy as np |
|
|
|
def lossless_compression(image, reduction_percent, target_size_kb, auto_mode): |
|
""" |
|
Сжимает изображение без потерь качества, уменьшая количество пикселей и применяя алгоритмы для сохранения деталей. |
|
|
|
Args: |
|
image: Входное изображение (PIL Image). |
|
reduction_percent: Процент уменьшения пикселей по горизонтали (0-100). |
|
target_size_kb: Желаемый размер файла в килобайтах (используется в автоматическом режиме). |
|
auto_mode: Флаг автоматического режима (True/False). |
|
|
|
Returns: |
|
Сжатое изображение (PIL Image). |
|
""" |
|
|
|
if auto_mode: |
|
|
|
reduction_percent, quality = auto_adjust_compression(image, target_size_kb) |
|
else: |
|
|
|
quality = 95 |
|
|
|
|
|
width, height = image.size |
|
new_width = int(width * (1 - reduction_percent / 100)) |
|
resized_image = image.resize((new_width, height), Image.LANCZOS) |
|
|
|
|
|
stretched_image = resized_image.resize((width, height), Image.LANCZOS) |
|
|
|
|
|
blurred_image = adaptive_blur(stretched_image) |
|
|
|
|
|
sharpened_image = blurred_image.filter(ImageFilter.UnsharpMask(radius=1, percent=150, threshold=3)) |
|
|
|
|
|
output_image = sharpened_image |
|
|
|
|
|
if output_image.mode != "RGB": |
|
output_image = output_image.convert("RGB") |
|
|
|
return output_image, reduction_percent, quality |
|
|
|
def auto_adjust_compression(image, target_size_kb): |
|
""" |
|
Автоматически подбирает параметры сжатия для достижения целевого размера файла. |
|
|
|
Args: |
|
image: Входное изображение (PIL Image). |
|
target_size_kb: Желаемый размер файла в килобайтах. |
|
|
|
Returns: |
|
Оптимальный процент уменьшения, оптимальное качество JPEG. |
|
""" |
|
|
|
|
|
initial_reduction = min(50, int(100 * (1 - target_size_kb * 1024 / len(image.tobytes())))) |
|
reduction_percent = initial_reduction |
|
quality = 95 |
|
|
|
|
|
|
|
|
|
|
|
return reduction_percent, quality |
|
|
|
def adaptive_blur(image): |
|
""" |
|
Применяет адаптивное размытие к изображению. |
|
|
|
Args: |
|
image: Входное изображение (PIL Image). |
|
|
|
Returns: |
|
Изображение с адаптивным размытием (PIL Image). |
|
""" |
|
|
|
img_array = np.array(image) |
|
|
|
|
|
|
|
|
|
std_dev = np.std(img_array) |
|
|
|
if std_dev < 20: |
|
|
|
blurred_image = image.filter(ImageFilter.GaussianBlur(radius=2)) |
|
else: |
|
|
|
blurred_image = image.filter(ImageFilter.GaussianBlur(radius=1)) |
|
|
|
return blurred_image |
|
|
|
def save_compressed_image(image, quality, filename="compressed_image.jpg"): |
|
""" |
|
Сохраняет сжатое изображение с указанным качеством. |
|
|
|
Args: |
|
image: PIL Image. |
|
quality: Качество JPEG (0-100). |
|
filename: Имя файла для сохранения. |
|
""" |
|
image.save(filename, "JPEG", optimize=True, quality=quality) |
|
|
|
|
|
def gradio_interface(image, reduction_percent, target_size_kb, auto_mode): |
|
compressed_image, used_reduction, used_quality = lossless_compression(image, reduction_percent, target_size_kb, auto_mode) |
|
save_compressed_image(compressed_image, used_quality) |
|
return compressed_image, f"Использованное уменьшение: {used_reduction:.2f}%, Качество JPEG: {used_quality}" |
|
|
|
iface = gr.Interface( |
|
fn=gradio_interface, |
|
inputs=[ |
|
gr.Image(type="pil", label="Исходное изображение"), |
|
gr.Slider(0, 50, step=1, value=12, label="Процент уменьшения пикселей по горизонтали (ручной режим)"), |
|
gr.Slider(1, 200, step=1, value=50, label="Желаемый размер файла в KB (автоматический режим)"), |
|
gr.Checkbox(label="Автоматический режим"), |
|
], |
|
outputs=[ |
|
gr.Image(type="pil", label="Сжатое изображение"), |
|
gr.Textbox(label="Параметры сжатия") |
|
], |
|
title="Сжатие изображений без потерь", |
|
description="Уменьшает размер изображения, сохраняя визуальное качество. " |
|
"Выберите автоматический режим или введите желаемый размер файла " |
|
"или процент уменьшения пикселей вручную.", |
|
) |
|
|
|
iface.launch() |