Implemented image conversion and resizing with pillow.

This commit is contained in:
s3lph 2018-09-09 23:59:06 +02:00
parent a7a2b5a76f
commit 31b1cc9c21
7 changed files with 56 additions and 34 deletions

View file

@ -2,6 +2,8 @@ from typing import Any, Dict, Union
import os
import magic
from io import BytesIO
from PIL import Image
from matemat.webserver import pagelet, RequestArguments, PageletResponse, RedirectResponse, TemplateResponse
from matemat.db import MatematDatabase
@ -124,16 +126,20 @@ def handle_change(args: RequestArguments, user: User, db: MatematDatabase, confi
return
# Detect the MIME type
filemagic: magic.FileMagic = magic.detect_from_content(avatar)
# Currently, only image/png is supported, don't process any other formats
if filemagic.mime_type != 'image/png':
# TODO: Optionally convert to png
if not filemagic.mime_type.startswith('image/'):
return
# Create the absolute path of the upload directory
abspath: str = os.path.join(os.path.abspath(config['UploadDir']), 'thumbnails/users/')
os.makedirs(abspath, exist_ok=True)
try:
# Parse the image data
image: Image = Image.open(BytesIO(avatar))
# Resize the image to 150x150
image.thumbnail((150, 150), Image.LANCZOS)
# Write the image to the file
with open(os.path.join(abspath, f'{user.id}.png'), 'wb') as f:
f.write(avatar)
image.save(os.path.join(abspath, f'{user.id}.png'), 'PNG')
except OSError:
return
except UnicodeDecodeError:
raise ValueError('an argument not a string')
@ -182,22 +188,26 @@ def handle_admin_change(args: RequestArguments, db: MatematDatabase, config: Dic
# If a new product image was uploaded, process it
if 'image' in args:
# Read the raw image data from the request
image = bytes(args.image)
avatar = bytes(args.image)
# Only process the image, if its size is more than zero. Zero size means no new image was uploaded
if len(image) == 0:
if len(avatar) == 0:
return
# Detect the MIME type
filemagic: magic.FileMagic = magic.detect_from_content(image)
# Currently, only image/png is supported, don't process any other formats
if filemagic.mime_type != 'image/png':
# TODO: Optionally convert to png
filemagic: magic.FileMagic = magic.detect_from_content(avatar)
if not filemagic.mime_type.startswith('image/'):
return
# Create the absolute path of the upload directory
abspath: str = os.path.join(os.path.abspath(config['UploadDir']), 'thumbnails/products/')
os.makedirs(abspath, exist_ok=True)
try:
# Parse the image data
image: Image = Image.open(BytesIO(avatar))
# Resize the image to 150x150
image.thumbnail((150, 150), Image.LANCZOS)
# Write the image to the file
with open(os.path.join(abspath, f'{newproduct.id}.png'), 'wb') as f:
f.write(image)
image.save(os.path.join(abspath, f'{newproduct.id}.png'), 'PNG')
except OSError:
return
# The user requested to restock a product
elif change == 'restock':

View file

@ -2,6 +2,8 @@ from typing import Any, Dict, Union
import os
import magic
from PIL import Image
from io import BytesIO
from matemat.webserver import pagelet, RequestArguments, PageletResponse, RedirectResponse, TemplateResponse
from matemat.db import MatematDatabase
@ -101,19 +103,23 @@ def handle_change(args: RequestArguments, product: Product, db: MatematDatabase,
# If a new product image was uploaded, process it
if 'image' in args:
# Read the raw image data from the request
image = bytes(args.image)
avatar = bytes(args.image)
# Only process the image, if its size is more than zero. Zero size means no new image was uploaded
if len(image) == 0:
if len(avatar) == 0:
return
# Detect the MIME type
filemagic: magic.FileMagic = magic.detect_from_content(image)
# Currently, only image/png is supported, don't process any other formats
if filemagic.mime_type != 'image/png':
# TODO: Optionally convert to png
filemagic: magic.FileMagic = magic.detect_from_content(avatar)
if not filemagic.mime_type.startswith('image/'):
return
# Create the absolute path of the upload directory
abspath: str = os.path.join(os.path.abspath(config['UploadDir']), 'thumbnails/products/')
os.makedirs(abspath, exist_ok=True)
try:
# Parse the image data
image: Image = Image.open(BytesIO(avatar))
# Resize the image to 150x150
image.thumbnail((150, 150), Image.LANCZOS)
# Write the image to the file
with open(os.path.join(abspath, f'{product.id}.png'), 'wb') as f:
f.write(image)
image.save(os.path.join(abspath, f'{product.id}.png'), 'PNG')
except OSError:
return

View file

@ -2,6 +2,8 @@ from typing import Any, Dict, Optional, Union
import os
import magic
from PIL import Image
from io import BytesIO
from matemat.webserver import pagelet, RequestArguments, PageletResponse, RedirectResponse, TemplateResponse
from matemat.db import MatematDatabase
@ -130,13 +132,17 @@ def handle_change(args: RequestArguments, user: User, authuser: User, db: Matema
return
# Detect the MIME type
filemagic: magic.FileMagic = magic.detect_from_content(avatar)
# Currently, only image/png is supported, don't process any other formats
if filemagic.mime_type != 'image/png':
# TODO: Optionally convert to png
if not filemagic.mime_type.startswith('image/'):
return
# Create the absolute path of the upload directory
abspath: str = os.path.join(os.path.abspath(config['UploadDir']), 'thumbnails/users/')
os.makedirs(abspath, exist_ok=True)
try:
# Parse the image data
image: Image = Image.open(BytesIO(avatar))
# Resize the image to 150x150
image.thumbnail((150, 150), Image.LANCZOS)
# Write the image to the file
with open(os.path.join(abspath, f'{user.id}.png'), 'wb') as f:
f.write(avatar)
image.save(os.path.join(abspath, f'{user.id}.png'), 'PNG')
except OSError:
return

View file

@ -34,7 +34,7 @@
<img src="/upload/thumbnails/users/{{ authuser.id }}.png" alt="Avatar of {{ authuser.name }}" /><br/>
<label for="admin-avatar-avatar">Upload new file: </label>
<input id="admin-avatar-avatar" type="file" name="avatar" accept="image/png" /><br/>
<input id="admin-avatar-avatar" type="file" name="avatar" accept="image/*" /><br/>
<input type="submit" value="Save changes" />
</form>

View file

@ -50,7 +50,7 @@
<input id="admin-newproduct-price-non-member" type="number" min="0" name="pricenonmember" /><br/>
<label for="admin-newproduct-image">Image: </label>
<input id="admin-newproduct-image" type="file" accept="image/png" /><br/>
<input id="admin-newproduct-image" type="file" accept="image/*" /><br/>
<input type="submit" value="Create Product" />
</form>

View file

@ -26,7 +26,7 @@
<label for="modproduct-image">
<img height="150" src="/upload/thumbnails/products/{{ product.id }}.png" alt="Image of {{ product.name }}" />
</label><br/>
<input id="modproduct-image" type="file" name="image" accept="image/png" /><br/>
<input id="modproduct-image" type="file" name="image" accept="image/*" /><br/>
<input id="modproduct-productid" type="hidden" name="productid" value="{{ product.id }}" /><br/>

View file

@ -44,7 +44,7 @@
<label for="moduser-account-avatar">
<img height="150" src="/upload/thumbnails/users/{{ user.id }}.png" alt="Avatar of {{ user.name }}" />
</label><br/>
<input id="moduser-account-avatar" type="file" name="avatar" accept="image/png" /><br/>
<input id="moduser-account-avatar" type="file" name="avatar" accept="image/*" /><br/>
<input id="moduser-account-userid" type="hidden" name="userid" value="{{ user.id }}" /><br/>