Example #1
0
    def get_object(self, request, channel_slug=None):
        self._root_url = get_base_url(request)
        if channel_slug:
            self.channel = get_object_or_404(Channel,
                                             slug__iexact=channel_slug)
        else:
            self.channel = Channel.objects.get(
                slug=settings.DEFAULT_CHANNEL_SLUG)
        if self.channel.cover_art:
            self.itunes_lg_url = thumbnail(self.channel.cover_art,
                                           '1400x1400').url
            self.itunes_sm_url = thumbnail(self.channel.cover_art,
                                           '144x144').url
            if self.itunes_lg_url.startswith('//'):
                # e.g. //cdn.example.com/media/cache/file.png
                protocol = self._root_url.split('//')[0]
                self.itunes_lg_url = protocol + self.itunes_lg_url
                self.itunes_sm_url = protocol + self.itunes_sm_url
            elif '://' not in self.itunes_lg_url:
                self.itunes_lg_url = self._root_url + self.itunes_lg_url
                self.itunes_sm_url = self._root_url + self.itunes_sm_url
        else:
            # Use the default ones
            self.itunes_sm_url = get_abs_static(
                'main/img/podcast-cover-144x144.png', request)
            self.itunes_lg_url = get_abs_static(
                'main/img/podcast-cover-1400x1400.png', request)

        super(ITunesFeed, self).get_object(request)
Example #2
0
def event_processing_timenails(request, slug):
    event = get_object_or_404(Event, slug=slug)
    if not event.duration:
        return {'pictures': []}
    form = forms.ProcessingTimenailsForm(request.GET)
    if not form.is_valid():
        return http.HttpResponseBadRequest(form.errors)
    percentage = min(100.0, form.cleaned_data['percent'] or 100.0)
    max_ = form.cleaned_data['max']
    point = event.duration * percentage / 100.0
    pictures = Picture.objects.filter(
        event=event,
        timestamp__isnull=False,
        timestamp__lte=point,
    )
    pictures_ = []
    for picture in pictures.order_by('-timestamp')[:max_]:
        # NOTE! This code is the same as used
        # in then EventChaptersThumbnailsView.get view.
        thumb = thumbnail(
            picture.file, '160x90', crop='center'
        )
        pictures_.append({
            'id': picture.id,
            'timestamp': picture.timestamp,
            'thumbnail': {
                'url': thumb.url,
                'width': thumb.width,
                'height': thumb.height,
            },
        })
    pictures_.reverse()
    return {'pictures': pictures_}
Example #3
0
 def event_to_dict(event):
     picture_id = event.picture.id if event.picture else None
     data = {
         'event_id': event.id,
         'title': event.title,
         'description': event.description,
         'short_description': event.short_description,
         'channels': [x.pk for x in event.channels.all()],
         'tags': [x.pk for x in event.tags.all()],
         'call_info': event.call_info,
         'additional_links': event.additional_links,
         'recruitmentmessage': None,
         'picture': picture_id
     }
     if event.recruitmentmessage_id:
         data['recruitmentmessage'] = event.recruitmentmessage_id
     if event.placeholder_img:
         data['placeholder_img'] = event.placeholder_img.url
         if event.picture:
             file = event.picture.file
         else:
             file = event.placeholder_img
         data['thumbnail_url'] = (
             thumbnail(
                 file,
                 '121x68',
                 crop='center'
             ).url
         )
     return data
Example #4
0
 def event_to_dict(event):
     picture_id = event.picture.id if event.picture else None
     data = {
         'event_id': event.id,
         'title': event.title,
         'description': event.description,
         'short_description': event.short_description,
         'channels': [x.pk for x in event.channels.all()],
         'tags': [x.pk for x in event.tags.all()],
         'call_info': event.call_info,
         'additional_links': event.additional_links,
         'picture': picture_id
     }
     if event.placeholder_img:
         data['placeholder_img'] = event.placeholder_img.url
         if event.picture:
             file = event.picture.file
         else:
             file = event.placeholder_img
         data['thumbnail_url'] = (
             thumbnail(
                 file,
                 '121x68',
                 crop='center'
             ).url
         )
     return data
