svg image support #374

This commit is contained in:
rimu 2024-12-06 10:21:44 +13:00
parent 4f95d1237e
commit 4e87a365b3
7 changed files with 43 additions and 30 deletions

View file

@ -155,7 +155,7 @@ class CreateImageForm(CreatePostForm):
def validate(self, extra_validators=None) -> bool: def validate(self, extra_validators=None) -> bool:
uploaded_file = request.files['image_file'] uploaded_file = request.files['image_file']
if uploaded_file and uploaded_file.filename != '': if uploaded_file and uploaded_file.filename != '' and not uploaded_file.filename.endswith('.svg'):
Image.MAX_IMAGE_PIXELS = 89478485 Image.MAX_IMAGE_PIXELS = 89478485
# Do not allow fascist meme content # Do not allow fascist meme content
try: try:

View file

@ -679,13 +679,14 @@ def add_post(actor, type):
Image.MAX_IMAGE_PIXELS = 89478485 Image.MAX_IMAGE_PIXELS = 89478485
# resize if necessary # resize if necessary
img = Image.open(final_place) if not final_place.endswith('.svg'):
if '.' + img.format.lower() in allowed_extensions: img = Image.open(final_place)
img = ImageOps.exif_transpose(img) if '.' + img.format.lower() in allowed_extensions:
img = ImageOps.exif_transpose(img)
# limit full sized version to 2000px # limit full sized version to 2000px
img.thumbnail((2000, 2000)) img.thumbnail((2000, 2000))
img.save(final_place) img.save(final_place)
request_json['object']['attachment'] = [{'type': 'Image', 'url': f'https://{current_app.config["SERVER_NAME"]}/{final_place.replace("app/", "")}', request_json['object']['attachment'] = [{'type': 'Image', 'url': f'https://{current_app.config["SERVER_NAME"]}/{final_place.replace("app/", "")}',
'name': form.image_alt_text.data}] 'name': form.image_alt_text.data}]

View file

@ -25,7 +25,7 @@ from sqlalchemy import func, desc, text
import os import os
allowed_extensions = ['.gif', '.jpg', '.jpeg', '.png', '.webp', '.heic', '.mpo', '.avif'] allowed_extensions = ['.gif', '.jpg', '.jpeg', '.png', '.webp', '.heic', '.mpo', '.avif', '.svg']
def search_for_community(address: str): def search_for_community(address: str):
@ -649,30 +649,38 @@ def save_icon_file(icon_file, directory='communities') -> File:
if file_ext.lower() == '.heic': if file_ext.lower() == '.heic':
register_heif_opener() register_heif_opener()
elif file_ext.lower() == '.avif':
import pillow_avif
# resize if necessary # resize if necessary
Image.MAX_IMAGE_PIXELS = 89478485 if file_ext.lower() in allowed_extensions:
img = Image.open(final_place) if file_ext.lower() == '.svg': # svgs don't need to be resized
if '.' + img.format.lower() in allowed_extensions: file = File(file_path=final_place, file_name=new_filename + file_ext, alt_text=f'{directory} icon',
img = ImageOps.exif_transpose(img) thumbnail_path=final_place)
img_width = img.width db.session.add(file)
img_height = img.height return file
if img.width > 250 or img.height > 250: else:
img.thumbnail((250, 250)) Image.MAX_IMAGE_PIXELS = 89478485
img.save(final_place) img = Image.open(final_place)
img = ImageOps.exif_transpose(img)
img_width = img.width img_width = img.width
img_height = img.height img_height = img.height
# save a second, smaller, version as a thumbnail if img.width > 250 or img.height > 250:
img.thumbnail((40, 40)) img.thumbnail((250, 250))
img.save(final_place_thumbnail, format="WebP", quality=93) img.save(final_place)
thumbnail_width = img.width img_width = img.width
thumbnail_height = img.height img_height = img.height
# save a second, smaller, version as a thumbnail
img.thumbnail((40, 40))
img.save(final_place_thumbnail, format="WebP", quality=93)
thumbnail_width = img.width
thumbnail_height = img.height
file = File(file_path=final_place, file_name=new_filename + file_ext, alt_text=f'{directory} icon', file = File(file_path=final_place, file_name=new_filename + file_ext, alt_text=f'{directory} icon',
width=img_width, height=img_height, thumbnail_width=thumbnail_width, width=img_width, height=img_height, thumbnail_width=thumbnail_width,
thumbnail_height=thumbnail_height, thumbnail_path=final_place_thumbnail) thumbnail_height=thumbnail_height, thumbnail_path=final_place_thumbnail)
db.session.add(file) db.session.add(file)
return file return file
else: else:
abort(400) abort(400)
@ -695,6 +703,8 @@ def save_banner_file(banner_file, directory='communities') -> File:
if file_ext.lower() == '.heic': if file_ext.lower() == '.heic':
register_heif_opener() register_heif_opener()
elif file_ext.lower() == '.avif':
import pillow_avif
# resize if necessary # resize if necessary
Image.MAX_IMAGE_PIXELS = 89478485 Image.MAX_IMAGE_PIXELS = 89478485

View file

@ -905,6 +905,7 @@ div.navbar {
} }
.post_teaser_image_preview img { .post_teaser_image_preview img {
max-width: 100%; max-width: 100%;
min-width: 150px;
margin-right: 4px; margin-right: 4px;
border-radius: 5px; border-radius: 5px;
height: auto; height: auto;

View file

@ -501,6 +501,7 @@ div.navbar {
} }
img { img {
max-width: 100%; max-width: 100%;
min-width: 150px;
margin-right: 4px; margin-right: 4px;
border-radius: 5px; border-radius: 5px;
height: auto; height: auto;

View file

@ -22,9 +22,9 @@
</div> </div>
{{ render_field(form.description) }} {{ render_field(form.description) }}
{{ render_field(form.icon_file) }} {{ render_field(form.icon_file) }}
<small class="field_hint">Provide a square image that looks good when small.</small> <small class="field_hint">{{ _('Provide a square image that looks good when small. SVG is allowed.') }}</small>
{{ render_field(form.banner_file) }} {{ render_field(form.banner_file) }}
<small class="field_hint">Provide a wide image - letterbox orientation.</small> <small class="field_hint">{{ _('Provide a wide image - letterbox orientation.') }}</small>
{{ render_field(form.rules) }} {{ render_field(form.rules) }}
{{ render_field(form.nsfw) }} {{ render_field(form.nsfw) }}
{{ render_field(form.local_only) }} {{ render_field(form.local_only) }}

View file

@ -187,7 +187,7 @@ def make_cache_key(sort=None, post_id=None, view_filter=None):
def is_image_url(url): def is_image_url(url):
common_image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp', '.avif'] common_image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp', '.avif', '.svg+xml', '.svg+xml; charset=utf-8']
mime_type = mime_type_using_head(url) mime_type = mime_type_using_head(url)
if mime_type: if mime_type:
mime_type_parts = mime_type.split('/') mime_type_parts = mime_type.split('/')