Skip to content

Commit

Permalink
Use webp for thumbnails
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenwardy committed Nov 10, 2023
1 parent 5ce5684 commit 4578cb1
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 34 deletions.
8 changes: 4 additions & 4 deletions app/blueprints/packages/packages.py
Expand Up @@ -426,7 +426,7 @@ def move_to_state(package):
if not package.approved_at:
post_discord_webhook.delay(package.author.display_name,
"New package {}".format(package.get_url("packages.view", absolute=True)), False,
package.title, package.short_desc, package.get_thumb_url(2, True))
package.title, package.short_desc, package.get_thumb_url(2, True, "png"))
package.approved_at = datetime.datetime.now()

screenshots = PackageScreenshot.query.filter_by(package=package, approved=False).all()
Expand All @@ -437,7 +437,7 @@ def move_to_state(package):
elif state == PackageState.READY_FOR_REVIEW:
post_discord_webhook.delay(package.author.display_name,
"Ready for Review: {}".format(package.get_url("packages.view", absolute=True)), True,
package.title, package.short_desc, package.get_thumb_url(2, True))
package.title, package.short_desc, package.get_thumb_url(2, True, "png"))

add_notification(package.maintainers, current_user, NotificationType.PACKAGE_APPROVAL, msg, package.get_url("packages.view"), package)
severity = AuditSeverity.NORMAL if current_user in package.maintainers else AuditSeverity.EDITOR
Expand Down Expand Up @@ -480,7 +480,7 @@ def remove(package):

post_discord_webhook.delay(current_user.username,
f"Deleted package {package.author.username}/{package.name} with reason '{reason}'",
True, package.title, package.short_desc, package.get_thumb_url(2, True))
True, package.title, package.short_desc, package.get_thumb_url(2, True, "png"))

flash(gettext("Deleted package"), "success")

Expand All @@ -500,7 +500,7 @@ def remove(package):

post_discord_webhook.delay(current_user.username,
"Unapproved package with reason {}\n\n{}".format(reason, package.get_url("packages.view", absolute=True)), True,
package.title, package.short_desc, package.get_thumb_url(2, True))
package.title, package.short_desc, package.get_thumb_url(2, True, "png"))

flash(gettext("Unapproved package"), "success")

Expand Down
40 changes: 29 additions & 11 deletions app/blueprints/thumbnails/__init__.py
Expand Up @@ -14,15 +14,17 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.


from flask import abort, send_file, Blueprint, current_app
import os
from PIL import Image


bp = Blueprint("thumbnails", __name__)

import os
from PIL import Image

ALLOWED_RESOLUTIONS=[(100,67), (270,180), (350,233), (1100,520)]
ALLOWED_RESOLUTIONS = [(100, 67), (270, 180), (350, 233), (1100, 520)]
ALLOWED_EXTENSIONS = {"png", "webp"}


def mkdir(path):
assert path != "" and path is not None
Expand All @@ -34,10 +36,7 @@ def mkdir(path):


def resize_and_crop(img_path, modified_path, size):
try:
img = Image.open(img_path)
except FileNotFoundError:
abort(404)
img = Image.open(img_path)

# Get current and desired ratio for the images
img_ratio = img.size[0] / float(img.size[1])
Expand All @@ -64,21 +63,40 @@ def resize_and_crop(img_path, modified_path, size):
img.save(modified_path)


def find_source_file(img):
upload_dir = current_app.config["UPLOAD_DIR"]
source_filepath = os.path.join(upload_dir, img)
if os.path.isfile(source_filepath):
return source_filepath

period = source_filepath.rfind(".")
start = source_filepath[:period]
ext = source_filepath[period + 1:]
if ext not in ALLOWED_EXTENSIONS:
abort(404)

for other_ext in ALLOWED_EXTENSIONS:
other_path = f"{start}.{other_ext}"
if ext != other_ext and os.path.isfile(other_path):
return other_path

abort(404)


@bp.route("/thumbnails/<int:level>/<img>")
def make_thumbnail(img, level):
if level > len(ALLOWED_RESOLUTIONS) or level <= 0:
abort(403)
w, h = ALLOWED_RESOLUTIONS[level - 1]

upload_dir = current_app.config["UPLOAD_DIR"]
thumbnail_dir = current_app.config["THUMBNAIL_DIR"]
mkdir(thumbnail_dir)

output_dir = os.path.join(thumbnail_dir, str(level))
mkdir(output_dir)

cache_filepath = os.path.join(output_dir, img)
source_filepath = os.path.join(upload_dir, img)
cache_filepath = os.path.join(output_dir, img)
source_filepath = find_source_file(img)

resize_and_crop(source_filepath, cache_filepath, (w, h))
return send_file(cache_filepath)
24 changes: 14 additions & 10 deletions app/models/packages.py
Expand Up @@ -528,7 +528,7 @@ def as_key_dict(self):
}

def as_short_dict(self, base_url, version=None, release_id=None, no_load=False):
tnurl = self.get_thumb_url(1)
tnurl = self.get_thumb_url(1, format="png")

if release_id is None and no_load == False:
release = self.get_download_release(version=version)
Expand All @@ -555,7 +555,7 @@ def as_short_dict(self, base_url, version=None, release_id=None, no_load=False):
return ret

