-
Notifications
You must be signed in to change notification settings - Fork 35
⚡ Bolt: Optimize image processing and fix RGBA resize crash #353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -86,6 +86,7 @@ def _validate_uploaded_file_sync(file: UploadFile) -> Optional[Image.Image]: | |
| # Additional content validation: Try to open with PIL to ensure it's a valid image | ||
| try: | ||
| img = Image.open(file.file) | ||
| original_format = img.format # Capture format before operations | ||
| # Optimization: Skip img.verify() to avoid full file read. | ||
| # Corrupt files will fail during resize or subsequent processing. | ||
|
|
||
|
|
@@ -101,7 +102,11 @@ def _validate_uploaded_file_sync(file: UploadFile) -> Optional[Image.Image]: | |
|
|
||
| # Save resized image back to file | ||
| output = io.BytesIO() | ||
| img.save(output, format=img.format or 'JPEG', quality=85) | ||
|
|
||
| # Determine save format (default to PNG for RGBA to avoid JPEG error) | ||
| save_format = original_format or ('PNG' if img.mode == 'RGBA' else 'JPEG') | ||
|
|
||
| img.save(output, format=save_format, quality=85) | ||
| output.seek(0) | ||
|
|
||
| # Replace file content | ||
|
|
@@ -168,6 +173,7 @@ def process_uploaded_image_sync(file: UploadFile) -> io.BytesIO: | |
|
|
||
| try: | ||
| img = Image.open(file.file) | ||
| original_format = img.format # Capture format before operations | ||
|
|
||
| # Resize if needed | ||
| if img.width > 1024 or img.height > 1024: | ||
|
|
@@ -177,14 +183,17 @@ def process_uploaded_image_sync(file: UploadFile) -> io.BytesIO: | |
| img = img.resize((new_width, new_height), Image.Resampling.BILINEAR) | ||
|
|
||
| # Strip EXIF | ||
| img_no_exif = Image.new(img.mode, img.size) | ||
| img_no_exif.paste(img) | ||
| # Optimization: Clear info dictionary instead of creating new image and pasting (avoids full copy) | ||
| if hasattr(img, 'info'): | ||
| img.info.clear() | ||
|
|
||
| # Save to BytesIO | ||
| output = io.BytesIO() | ||
| # Preserve format or default to JPEG | ||
| fmt = img.format or 'JPEG' | ||
| img_no_exif.save(output, format=fmt, quality=85) | ||
|
|
||
| # Preserve format or default to JPEG, handling RGBA edge case | ||
| save_format = original_format or ('PNG' if img.mode == 'RGBA' else 'JPEG') | ||
|
|
||
| img.save(output, format=save_format, quality=85) | ||
|
Comment on lines
185
to
+196
|
||
| output.seek(0) | ||
|
|
||
| return output | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After resizing,
imgis a new PIL object whoseformatis typicallyNone. Even though you preserveoriginal_formatfor saving back intofile.file, you still return the resizedimgwithimg.format=None, which can later cause downstream code (e.g., helpers that default to JPEG whenimage.formatis missing) to attempt JPEG encoding and crash again for RGBA images. Consider restoringimg.format(and/or returning a reopened image from the resized bytes) so callers receive an image with a correct format.