Example #5
0
def event_processing_timenails(request, slug):
    event = get_object_or_404(Event, slug=slug)
    if not event.duration:
        return {'pictures': []}
    form = forms.ProcessingTimenailsForm(request.GET)
    if not form.is_valid():
        return http.HttpResponseBadRequest(form.errors)
    percentage = min(100.0, form.cleaned_data['percent'] or 100.0)
    max_ = form.cleaned_data['max']
    point = event.duration * percentage / 100.0
    pictures = Picture.objects.filter(
        event=event,
        timestamp__isnull=False,
        timestamp__lte=point,
    )
    pictures_ = []
    for picture in pictures.order_by('-timestamp')[:max_]:
        # NOTE! This code is the same as used
        # in then EventChaptersThumbnailsView.get view.
        thumb = thumbnail(picture.file, '160x90', crop='center')
        pictures_.append({
            'id': picture.id,
            'timestamp': picture.timestamp,
            'thumbnail': {
                'url': thumb.url,
                'width': thumb.width,
                'height': thumb.height,
            },
        })
    pictures_.reverse()
    return {'pictures': pictures_}
Example #6
0
 def render(self, name, value, attrs):
     pictures = []
     qs = Picture.objects.all()
     if self.event:
         qs = qs.exclude(timestamp__isnull=False)
         qs = qs.filter(Q(event__isnull=True) | Q(event=self.event))
         # If the current event does use an inactive picture,
         # let it still be a choice.
         if self.event.picture_id:
             qs = qs.filter(Q(is_active=True) | Q(id=self.event.picture_id))
         else:
             qs = qs.filter(is_active=True)
     else:
         qs = qs.filter(
             event__isnull=True,
             is_active=True,
         )
     for pic in qs.order_by('event', '-created'):
         thumb = thumbnail(pic.file, '160x90', crop='center')
         pictures.append({
             'thumb': {
                 'url': thumb.url,
                 'width': thumb.width,
                 'height': thumb.height
             },
             'notes': pic.notes,
             'selected': value == pic.id,
             'id': pic.id,
         })
     context = {'pictures': pictures, 'current_id': value, 'name': name}
     return mark_safe(render_to_response('gallery.html', context).content)
Example #7
0
 def render(self, name, value, attrs=None, **__):
     if value:
         picture = Picture.objects.get(id=value)
         thumb = thumbnail(picture.file, '96x54', crop='center')
         img = ('<img src="%s" width="%d" height="%d" alt="%s">' %
                (thumb.url, thumb.width, thumb.height,
                 picture.notes and cgi.escape(picture.notes) or ''))
         html = ('<input type="hidden" name="%s" value="%d">'
                 '<a href="%s" title="Current picture">%s</a> ' % (
                     name,
                     picture.id,
                     reverse('manage:picture_edit', args=(picture.id, )),
                     img,
                 ))
         if self.editable:
             html += ('<a href="%s?event=%d" '
                      'title="This will leave the editing without saving"'
                      '>Pick another</a>' %
                      (reverse('manage:picturegallery'), self.instance.id))
         else:
             html += ('You can pick a different picture later')
         return mark_safe(html)
     else:
         html = ('<a href="%s?event=%d" '
                 'title="This will leave the editing without saving">'
                 'Pick a picture from the gallery</a>' % (
                     reverse('manage:picturegallery'),
                     self.instance.id,
                 ))
         return mark_safe(html)
Example #8
0
    def get(self, request, slug):
        event = self.get_event(slug, request)
        if not self.can_view_event(event, request):
            return self.cant_view_event(event, request)
        if not self.can_edit_event(event, request):
            return self.cant_edit_event(event, request)

        pictures = []
        missing = []
        fetch = []
        base_qs = Picture.objects.filter(event=event)

        prev = None
        for at in get_timenail_timestamps(event):
            qs = base_qs.filter(timestamp=at)
            for picture in qs.order_by('-modified')[:1]:
                thumb = thumbnail(
                    picture.file, '160x90', crop='center'
                )
                similarity = None
                img = Image.open(picture.file)
                if prev is not None:
                    cmp = FuzzyImageCompare(prev, img)
                    similarity = cmp.similarity()
                prev = img
                pictures.append({
                    'at': picture.timestamp,
                    'thumbnail': {
                        'url': thumb.url,
                        'width': thumb.width,
                        'height': thumb.height,
                    },
                    'similarity': similarity
                })
                break
            else:
                missing.append(at)
                lock = 'lock-{}-{}'.format(event.id, at)
                if not cache.get(lock):
                    fetch.append(at)
                    cache.set(lock, True, 60 * 10)

        if fetch:
            # break it up so that we only ask for 10 at a time
            fetches = [fetch[i:i + 10] for i in range(0, len(fetch), 10)]
            for group in fetches:
                tasks.create_timestamp_pictures.delay(event.id, group)

        return http.JsonResponse({
            'pictures': pictures,
            'missing': len(missing),
        })
