AllFileConverter / converters /image_converter.py
embedingHF's picture
Upload folder using huggingface_hub
84fc8e7 verified
Raw
History Blame Contribute Delete
6.24 kB
from PIL import (
Image,
ImageEnhance,
ImageFilter,
ImageOps
)
from pathlib import Path
from typing import Callable, Dict, Any
import traceback
import os
class ImageConverter:
SUPPORTED_FORMATS = {
".png",
".jpg",
".jpeg",
".webp",
".bmp",
".tiff"
}
def __init__(self):
# Prevent PIL decompression bomb crash
Image.MAX_IMAGE_PIXELS = None
def convert(
self,
input_path: str,
output_path: str,
options: Dict[str, Any] | None = None,
progress_callback: Callable = None
) -> bool:
options = options or {}
try:
self._update_progress(
progress_callback,
10
)
# Validate input
if not os.path.exists(input_path):
raise FileNotFoundError(
input_path
)
input_ext = Path(input_path).suffix.lower()
output_ext = Path(output_path).suffix.lower()
# Validate output format
if output_ext not in self.SUPPORTED_FORMATS:
raise ValueError(
f"Unsupported format: {output_ext}"
)
# Open image safely
img = Image.open(input_path)
# Fix EXIF rotation
img = ImageOps.exif_transpose(img)
self._update_progress(
progress_callback,
25
)
# Convert palette images safely
if img.mode == "P":
img = img.convert("RGBA")
# Optional resize
max_size = options.get("max_size")
if max_size:
img.thumbnail(
(max_size, max_size)
)
self._update_progress(
progress_callback,
40
)
# AI enhancement
if options.get(
"ai_enhancement",
False
):
img = self.enhance_image(img)
self._update_progress(
progress_callback,
60
)
# Quality
quality_settings = options.get(
"quality_settings",
{}
)
quality = int(
quality_settings.get(
"image",
85
)
)
# Create output folder
Path(output_path).parent.mkdir(
parents=True,
exist_ok=True
)
# Format handling
if output_ext in [".jpg", ".jpeg"]:
# JPEG does not support transparency
if img.mode in ("RGBA", "LA"):
background = Image.new(
"RGB",
img.size,
(255, 255, 255)
)
background.paste(
img,
mask=img.split()[-1]
)
img = background
else:
img = img.convert("RGB")
img.save(
output_path,
"JPEG",
quality=quality,
optimize=True
)
elif output_ext == ".png":
compress_level = 9
if quality >= 90:
compress_level = 2
elif quality >= 75:
compress_level = 5
img.save(
output_path,
"PNG",
optimize=True,
compress_level=compress_level
)
elif output_ext == ".webp":
img.save(
output_path,
"WEBP",
quality=quality,
method=6
)
elif output_ext == ".bmp":
if img.mode == "RGBA":
img = img.convert("RGB")
img.save(
output_path,
"BMP"
)
elif output_ext == ".tiff":
img.save(
output_path,
"TIFF",
compression="tiff_lzw"
)
else:
img.save(output_path)
self._update_progress(
progress_callback,
100
)
print(
f"✓ Converted: "
f"{os.path.basename(input_path)} "
f"→ {output_ext}"
)
return True
except Exception as e:
print(
f"Image conversion error: {e}"
)
traceback.print_exc()
return False
def _update_progress(
self,
callback,
value
):
try:
if callback:
callback(value)
except Exception as e:
print(
f"Progress callback error: {e}"
)
def enhance_image(
self,
img
):
try:
# Contrast
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(1.08)
# Sharpness
enhancer = ImageEnhance.Sharpness(img)
img = enhancer.enhance(1.1)
# Slight color boost
enhancer = ImageEnhance.Color(img)
img = enhancer.enhance(1.03)
# Optional smooth sharpen
img = img.filter(
ImageFilter.SHARPEN
)
return img
except Exception as e:
print(
f"Enhancement error: {e}"
)
return img