Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove thumbnail cropping, and default thumbnail aspect ratio to 16:9 #1369

Merged
merged 8 commits into from
May 21, 2019
1 change: 1 addition & 0 deletions .idea/studio.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -271,14 +271,12 @@

padding: 0 20px 40px;
.channel-thumbnail {
width: @channel-thumbnail-size;
width: @channel-thumbnail-width;
height: @channel-thumbnail-height;
margin-top: 35px;
/deep/ .image_dropzone {
width: @channel-thumbnail-size;
img {
width: @channel-thumbnail-size;
height: @channel-thumbnail-size;
}
width: @channel-thumbnail-width;
height: @channel-thumbnail-height;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
@click="openChannel"
>
<div class="profile">
<img class="channel-pic" :alt="channel.name" :src="picture">
<div class="channel-pic">
<img :alt="channel.name" :src="picture">
</div>
</div>
<div class="channel-information">
<div class="channel-options-wrapper">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@
grid-template-columns: 1fr 3fr;
padding: 0 20px 40px;
img {
width: 130px;
height: 130px;
width: 160px;
height: 90px;
margin-top: 35px;
border: 2px solid @gray-500;
object-fit: cover;
object-fit: contain;
}
.channel-section {
padding-left: 20px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@
.section {
padding: 0;
img {
width: 100px;
height: 100px;
object-fit: cover;
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
}
.title {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@
{{#each details.original_channels}}
<li class="original_channel row">
<a href="/channels/{{id}}/view" target="_blank">
<div class="col-xs-2"><img src="{{#if thumbnail}}{{thumbnail}}{{else}}{{/if}}"></div>
<div class="col-xs-10"><span data-toggle="tooltip" data-placement="top" data-container="body" title="{{formatMessage (intlGet 'messages.resource_count') count=count}}">{{name}}</span></div>
<div class="col-xs-4"><img src="{{#if thumbnail}}{{thumbnail}}{{else}}{{/if}}"></div>
<div class="col-xs-8"><span data-toggle="tooltip" data-placement="top" data-container="body" title="{{formatMessage (intlGet 'messages.resource_count') count=count}}">{{name}}</span></div>
</a>
</li>
{{/each}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ require('croppie/croppie.css');
var dialog = require('edit_channel/utils/dialog');
const Constants = require('edit_channel/constants/index');

const CHANNEL_ASPECT_RATIO = { width: 130, height: 130 };
const CHANNEL_CROP_BOUNDARY = {
width: CHANNEL_ASPECT_RATIO.width + 20,
height: CHANNEL_ASPECT_RATIO.height + 20,
};
const THUMBNAIL_ASPECT_RATIO = { width: 160, height: 90 };
const THUMBNAIL_CROP_BOUNDARY = {
width: THUMBNAIL_ASPECT_RATIO.width + 10,
Expand Down Expand Up @@ -81,8 +76,8 @@ export const ThumbnailUploadView = BaseViews.BaseView.extend({
this.upload_url = options.upload_url;
this.default_url = options.default_url;
this.allow_edit = options.allow_edit;
this.aspect_ratio = options.is_channel ? CHANNEL_ASPECT_RATIO : THUMBNAIL_ASPECT_RATIO;
this.boundary = options.is_channel ? CHANNEL_CROP_BOUNDARY : THUMBNAIL_CROP_BOUNDARY;
this.aspect_ratio = THUMBNAIL_ASPECT_RATIO;
this.boundary = THUMBNAIL_CROP_BOUNDARY;
this.cropping = false;
this.render();
this.dropzone = null;
Expand Down Expand Up @@ -194,6 +189,7 @@ export const ThumbnailUploadView = BaseViews.BaseView.extend({
this.croppie = new Croppie(this.$(selector).get(0), {
boundary: this.boundary,
viewport: this.aspect_ratio,
enforceBoundary: false,
showZoomer: false,
customClass: 'crop-img',
});
Expand Down
17 changes: 12 additions & 5 deletions contentcuration/contentcuration/static/less/channel_list.less
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
@channel-item-min-width: 400px;
@channel-container-height: 250px;
@channel-profile-width: 150px;
@channel-thumbnail-size: 150px;
@channel-thumbnail-width: 170px;
@channel-thumbnail-height: 100px;

// nested flexbox settings to ensure that the channels list view is vertically responsive.
body {
Expand Down Expand Up @@ -115,10 +116,16 @@ body {
.profile {
margin: 5px 15px 5px 5px;
text-align: left;
img {
width: @channel-thumbnail-size;
height: @channel-thumbnail-size;
object-fit: cover;
.channel-pic {
width: @channel-thumbnail-width;
height: @channel-thumbnail-height;
text-align: center;
background-color: #ffffff;
img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
}
span {
font-size: 65pt;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,23 @@
}
.channel_section {
display: inline-block;
width: 70%;
width: 65%;
margin-left: 5px;
}
.image_dropzone {
width: 120px;
}
.new_channel_pic {
width: 150px;
height: 100%;
width: 170px;
height: 100px;
margin: 5px 15px 5px 5px;
.image_dropzone {
width: auto;
}
img {
width: 150px;
height: 150px;
object-fit: cover;
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
}
hr {
Expand Down
1 change: 0 additions & 1 deletion contentcuration/contentcuration/static/less/details.less
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@
}
}
img {
width: 32px;
height: 32px;
border: 1px solid @blue-200;
object-fit: cover;
Expand Down
2 changes: 1 addition & 1 deletion contentcuration/contentcuration/static/less/queue.less
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@
}
.content-item-thumbnail {
display: inline-block;
width: 30px;
height: 30px;
margin-top: -3px; // HACK
margin-right: 10px;
margin-left: 6px;
Expand Down
33 changes: 13 additions & 20 deletions contentcuration/contentcuration/utils/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import shutil
import tempfile
import zipfile
from fractions import Fraction
from multiprocessing.dummy import Pool

import requests
Expand All @@ -32,7 +31,7 @@
from contentcuration.models import generate_object_storage_name

ImageFile.LOAD_TRUNCATED_IMAGES = True
THUMBNAIL_DIMENSION = 400
THUMBNAIL_WIDTH = 400


def create_file_from_contents(contents, ext=None, node=None, preset_id=None, uploaded_by=None):
Expand Down Expand Up @@ -233,21 +232,24 @@ def generate_thumbnail_from_channel(item, dimension=200):
return get_thumbnail_encoding(item.thumbnail, dimension=dimension)


def get_thumbnail_encoding(filename, dimension=THUMBNAIL_DIMENSION):
def get_thumbnail_encoding(filename, dimension=THUMBNAIL_WIDTH):
"""
Generates a base64 encoding for a thumbnail
Args:
filename (str): thumbnail to generate encoding from (must be in storage already)
dimension (int): how big resized image should be
dimension (int, optional): desired width of thumbnail. Defaults to 400.
Returns base64 encoding of resized thumbnail
"""

if filename.startswith("data:image"):
return filename

checksum, ext = os.path.splitext(filename.split("?")[0])
inbuffer = StringIO.StringIO()
outbuffer = StringIO.StringIO()

# make sure the aspect ratio between width and height is 16:9
thumbnail_size = [dimension, round(dimension / 1.77)]
try:
if not filename.startswith(settings.STATIC_ROOT):
filename = generate_object_storage_name(checksum, filename)
Expand All @@ -260,22 +262,13 @@ def get_thumbnail_encoding(filename, dimension=THUMBNAIL_DIMENSION):

with Image.open(inbuffer) as image:
image_format = image.format
width, height = image.size
dimension = min([dimension, width, height])
size = [dimension, dimension]
ratio = Fraction(*size)

# Crop image the aspect ratio is different
if width > ratio * height:
x, y = (width - ratio * height) // 2, 0
else:
x, y = 0, (height - width / ratio) // 2

image = image.crop((x, y, width - x, height - y))
if image.size > size:
image.thumbnail(size, Image.ANTIALIAS)
else:
image.thumbnail((dimension, dimension), Image.ANTIALIAS)

# Note: Image.thumbnail ensures that the image will fit in the
# specified thumbnail size, but it retains the original image's
# aspect ratio. So a square image will remain square rather
# than being distorted to a 16:9 aspect ratio. This removes
# the need to make any changes like cropping the image.
image.thumbnail(thumbnail_size, Image.ANTIALIAS)

image.save(outbuffer, image_format)
return "data:image/{};base64,{}".format(ext[1:], base64.b64encode(outbuffer.getvalue()))
Expand Down