Example #9
0
    def get_object(self, request, channel_slug=None):
        self._root_url = get_base_url(request)
        if channel_slug:
            self.channel = get_object_or_404(
                Channel,
                slug__iexact=channel_slug
            )
        else:
            self.channel = Channel.objects.get(
                slug=settings.DEFAULT_CHANNEL_SLUG
            )
        if self.channel.cover_art:
            self.itunes_lg_url = thumbnail(
                self.channel.cover_art, '1400x1400'
            ).url
            self.itunes_sm_url = thumbnail(
                self.channel.cover_art, '144x144'
            ).url
            if self.itunes_lg_url.startswith('//'):
                # e.g. //cdn.example.com/media/cache/file.png
                protocol = self._root_url.split('//')[0]
                self.itunes_lg_url = protocol + self.itunes_lg_url
                self.itunes_sm_url = protocol + self.itunes_sm_url
            elif '://' not in self.itunes_lg_url:
                self.itunes_lg_url = self._root_url + self.itunes_lg_url
                self.itunes_sm_url = self._root_url + self.itunes_sm_url
        else:
            # Use the default ones
            self.itunes_sm_url = get_abs_static(
                'main/img/podcast-cover-144x144.png',
                request
            )
            self.itunes_lg_url = get_abs_static(
                'main/img/podcast-cover-1400x1400.png',
                request
            )

        super(ITunesFeed, self).get_object(request)
Example #10
0
def upload_video(event):
    if isinstance(event, basestring):  # pragma: no cover
        # This is only really used when you use the commandline tool, like
        # ./manage.py debug-amara upload_video my-cool-slug
        if event.isdigit():
            event = Event.objects.get(id=event)
        else:
            event = Event.objects.get(
                Q(slug=event) | Q(title=event)
            )

    video_url, _ = videoinfo.get_video_url(
        event,
        True,
        False,
    )

    # Same dimensions we use for the Open Graph in main/event.html
    picture = event.picture and event.picture.file or event.placeholder_img
    thumb = thumbnail(picture, '385x218', crop='center')

    data = {
        'video_url': video_url,
        'title': event.title,
        'description': event.short_description or event.description,
        'duration': event.duration,
        # 'primary_audio_language_code': event.primary_audio_language_code,
        'team': settings.AMARA_TEAM,
        'project': settings.AMARA_PROJECT,
        'thumbnail': build_absolute_url(thumb.url),
    }

    response = requests.post(
        settings.AMARA_BASE_URL + '/api/videos/',
        data=data,
        headers=_get_headers()
    )
    if not response.status_code == 201:
        raise UploadError(response.status_code, response.content)

    upload_info = response.json()

    amara_video, _ = AmaraVideo.objects.get_or_create(
        event=event,
        video_url=video_url,
        video_id=upload_info['id'],
        upload_info=upload_info,
    )

    return amara_video
Example #11
0
def thumbnails(request):
    form = forms.ThumbnailsForm(request.GET)
    if not form.is_valid():
        return http.HttpResponseBadRequest(form.errors)
    id = form.cleaned_data['id']
    width = form.cleaned_data['width']
    height = form.cleaned_data['height']
    geometry = '%sx%s' % (width, height)
    event = get_object_or_404(Event, id=id)
    thumbnails = []
    for picture in Picture.objects.filter(event=event).order_by('created'):
        thumb = thumbnail(picture.file, geometry, crop='center')
        thumbnails.append(thumb.url)

    return {'thumbnails': thumbnails}
Example #12
0
def thumbnails(request):
    form = forms.ThumbnailsForm(request.GET)
    if not form.is_valid():
        return http.HttpResponseBadRequest(form.errors)
    id = form.cleaned_data['id']
    width = form.cleaned_data['width']
    height = form.cleaned_data['height']
    geometry = '%sx%s' % (width, height)
    event = get_object_or_404(Event, id=id)
    thumbnails = []
    for picture in Picture.objects.filter(event=event).order_by('created'):
        thumb = thumbnail(picture.file, geometry, crop='center')
        thumbnails.append(thumb.url)

    return {'thumbnails': thumbnails}
