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
|
temp_ppt = temp_path / filename
|
||||||
shutil.copy2(filepath, temp_ppt)
|
shutil.copy2(filepath, temp_ppt)
|
||||||
|
|
||||||
# Convert presentation to images (PNG format)
|
# Convert presentation to PDF first (for better quality)
|
||||||
# Using LibreOffice headless mode with custom resolution
|
|
||||||
convert_cmd = [
|
convert_cmd = [
|
||||||
libreoffice_cmd,
|
libreoffice_cmd,
|
||||||
'--headless',
|
'--headless',
|
||||||
'--convert-to', 'png',
|
'--convert-to', 'pdf',
|
||||||
'--outdir', str(temp_path),
|
'--outdir', str(temp_path),
|
||||||
str(temp_ppt)
|
str(temp_ppt)
|
||||||
]
|
]
|
||||||
|
|
||||||
log_action('info', f'Converting presentation to images: {filename}')
|
log_action('info', f'Converting presentation to PDF: {filename}')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
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}')
|
log_action('error', f'LibreOffice conversion failed: {result.stderr}')
|
||||||
return True, "Presentation accepted without conversion (conversion failed)"
|
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
|
# Find generated PNG files
|
||||||
png_files = sorted(temp_path.glob('*.png'))
|
png_files = sorted(temp_path.glob('slide-*.png'))
|
||||||
|
|
||||||
if not png_files:
|
if not png_files:
|
||||||
log_action('warning', f'No images generated from presentation: {filename}')
|
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']
|
upload_folder = current_app.config['UPLOAD_FOLDER']
|
||||||
base_name = os.path.splitext(filename)[0]
|
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
|
slide_count = 0
|
||||||
for idx, png_file in enumerate(png_files, start=1):
|
for idx, png_file in enumerate(png_files, start=1):
|
||||||
# Create descriptive filename
|
# Create descriptive filename
|
||||||
@@ -570,8 +601,8 @@ def process_presentation_file(filepath: str, filename: str) -> tuple[bool, str]:
|
|||||||
|
|
||||||
shutil.move(str(png_file), destination)
|
shutil.move(str(png_file), destination)
|
||||||
|
|
||||||
# Optimize the image to Full HD (1920x1080)
|
# Resize to exact Full HD dimensions (1920x1080) maintaining aspect ratio
|
||||||
optimize_image_to_fullhd(destination)
|
resize_image_to_fullhd(destination)
|
||||||
|
|
||||||
slide_count += 1
|
slide_count += 1
|
||||||
|
|
||||||
@@ -616,6 +647,64 @@ def create_fullhd_image(img):
|
|||||||
return fullhd_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:
|
def optimize_image_to_fullhd(filepath: str) -> bool:
|
||||||
"""Optimize and resize image file to Full HD (1920x1080) maintaining aspect ratio."""
|
"""Optimize and resize image file to Full HD (1920x1080) maintaining aspect ratio."""
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user