Thumbnails for images and videos #87
@ -104,8 +104,6 @@ ABUSE_TYPE = Choices(
|
||||
# **N.B.**: thumbnail sizes are not intended to be changed on the fly:
|
||||
# thumbnails of existing images must exist in MEDIA_ROOT before
|
||||
# the code expecting thumbnails of new dimensions can be deployed!
|
||||
THUMBNAIL_SIZE_L = (1920, 1080)
|
||||
THUMBNAIL_SIZE_S = (640, 360)
|
||||
THUMBNAIL_SIZES = {'l': THUMBNAIL_SIZE_L, 's': THUMBNAIL_SIZE_S}
|
||||
THUMBNAIL_SIZES = {'1080p': [1920, 1080], '360p': [640, 360]}
|
||||
THUMBNAIL_FORMAT = 'PNG'
|
||||
THUMBNAIL_QUALITY = 83
|
||||
|
@ -1,13 +1,13 @@
|
||||
{% load common filters %}
|
||||
{% with latest=extension.latest_version thumbnail_s_url=extension.previews.listed.first.thumbnail_s_url %}
|
||||
{% with latest=extension.latest_version thumbnail_360p_url=extension.previews.listed.first.thumbnail_360p_url %}
|
||||
|
||||
<div class="ext-card {% if blur %}is-background-blur{% endif %}">
|
||||
{% if blur %}
|
||||
<div class="ext-card-thumbnail-blur" style="background-image: url({{ thumbnail_s_url }});"></div>
|
||||
<div class="ext-card-thumbnail-blur" style="background-image: url({{ thumbnail_360p_url }});"></div>
|
||||
{% endif %}
|
||||
|
||||
<a class="ext-card-thumbnail" href="{{ extension.get_absolute_url }}">
|
||||
<div class="ext-card-thumbnail-img" style="background-image: url({{ thumbnail_s_url }});" title="{{ extension.name }}"></div>
|
||||
<div class="ext-card-thumbnail-img" style="background-image: url({{ thumbnail_360p_url }});" title="{{ extension.name }}"></div>
|
||||
</a>
|
||||
|
||||
<div class="ext-card-body">
|
||||
|
@ -3,15 +3,15 @@
|
||||
{% if previews %}
|
||||
<div class="galleria-items{% if previews.count > 5 %} is-many{% endif %}{% if previews.count == 1 %} is-single{% endif %}" id="galleria-items">
|
||||
{% for preview in previews %}
|
||||
{% with thumbnail_l_url=preview.thumbnail_l_url %}
|
||||
{% with thumbnail_1080p_url=preview.thumbnail_1080p_url %}
|
||||
<a
|
||||
class="galleria-item js-galleria-item-preview galleria-item-type-{{ preview.content_type|slugify|slice:5 }}{% if forloop.first %} is-active{% endif %}"
|
||||
href="{{ thumbnail_l_url }}"
|
||||
href="{{ thumbnail_1080p_url }}"
|
||||
{% if 'video' in preview.content_type %}data-galleria-video-url="{{ preview.source.url }}"{% endif %}
|
||||
data-galleria-content-type="{{ preview.content_type }}"
|
||||
data-galleria-index="{{ forloop.counter }}">
|
||||
|
||||
<img src="{{ thumbnail_l_url }}" alt="{{ preview.preview.caption }}">
|
||||
<img src="{{ thumbnail_1080p_url }}" alt="{{ preview.preview.caption }}">
|
||||
</a>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
|
@ -7,7 +7,6 @@ import background_task.admin
|
||||
import background_task.models
|
||||
|
||||
from .models import File, FileValidation
|
||||
from constants.base import THUMBNAIL_SIZE_L
|
||||
import files.signals
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -47,11 +46,7 @@ class FileAdmin(admin.ModelAdmin):
|
||||
if not obj or not (obj.is_image or obj.is_video):
|
||||
return ''
|
||||
try:
|
||||
context = {
|
||||
'file': obj,
|
||||
'MEDIA_URL': settings.MEDIA_URL,
|
||||
'THUMBNAIL_SIZE_L': THUMBNAIL_SIZE_L,
|
||||
}
|
||||
context = {'file': obj, 'MEDIA_URL': settings.MEDIA_URL}
|
||||
return render_to_string('files/admin/thumbnails.html', context)
|
||||
except Exception:
|
||||
# Make sure any exception happening here is always logged
|
||||
|
@ -213,12 +213,12 @@ class File(CreatedModifiedMixin, TrackChangesMixin, models.Model):
|
||||
return self.source.url
|
||||
|
||||
@property
|
||||
def thumbnail_l_url(self) -> str:
|
||||
return self.get_thumbnail_of_size('l')
|
||||
def thumbnail_1080p_url(self) -> str:
|
||||
return self.get_thumbnail_of_size('1080p')
|
||||
|
||||
@property
|
||||
def thumbnail_s_url(self) -> str:
|
||||
return self.get_thumbnail_of_size('s')
|
||||
def thumbnail_360p_url(self) -> str:
|
||||
return self.get_thumbnail_of_size('360p')
|
||||
|
||||
|
||||
class FileValidation(CreatedModifiedMixin, TrackChangesMixin, models.Model):
|
||||
|
@ -56,7 +56,7 @@ def make_thumbnails(file_id: int) -> None:
|
||||
thumbnails = files.utils.make_thumbnails(source_path, file.hash)
|
||||
|
||||
if not thumbnail_field.name:
|
||||
thumbnail_field.name = thumbnails['l']['path']
|
||||
thumbnail_field.name = thumbnails['1080p']['path']
|
||||
|
||||
update_fields = set()
|
||||
if thumbnail_field.name != unchanged_thumbnail:
|
||||
|
@ -5,12 +5,4 @@
|
||||
<img height="{% widthratio thumb.size.1 10 1 %}" src="{{ MEDIA_URL }}{{ thumb.path }}" title={{ thumb.path }}>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{# alert about unexpected size of the default thumbnail, which might happen if source file was smaller than 1080p #}
|
||||
{# TODO: do we want to make minimum resolution a validation criteria during upload instead? #}
|
||||
{% if file.thumbnail.width != THUMBNAIL_SIZE_L.0 or file.thumbnail.height != THUMBNAIL_SIZE_L.1 %}
|
||||
<p>
|
||||
<b class="icon-alert">⚠</b> Expected {{ THUMBNAIL_SIZE_L.0 }}x{{ THUMBNAIL_SIZE_L.1 }}px,
|
||||
got {{ file.thumbnail.width }}x{{ file.thumbnail.height }}px: resolution of the source file might be too low?
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -53,8 +53,8 @@ class TasksTest(TestCase):
|
||||
file.metadata,
|
||||
{
|
||||
'thumbnails': {
|
||||
'l': {'path': 'thumbnails/fo/foobar_1920x1080.png', 'size': [1920, 1080]},
|
||||
's': {'path': 'thumbnails/fo/foobar_640x360.png', 'size': [640, 360]},
|
||||
'1080p': {'path': 'thumbnails/fo/foobar_1920x1080.png', 'size': [1920, 1080]},
|
||||
'360p': {'path': 'thumbnails/fo/foobar_640x360.png', 'size': [640, 360]},
|
||||
},
|
||||
},
|
||||
)
|
||||
@ -86,8 +86,8 @@ class TasksTest(TestCase):
|
||||
file.metadata,
|
||||
{
|
||||
'thumbnails': {
|
||||
'l': {'path': 'thumbnails/de/deadbeef_1920x1080.png', 'size': [1920, 1080]},
|
||||
's': {'path': 'thumbnails/de/deadbeef_640x360.png', 'size': [640, 360]},
|
||||
'1080p': {'path': 'thumbnails/de/deadbeef_1920x1080.png', 'size': [1920, 1080]},
|
||||
'360p': {'path': 'thumbnails/de/deadbeef_640x360.png', 'size': [640, 360]},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
@ -126,8 +126,8 @@ class UtilsTest(TestCase):
|
||||
def test_make_thumbnails(self, mock_resize_image):
|
||||
self.assertEqual(
|
||||
{
|
||||
'l': {'path': 'thumbnails/fo/foobar_1920x1080.png', 'size': (1920, 1080)},
|
||||
's': {'path': 'thumbnails/fo/foobar_640x360.png', 'size': (640, 360)},
|
||||
'1080p': {'path': 'thumbnails/fo/foobar_1920x1080.png', 'size': (1920, 1080)},
|
||||
'360p': {'path': 'thumbnails/fo/foobar_640x360.png', 'size': (640, 360)},
|
||||
},
|
||||
make_thumbnails(TEST_FILES_DIR / 'test_preview_image_0001.png', 'foobar'),
|
||||
)
|
||||
|
@ -76,10 +76,10 @@
|
||||
<h3>Previews Pending Approval</h3>
|
||||
<div class="row">
|
||||
{% for preview in pending_previews %}
|
||||
{% with thumbnail_l_url=preview.file.thumbnail_l_url %}
|
||||
{% with thumbnail_1080p_url=preview.file.thumbnail_1080p_url %}
|
||||
<div class="col-md-3">
|
||||
<a href="{{ preview.file.source.url }}" class="d-block mb-2" title="{{ preview.caption }}" target="_blank">
|
||||
<img class="img-fluid rounded" src="{{ thumbnail_l_url }}" alt="{{ preview.caption }}">
|
||||
<img class="img-fluid rounded" src="{{ thumbnail_1080p_url }}" alt="{{ preview.caption }}">
|
||||
</a>
|
||||
{% include "common/components/status.html" with object=preview.file class="d-block" %}
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user