Example #13
0
def upload_video(event):
    if isinstance(event, basestring):  # pragma: no cover
        # This is only really used when you use the commandline tool, like
        # ./manage.py debug-amara upload_video my-cool-slug
        if event.isdigit():
            event = Event.objects.get(id=event)
        else:
            event = Event.objects.get(Q(slug=event) | Q(title=event))

    video_url, _ = videoinfo.get_video_url(
        event,
        True,
        False,
    )

    # Same dimensions we use for the Open Graph in main/event.html
    picture = event.picture and event.picture.file or event.placeholder_img
    thumb = thumbnail(picture, '385x218', crop='center')

    data = {
        'video_url': video_url,
        'title': event.title,
        'description': event.short_description or event.description,
        'duration': event.duration,
        # 'primary_audio_language_code': event.primary_audio_language_code,
        'team': settings.AMARA_TEAM,
        'project': settings.AMARA_PROJECT,
        'thumbnail': build_absolute_url(thumb.url),
    }

    response = requests.post(settings.AMARA_BASE_URL + '/api/videos/',
                             data=data,
                             headers=_get_headers())
    if not response.status_code == 201:
        raise UploadError(response.status_code, response.content)

    upload_info = response.json()

    amara_video, _ = AmaraVideo.objects.get_or_create(
        event=event,
        video_url=video_url,
        video_id=upload_info['id'],
        upload_info=upload_info,
    )

    return amara_video
Example #14
0
    def __init__(self, event, *args, **kwargs):
        super(EventTweetForm, self).__init__(*args, **kwargs)
        self.fields['text'].help_text = (
            '<b class="char-counter">140</b> characters left. '
            '<span class="char-counter-warning"><b>Note!</b> Sometimes '
            'Twitter can count it as longer than it appears if you '
            'include a URL. '
            'It\'s usually best to leave a little room.</span>'
        )
        # it's a NOT NULL field but it defaults to NOW()
        # in the views code
        self.fields['send_date'].required = False

        if event.tags.all():

            def pack_tags(tags):
                return '[%s]' % (','.join('"%s"' % x for x in tags))

            self.fields['text'].help_text += (
                '<br><a href="#" class="include-event-tags" '
                'data-tags=\'%s\'>include all event tags</a>'
                % pack_tags([x.name for x in event.tags.all()])
            )

        if event.placeholder_img or event.picture:
            from airmozilla.main.templatetags.jinja_helpers import thumbnail
            if event.picture:
                pic = event.picture.file
            else:
                pic = event.placeholder_img
            thumb = thumbnail(pic, '160x90', crop='center')

            self.fields['include_placeholder'].help_text = (
                '<img src="%(url)s" alt="placeholder" class="thumbnail" '
                'width="%(width)s" width="%(height)s">' %
                {
                    'url': thumb.url,
                    'width': thumb.width,
                    'height': thumb.height
                }
            )
        else:
            del self.fields['include_placeholder']

        self.fields['send_date'].help_text = 'Timezone is UTC'
Example #15
0
 def render(self, name, value, attrs=None, **__):
     if value:
         picture = Picture.objects.get(id=value)
         thumb = thumbnail(picture.file, '96x54', crop='center')
         img = (
             '<img src="%s" width="%d" height="%d" alt="%s">' % (
                 thumb.url,
                 thumb.width,
                 thumb.height,
                 picture.notes and cgi.escape(picture.notes) or ''
             )
         )
         html = (
             '<input type="hidden" name="%s" value="%d">'
             '<a href="%s" title="Current picture">%s</a> ' % (
                 name,
                 picture.id,
                 reverse('manage:picture_edit', args=(picture.id,)),
                 img,
             )
         )
         if self.editable:
             html += (
                 '<a href="%s?event=%d" '
                 'title="This will leave the editing without saving"'
                 '>Pick another</a>' % (
                     reverse('manage:picturegallery'),
                     self.instance.id
                 )
             )
         else:
             html += (
                 'You can pick a different picture later'
             )
         return mark_safe(html)
     else:
         html = (
             '<a href="%s?event=%d" '
             'title="This will leave the editing without saving">'
             'Pick a picture from the gallery</a>' % (
                 reverse('manage:picturegallery'),
                 self.instance.id,
             )
         )
         return mark_safe(html)
