updated to fullscreen view ppt
This commit is contained in:
@@ -526,17 +526,16 @@ def process_presentation_file(filepath: str, filename: str) -> tuple[bool, str]:
|
||||
temp_ppt = temp_path / filename
|
||||
shutil.copy2(filepath, temp_ppt)
|
||||
|
||||
# Convert presentation to images (PNG format)
|
||||
# Using LibreOffice headless mode with custom resolution
|
||||
# Convert presentation to PDF first (for better quality)
|
||||
convert_cmd = [
|
||||
libreoffice_cmd,
|
||||
'--headless',
|
||||
'--convert-to', 'png',
|
||||
'--convert-to', 'pdf',
|
||||
'--outdir', str(temp_path),
|
||||
str(temp_ppt)
|
||||
]
|
||||
|
||||
log_action('info', f'Converting presentation to images: {filename}')
|
||||
log_action('info', f'Converting presentation to PDF: {filename}')
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
@@ -550,8 +549,40 @@ def process_presentation_file(filepath: str, filename: str) -> tuple[bool, str]:
|
||||
log_action('error', f'LibreOffice conversion failed: {result.stderr}')
|
||||
return True, "Presentation accepted without conversion (conversion failed)"
|
||||
|
||||
# Find generated PDF file
|
||||
pdf_files = list(temp_path.glob('*.pdf'))
|
||||
if not pdf_files:
|
||||
log_action('warning', f'No PDF generated from presentation: {filename}')
|
||||
return True, "Presentation accepted without conversion"
|
||||
|
||||
pdf_file = pdf_files[0]
|
||||
log_action('info', f'Converting PDF to images at Full HD resolution: {pdf_file.name}')
|
||||
|
||||
# Convert PDF to images using pdftoppm at Full HD resolution (1920x1080)
|
||||
# Calculate DPI for Full HD output (assuming standard presentation is 10x7.5 inches)
|
||||
# 1920/10 = 192 DPI for width, use 192 DPI for best quality
|
||||
pdftoppm_cmd = [
|
||||
'pdftoppm',
|
||||
'-png',
|
||||
'-r', '300', # High DPI for quality
|
||||
'-scale-to', '1920', # Scale width to 1920px
|
||||
str(pdf_file),
|
||||
str(temp_path / 'slide')
|
||||
]
|
||||
|
||||
result = subprocess.run(
|
||||
pdftoppm_cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120
|
||||
)
|
||||
|
||||
if result.returncode != 0:
|
||||
log_action('error', f'pdftoppm conversion failed: {result.stderr}')
|
||||
return True, "Presentation accepted without conversion (image conversion failed)"
|
||||
|
||||
# Find generated PNG files
|
||||
png_files = sorted(temp_path.glob('*.png'))
|
||||
png_files = sorted(temp_path.glob('slide-*.png'))
|
||||
|
||||
if not png_files:
|
||||
log_action('warning', f'No images generated from presentation: {filename}')
|
||||
@@ -561,7 +592,7 @@ def process_presentation_file(filepath: str, filename: str) -> tuple[bool, str]:
|
||||
upload_folder = current_app.config['UPLOAD_FOLDER']
|
||||
base_name = os.path.splitext(filename)[0]
|
||||
|
||||
# Move converted images to upload folder
|
||||
# Move converted images to upload folder and resize to exact Full HD
|
||||
slide_count = 0
|
||||
for idx, png_file in enumerate(png_files, start=1):
|
||||
# Create descriptive filename
|
||||
@@ -570,8 +601,8 @@ def process_presentation_file(filepath: str, filename: str) -> tuple[bool, str]:
|
||||
|
||||
shutil.move(str(png_file), destination)
|
||||
|
||||
# Optimize the image to Full HD (1920x1080)
|
||||
optimize_image_to_fullhd(destination)
|
||||
# Resize to exact Full HD dimensions (1920x1080) maintaining aspect ratio
|
||||
resize_image_to_fullhd(destination)
|
||||
|
||||
slide_count += 1
|
||||
|
||||
@@ -616,6 +647,64 @@ def create_fullhd_image(img):
|
||||
return fullhd_img
|
||||
|
||||
|
||||
def resize_image_to_fullhd(filepath: str) -> bool:
|
||||
"""Resize image to exactly Full HD (1920x1080) maintaining aspect ratio with centered crop or padding."""
|
||||
try:
|
||||
from PIL import Image
|
||||
|
||||
img = Image.open(filepath)
|
||||
target_width = 1920
|
||||
target_height = 1080
|
||||
|
||||
# Calculate aspect ratios
|
||||
img_aspect = img.width / img.height
|
||||
target_aspect = target_width / target_height
|
||||
|
||||
if abs(img_aspect - target_aspect) < 0.01:
|
||||
# Aspect ratio is very close, just resize
|
||||
img_resized = img.resize((target_width, target_height), Image.Resampling.LANCZOS)
|
||||
elif img_aspect > target_aspect:
|
||||
# Image is wider than target, fit height and crop/pad width
|
||||
new_height = target_height
|
||||
new_width = int(target_height * img_aspect)
|
||||
img_resized = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
||||
|
||||
# Crop to center if wider
|
||||
if new_width > target_width:
|
||||
left = (new_width - target_width) // 2
|
||||
img_resized = img_resized.crop((left, 0, left + target_width, target_height))
|
||||
else:
|
||||
# Pad with white if narrower
|
||||
result = Image.new('RGB', (target_width, target_height), (255, 255, 255))
|
||||
offset = (target_width - new_width) // 2
|
||||
result.paste(img_resized, (offset, 0))
|
||||
img_resized = result
|
||||
else:
|
||||
# Image is taller than target, fit width and crop/pad height
|
||||
new_width = target_width
|
||||
new_height = int(target_width / img_aspect)
|
||||
img_resized = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
||||
|
||||
# Crop to center if taller
|
||||
if new_height > target_height:
|
||||
top = (new_height - target_height) // 2
|
||||
img_resized = img_resized.crop((0, top, target_width, top + target_height))
|
||||
else:
|
||||
# Pad with white if shorter
|
||||
result = Image.new('RGB', (target_width, target_height), (255, 255, 255))
|
||||
offset = (target_height - new_height) // 2
|
||||
result.paste(img_resized, (0, offset))
|
||||
img_resized = result
|
||||
|
||||
# Save optimized image
|
||||
img_resized.save(filepath, 'PNG', optimize=True, quality=95)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
log_action('error', f'Image resize error: {str(e)}')
|
||||
return False
|
||||
|
||||
|
||||
def optimize_image_to_fullhd(filepath: str) -> bool:
|
||||
"""Optimize and resize image file to Full HD (1920x1080) maintaining aspect ratio."""
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user