def as_dict(self, base_url, version=None):
tnurl = self.get_thumb_url(1)
tnurl = self.get_thumb_url(1, format="png")
release = self.get_download_release(version=version)
return {
"author": self.author.username,
Expand Down Expand Up @@ -603,21 +603,21 @@ def as_dict(self, base_url, version=None):
]
}

def get_thumb_or_placeholder(self, level=2):
return self.get_thumb_url(level) or "/static/placeholder.png"
def get_thumb_or_placeholder(self, level=2, format="webp"):
return self.get_thumb_url(level, False, format) or "/static/placeholder.png"

def get_thumb_url(self, level=2, abs=False):
def get_thumb_url(self, level=2, abs=False, format="webp"):
screenshot = self.main_screenshot
url = screenshot.get_thumb_url(level) if screenshot is not None else None
url = screenshot.get_thumb_url(level, format) if screenshot is not None else None
if abs:
from app.utils import abs_url
return abs_url(url)
else:
return url

def get_cover_image_url(self):
def get_cover_image_url(self, format="webp"):
screenshot = self.cover_image or self.main_screenshot
return screenshot and screenshot.get_thumb_url(4)
return screenshot and screenshot.get_thumb_url(4, format)

def get_url(self, endpoint, absolute=False, **kwargs):
if absolute:
Expand Down Expand Up @@ -1101,8 +1101,12 @@ def get_delete_url(self):
name=self.package.name,
id=self.id)

def get_thumb_url(self, level=2):
return self.url.replace("/uploads/", "/thumbnails/{:d}/".format(level))
def get_thumb_url(self, level=2, format="webp"):
url = self.url.replace("/uploads/", "/thumbnails/{:d}/".format(level))
if format is not None:
start = url[:url.rfind(".")]
url = f"{start}.{format}"
return url

def as_dict(self, base_url=""):
return {
Expand Down
2 changes: 1 addition & 1 deletion app/templates/collections/view.html
Expand Up @@ -9,7 +9,7 @@
{%- endblock %}

{% block headextra %}
{% set thumb_url = collection.packages and collection.packages[0].get_thumb_url(3, True) %}
{% set thumb_url = collection.packages and collection.packages[0].get_thumb_url(3, True, "png") %}
{% if thumb_url -%}
<meta name="og:image" content="{{ thumb_url }}">
{%- endif %}
Expand Down
2 changes: 1 addition & 1 deletion app/templates/macros/packagegridtile.html
@@ -1,6 +1,6 @@
{% macro render_pkgtile(package, show_author) -%}
<li class="packagetile flex-fill"><a href="{{ package.get_url('packages.view') }}">
<img src="{{ package.get_thumb_or_placeholder(2) }}" loading="lazy">
<img src="{{ package.get_thumb_or_placeholder() }}" loading="lazy">
<div class="packagegridscrub"></div>
<div class="packagegridinfo">
<h3>
Expand Down
4 changes: 2 additions & 2 deletions app/templates/packages/game_hub.html
Expand Up @@ -10,8 +10,8 @@
{% endblock %}

{% block headextra %}
{% if package.get_thumb_url(3, True) %}
<meta name="og:image" content="{{ package.get_thumb_url(3, True) }}"/>
{% if package.get_thumb_url(3, True, "png") %}
<meta name="og:image" content="{{ package.get_thumb_url(3, True, "png") }}"/>
{% endif %}
{% endblock %}

Expand Down
4 changes: 2 additions & 2 deletions app/templates/packages/gone.html
Expand Up @@ -9,8 +9,8 @@
{% endblock %}

{% block headextra %}
{% if package.get_thumb_url(3, True) -%}
<meta name="og:image" content="{{ package.get_thumb_url(3, True) }}"/>
{% if package.get_thumb_url(3, True, "png") -%}
<meta name="og:image" content="{{ package.get_thumb_url(3, True, "png") }}"/>
{%- endif %}
{% endblock %}

Expand Down
6 changes: 3 additions & 3 deletions app/templates/packages/view.html
Expand Up @@ -12,8 +12,8 @@
{% endblock %}

{% block headextra %}
{% if package.get_thumb_url(3, True) -%}
<meta name="og:image" content="{{ package.get_thumb_url(3, True) }}"/>
{% if package.get_thumb_url(3, True, "png") -%}
<meta name="og:image" content="{{ package.get_thumb_url(3, True, "png") }}"/>
{%- endif %}
{% endblock %}

Expand Down Expand Up @@ -261,7 +261,7 @@ <h1 class="display-3">
{% if ss.approved or package.check_perm(current_user, "ADD_SCREENSHOTS") %}
<div class="carousel-item {% if loop.index == 1 %}active{% endif %}">
<a href="{{ ss.url }}" target="_blank">
<img class="img-size w-100" src="{{ ss.url }}" alt="{{ ss.title }}" title="{{ ss.title }}" />
<img class="img-size w-100" loading="lazy" src="{{ ss.url }}" alt="{{ ss.title }}" title="{{ ss.title }}" />
</a>
</div>
{% endif %}
Expand Down

0 comments on commit 4578cb1

Please sign in to comment.