Example #16
0
 def render(self, name, value, attrs):
     pictures = []
     qs = Picture.objects.all()
     if self.event:
         qs = qs.exclude(
             timestamp__isnull=False
         )
         qs = qs.filter(
             Q(event__isnull=True) |
             Q(event=self.event)
         )
         # If the current event does use an inactive picture,
         # let it still be a choice.
         if self.event.picture_id:
             qs = qs.filter(
                 Q(is_active=True) | Q(id=self.event.picture_id)
             )
         else:
             qs = qs.filter(is_active=True)
     else:
         qs = qs.filter(
             event__isnull=True,
             is_active=True,
         )
     for pic in qs.order_by('event', '-created'):
         thumb = thumbnail(pic.file, '160x90', crop='center')
         pictures.append({
             'thumb': {
                 'url': thumb.url,
                 'width': thumb.width,
                 'height': thumb.height
             },
             'notes': pic.notes,
             'selected': value == pic.id,
             'id': pic.id,
         })
     context = {
         'pictures': pictures,
         'current_id': value,
         'name': name
     }
     return mark_safe(render_to_response('gallery.html', context).content)
Example #17
0
    def test_thumbnail_with_some_integrityerrors(
        self,
        mocked_get_thumbnail,
        mocked_time
    ):

        runs = []

        def proxy(*args, **kwargs):
            runs.append(args)
            if len(runs) < 3:
                raise IntegrityError('bla')
            return get_thumbnail(*args, **kwargs)

        mocked_get_thumbnail.side_effect = proxy

        nailed = thumbnail(os.path.basename(self.destination), '10x10')
        eq_(nailed.width, 10)
        # we don't want these lying around in local install
        nailed.delete()
Example #18
0
    def test_thumbnail_with_some_integrityerrors(
        self,
        mocked_get_thumbnail,
        mocked_time
    ):

        runs = []

        def proxy(*args, **kwargs):
            runs.append(args)
            if len(runs) < 3:
                raise IntegrityError('bla')
            return get_thumbnail(*args, **kwargs)

        mocked_get_thumbnail.side_effect = proxy

        nailed = thumbnail(os.path.basename(self.destination), '10x10')
        eq_(nailed.width, 10)
        # we don't want these lying around in local install
        nailed.delete()
Example #19
0
    def __init__(self, event, *args, **kwargs):
        super(EventTweetForm, self).__init__(*args, **kwargs)
        self.fields['text'].help_text = (
            '<b class="char-counter">140</b> characters left. '
            '<span class="char-counter-warning"><b>Note!</b> Sometimes '
            'Twitter can count it as longer than it appears if you '
            'include a URL. '
            'It\'s usually best to leave a little room.</span>')
        # it's a NOT NULL field but it defaults to NOW()
        # in the views code
        self.fields['send_date'].required = False

        if event.tags.all():

            def pack_tags(tags):
                return '[%s]' % (','.join('"%s"' % x for x in tags))

            self.fields['text'].help_text += (
                '<br><a href="#" class="include-event-tags" '
                'data-tags=\'%s\'>include all event tags</a>' %
                pack_tags([x.name for x in event.tags.all()]))

        if event.placeholder_img or event.picture:
            from airmozilla.main.templatetags.jinja_helpers import thumbnail
            if event.picture:
                pic = event.picture.file
            else:
                pic = event.placeholder_img
            thumb = thumbnail(pic, '160x90', crop='center')

            self.fields['include_placeholder'].help_text = (
                '<img src="%(url)s" alt="placeholder" class="thumbnail" '
                'width="%(width)s" width="%(height)s">' % {
                    'url': thumb.url,
                    'width': thumb.width,
                    'height': thumb.height
                })
        else:
            del self.fields['include_placeholder']

        self.fields['send_date'].help_text = 'Timezone is UTC'
Example #20
0
def send_tweet(event_tweet, save=True):
    if event_tweet.include_placeholder:
        if event_tweet.event.picture:
            pic = event_tweet.event.picture.file
        else:
            pic = event_tweet.event.placeholder_img
        thumb = thumbnail(
            pic,
            '385x218',  # 16/9 ratio
            crop='center'
        )
        file_path = thumb.storage.path(thumb.name)
    else:
        file_path = None

    try:
        tweet_id = _send(event_tweet.text, file_path=file_path)
        event_tweet.tweet_id = tweet_id
        event_tweet.error = None
    except Exception, msg:
        logging.error("Failed to send tweet", exc_info=True)
        event_tweet.error = str(msg)
        event_tweet.failed_attempts += 1
Example #21
0
def redirect_picture_thumbnail(request, id):
    picture = get_object_or_404(Picture, id=id)
    geometry = request.GET.get('geometry', '100x100')
    crop = request.GET.get('crop', 'center')
    thumb = thumbnail(picture.file, geometry, crop=crop)
    return redirect(thumb.url)
Example #22
0
 def test_thumbnail(self):
     nailed = thumbnail(os.path.basename(self.destination), '10x10')
     eq_(nailed.width, 10)
     # we don't want these lying around in local install
     nailed.delete()
Example #23
0
 def poster_url(geometry='896x504', crop='center'):
     image = event.picture and event.picture.file or event.placeholder_img
     return thumbnail(image, geometry, crop=crop).url
Example #24
0
    def get(self, request, slug):
        event = self.get_event(slug, request)
        if not self.can_view_event(event, request):
            return self.cant_view_event(event, request)
        if not self.can_edit_event(event, request):
            return self.cant_edit_event(event, request)

        pictures = []
        missing = []
        fetch = []
        base_qs = Picture.objects.filter(event=event)

        def make_similarity_cache_key(picture1, picture2):
            if picture2:
                modify_times = picture1.modified.strftime('%f')
                modify_times += picture2.modified.strftime('%f')
                return 'similarity:' + modify_times

        prev = None
        for at in get_timenail_timestamps(event):
            qs = base_qs.filter(timestamp=at)
            for picture in qs.order_by('-modified')[:1]:
                thumb = thumbnail(
                    picture.file,
                    # size shown with width set in CSS
                    '160x90',
                    crop='center',
                )
                similarity = -1
                similarity_cache_key = make_similarity_cache_key(
                    picture,
                    prev,
                )
                if similarity_cache_key:
                    similarity = cache.get(similarity_cache_key, -1)

                # still here?
                if similarity == -1:
                    similarity = None
                    if prev is not None:
                        cmp = FuzzyImageCompare(
                            Image.open(prev.file),
                            Image.open(picture.file),
                        )
                        similarity = cmp.similarity()
                        cache.set(
                            similarity_cache_key,
                            similarity,
                            60 * 60 * 24 * 7  # 7 days
                        )
                prev = picture
                pictures.append({
                    'at': picture.timestamp,
                    'thumbnail': {
                        'url': thumb.url,
                        'width': thumb.width,
                        'height': thumb.height,
                    },
                    'similarity': similarity
                })
                break
            else:
                missing.append(at)
                lock = 'lock-{}-{}'.format(event.id, at)
                if not cache.get(lock):
                    fetch.append(at)
                    cache.set(lock, True, 60 * 10)

        if fetch:
            # break it up so that we only ask for 10 at a time
            fetches = [fetch[i:i + 10] for i in range(0, len(fetch), 10)]
            for group in fetches:
                tasks.create_timestamp_pictures.delay(event.id, group)

        return http.JsonResponse({
            'pictures': pictures,
            'missing': len(missing),
        })
def redirect_picture_thumbnail(request, id):
    picture = get_object_or_404(Picture, id=id)
    geometry = request.GET.get('geometry', '100x100')
    crop = request.GET.get('crop', 'center')
    thumb = thumbnail(picture.file, geometry, crop=crop)
    return redirect(thumb.url)
Example #26
0
def get_thumbnail(event):
    image = event.picture and event.picture.file or event.placeholder_img
    geometry = '160x90'
    crop = 'center'

    return thumbnail(image, geometry, crop=crop)
Example #27
0
 def poster_url(geometry='896x504', crop='center'):
     image = event.picture and event.picture.file or event.placeholder_img
     return thumbnail(image, geometry, crop=crop).url
Example #28
0
def get_thumbnail(event):
    image = event.picture and event.picture.file or event.placeholder_img
    geometry = '160x90'
    crop = 'center'

    return thumbnail(image, geometry, crop=crop)
Example #29
0
 def test_thumbnail(self):
     nailed = thumbnail(os.path.basename(self.destination), '10x10')
     eq_(nailed.width, 10)
     # we don't want these lying around in local install
     nailed.delete()