151 lines
4.9 KiB
Python
151 lines
4.9 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Image Processing Service für Intelectra WebShop
|
|
EINFACH & SCHNELL - erstellt nur Thumbnails!
|
|
Kompatibel mit Legacy PHP item.class.php
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import os
|
|
from PIL import Image
|
|
import logging
|
|
|
|
# Logging
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(levelname)s - %(message)s',
|
|
handlers=[
|
|
logging.FileHandler('/var/www/vhosts/intelectra.de/httpdocs/logs/image_processing.log'),
|
|
logging.StreamHandler()
|
|
]
|
|
)
|
|
logger = logging.getLogger('image_processing')
|
|
|
|
|
|
class ImageProcessingService:
|
|
"""Einfacher Thumbnail-Generator - keine DB, keine Komplexität!"""
|
|
|
|
def __init__(self, config):
|
|
"""
|
|
config = {
|
|
'source_file': '/full/path/to/original.jpg',
|
|
'watermark': 0 oder 1,
|
|
'shop_system': 'intelectra_shop',
|
|
'document_root': '/var/www/...',
|
|
'image_sizes': [['thumb_', 90], ['overview_', 150], ...] # Von PHP übergeben!
|
|
}
|
|
"""
|
|
self.source_file = config.get('source_file')
|
|
self.watermark_enabled = config.get('watermark', 0) == 1
|
|
self.document_root = config.get('document_root', '')
|
|
|
|
# Bildgrößen von PHP übernehmen (aus DB-Konfiguration!)
|
|
# PHP übergibt: [['overview_', 150], ['thumb_', 90], ['details_', 330], ['detaildefault_', 600]]
|
|
php_image_sizes = config.get('image_sizes', [])
|
|
|
|
# In Python-Format konvertieren: [('prefix', size), ...]
|
|
self.image_sizes = []
|
|
|
|
# Original resized (falls konfiguriert)
|
|
self.image_sizes.append(('', 800))
|
|
|
|
# Thumbnails von PHP config
|
|
for img_config in php_image_sizes:
|
|
if isinstance(img_config, (list, tuple)) and len(img_config) >= 2:
|
|
prefix = img_config[0]
|
|
size = int(img_config[1])
|
|
self.image_sizes.append((prefix, size))
|
|
|
|
logger.info(f"Service initialized for: {self.source_file}")
|
|
logger.info(f"Image sizes: {self.image_sizes}")
|
|
|
|
def process(self):
|
|
"""Hauptfunktion: Erstellt alle Thumbnails"""
|
|
try:
|
|
if not os.path.exists(self.source_file):
|
|
logger.error(f"Source file not found: {self.source_file}")
|
|
return False
|
|
|
|
# Original-Bild öffnen
|
|
with Image.open(self.source_file) as img:
|
|
# Original Format beibehalten (JPG/PNG/GIF)
|
|
img_format = img.format
|
|
|
|
# Alle Größen generieren
|
|
for prefix, size in self.image_sizes:
|
|
self.create_thumbnail(img, prefix, size, img_format)
|
|
|
|
logger.info(f"✅ Successfully processed: {self.source_file}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"❌ Error processing {self.source_file}: {str(e)}")
|
|
return False
|
|
|
|
def create_thumbnail(self, img, prefix, max_size, img_format):
|
|
"""Erstellt ein Thumbnail mit gegebener Größe"""
|
|
try:
|
|
# Dateiname mit Präfix
|
|
source_dir = os.path.dirname(self.source_file)
|
|
source_filename = os.path.basename(self.source_file)
|
|
target_filename = f"{prefix}{source_filename}"
|
|
target_path = os.path.join(source_dir, target_filename)
|
|
|
|
# Kopie erstellen für Resize
|
|
thumb = img.copy()
|
|
|
|
# Proportional auf max_size verkleinern (behält Aspect Ratio!)
|
|
thumb.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
|
|
|
|
# Speichern im Original-Format
|
|
if img_format == 'JPEG':
|
|
thumb.save(target_path, 'JPEG', quality=85, optimize=True)
|
|
elif img_format == 'PNG':
|
|
thumb.save(target_path, 'PNG', optimize=True)
|
|
elif img_format == 'GIF':
|
|
thumb.save(target_path, 'GIF')
|
|
else:
|
|
thumb.save(target_path)
|
|
|
|
logger.debug(f"Created: {target_filename} ({max_size}px)")
|
|
|
|
except Exception as e:
|
|
logger.warning(f"Could not create {prefix} thumbnail: {str(e)}")
|
|
|
|
|
|
def main():
|
|
"""Entry Point - wird von PHP aufgerufen"""
|
|
try:
|
|
if len(sys.argv) < 2:
|
|
logger.error("No config provided!")
|
|
sys.exit(1)
|
|
|
|
# JSON Config von PHP
|
|
config_json = sys.argv[1]
|
|
config = json.loads(config_json)
|
|
|
|
logger.info("=" * 60)
|
|
logger.info("🚀 Image Processing Service STARTED")
|
|
logger.info(f"Source: {config.get('source_file', 'unknown')}")
|
|
|
|
# Service starten
|
|
service = ImageProcessingService(config)
|
|
success = service.process()
|
|
|
|
if success:
|
|
logger.info("✅ Processing completed successfully")
|
|
sys.exit(0)
|
|
else:
|
|
logger.error("❌ Processing failed")
|
|
sys.exit(1)
|
|
|
|
except Exception as e:
|
|
logger.error(f"FATAL ERROR: {str(e)}")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|