scale thumbnails properly
This commit is contained in:
parent
60a7305fb7
commit
899803467e
Binary file not shown.
Before Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
|
@ -429,7 +429,11 @@ class Media(models.Model):
|
||||||
def loaded_metadata(self):
|
def loaded_metadata(self):
|
||||||
if self.pk in _metadata_cache:
|
if self.pk in _metadata_cache:
|
||||||
return _metadata_cache[self.pk]
|
return _metadata_cache[self.pk]
|
||||||
_metadata_cache[self.pk] = json.loads(self.metadata)
|
try:
|
||||||
|
unpacked_data = json.loads(self.metadata)
|
||||||
|
except Exception:
|
||||||
|
return {}
|
||||||
|
_metadata_cache[self.pk] = unpacked_data
|
||||||
return _metadata_cache[self.pk]
|
return _metadata_cache[self.pk]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -460,9 +464,9 @@ class Media(models.Model):
|
||||||
dateobj = upload_date if upload_date else self.created
|
dateobj = upload_date if upload_date else self.created
|
||||||
datestr = dateobj.strftime('%Y-%m-%d')
|
datestr = dateobj.strftime('%Y-%m-%d')
|
||||||
source_name = slugify(self.source.name)
|
source_name = slugify(self.source.name)
|
||||||
title = slugify(self.title.replace('&', 'and').replace('+', 'and'))
|
name = slugify(self.name.replace('&', 'and').replace('+', 'and'))
|
||||||
ext = self.source.extension
|
ext = self.source.extension
|
||||||
fn = f'{datestr}_{source_name}_{title}'[:100]
|
fn = f'{datestr}_{source_name}_{name}'[:100]
|
||||||
return f'{fn}.{ext}'
|
return f'{fn}.{ext}'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -15,7 +15,7 @@ from background_task import background
|
||||||
from background_task.models import Task
|
from background_task.models import Task
|
||||||
from common.logger import log
|
from common.logger import log
|
||||||
from .models import Source, Media
|
from .models import Source, Media
|
||||||
from .utils import get_remote_image
|
from .utils import get_remote_image, resize_image_to_height
|
||||||
|
|
||||||
|
|
||||||
def delete_index_source_task(source_id):
|
def delete_index_source_task(source_id):
|
||||||
|
@ -57,9 +57,6 @@ def index_source_task(source_id):
|
||||||
media.metadata = json.dumps(video)
|
media.metadata = json.dumps(video)
|
||||||
upload_date = media.upload_date
|
upload_date = media.upload_date
|
||||||
if upload_date:
|
if upload_date:
|
||||||
if timezone.is_aware(upload_date):
|
|
||||||
media.published = upload_date
|
|
||||||
else:
|
|
||||||
media.published = timezone.make_aware(upload_date)
|
media.published = timezone.make_aware(upload_date)
|
||||||
media.save()
|
media.save()
|
||||||
log.info(f'Indexed media: {source} / {media}')
|
log.info(f'Indexed media: {source} / {media}')
|
||||||
|
@ -76,13 +73,12 @@ def download_media_thumbnail(media_id, url):
|
||||||
except Media.DoesNotExist:
|
except Media.DoesNotExist:
|
||||||
# Task triggered but the media no longer exists, ignore task
|
# Task triggered but the media no longer exists, ignore task
|
||||||
return
|
return
|
||||||
|
width = getattr(settings, 'MEDIA_THUMBNAIL_WIDTH', 430)
|
||||||
|
height = getattr(settings, 'MEDIA_THUMBNAIL_HEIGHT', 240)
|
||||||
i = get_remote_image(url)
|
i = get_remote_image(url)
|
||||||
ratio = i.width / i.height
|
|
||||||
new_height = getattr(settings, 'MEDIA_THUMBNAIL_HEIGHT', 240)
|
|
||||||
new_width = math.ceil(new_height * ratio)
|
|
||||||
log.info(f'Resizing {i.width}x{i.height} thumbnail to '
|
log.info(f'Resizing {i.width}x{i.height} thumbnail to '
|
||||||
f'{new_width}x{new_height}: {url}')
|
f'{width}x{height}: {url}')
|
||||||
i = i.resize((new_width, new_height), Image.ANTIALIAS)
|
i = resize_image_to_height(i, width, height)
|
||||||
image_file = BytesIO()
|
image_file = BytesIO()
|
||||||
i.save(image_file, 'JPEG', quality=80, optimize=True, progressive=True)
|
i.save(image_file, 'JPEG', quality=80, optimize=True, progressive=True)
|
||||||
image_file.seek(0)
|
image_file.seek(0)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<a href="{% url 'sync:media-item' pk=m.pk %}" class="collection-item">
|
<a href="{% url 'sync:media-item' pk=m.pk %}" class="collection-item">
|
||||||
<div class="card mediacard">
|
<div class="card mediacard">
|
||||||
<div class="card-image">
|
<div class="card-image">
|
||||||
<img src="{% if m.thumb %}{% url 'sync:media-thumb' pk=m.pk %}{% else %}{% static 'images/nothumb.jpg' %} {% endif %}">
|
<img src="{% if m.thumb %}{% url 'sync:media-thumb' pk=m.pk %}{% else %}{% static 'images/nothumb.png' %}{% endif %}">
|
||||||
<span class="card-title truncate">{{ m.source }}<br>
|
<span class="card-title truncate">{{ m.source }}<br>
|
||||||
<span>{{ m.name }}</span><br>
|
<span>{{ m.name }}</span><br>
|
||||||
<span>{{ m.published|date:'Y-m-d' }}</span>
|
<span>{{ m.published|date:'Y-m-d' }}</span>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import math
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import requests
|
import requests
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
@ -59,6 +60,27 @@ def get_remote_image(url):
|
||||||
return Image.open(r.raw)
|
return Image.open(r.raw)
|
||||||
|
|
||||||
|
|
||||||
|
def resize_image_to_height(image, width, height):
|
||||||
|
'''
|
||||||
|
Resizes an image to 'height' pixels keeping the ratio. If the resulting width
|
||||||
|
is larger than 'width' then crop it. If the resulting width is smaller than
|
||||||
|
'width' then stretch it.
|
||||||
|
'''
|
||||||
|
ratio = image.width / image.height
|
||||||
|
scaled_width = math.ceil(height * ratio)
|
||||||
|
if scaled_width < width:
|
||||||
|
# Width too small, stretch it
|
||||||
|
scaled_width = width
|
||||||
|
image = image.resize((scaled_width, height), Image.ANTIALIAS)
|
||||||
|
if scaled_width > width:
|
||||||
|
# Width too large, crop it
|
||||||
|
delta = scaled_width - width
|
||||||
|
left, upper = (delta / 2), 0
|
||||||
|
right, lower = (left + width), height
|
||||||
|
image = image.crop((left, upper, right, lower))
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
def file_is_editable(filepath):
|
def file_is_editable(filepath):
|
||||||
'''
|
'''
|
||||||
Checks that a file exists and the file is in an allowed predefined tuple of
|
Checks that a file exists and the file is in an allowed predefined tuple of
|
||||||
|
|
|
@ -127,6 +127,7 @@ MEDIA_PER_PAGE = 36
|
||||||
INDEX_SOURCE_EVERY = 21600 # Seconds between indexing sources, 21600 = every 6 hours
|
INDEX_SOURCE_EVERY = 21600 # Seconds between indexing sources, 21600 = every 6 hours
|
||||||
|
|
||||||
|
|
||||||
|
MEDIA_THUMBNAIL_WIDTH = 430 # Width in pixels to resize thumbnails to
|
||||||
MEDIA_THUMBNAIL_HEIGHT = 240 # Height in pixels to resize thumbnails to
|
MEDIA_THUMBNAIL_HEIGHT = 240 # Height in pixels to resize thumbnails to
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue