예제 #1
0
    def _render(self, context):
        file_ = self.file_.resolve(context)
        geometry = self.geometry.resolve(context)
        options = {}
        for key, expr in self.options:
            noresolve = {'True': True, 'False': False, 'None': None}
            value = noresolve.get(text_type(expr), expr.resolve(context))
            if key == 'options':
                options.update(value)
            else:
                options[key] = value

        thumbnail = get_thumbnail(file_, geometry, **options)

        if not thumbnail or (isinstance(thumbnail, DummyImageFile) and self.nodelist_empty):
            if self.nodelist_empty:
                return self.nodelist_empty.render(context)
            else:
                return ''

        if self.as_var:
            context.push()
            context[self.as_var] = thumbnail
            output = self.nodelist_file.render(context)
            context.pop()
        else:
            output = thumbnail.url

        return output
예제 #2
0
    def _render(self, context):
        file_ = self.file_.resolve(context)
        geometry = self.geometry.resolve(context)
        options = {}
        for key, expr in self.options:
            noresolve = {'True': True, 'False': False, 'None': None}
            value = noresolve.get(text_type(expr), expr.resolve(context))
            if key == 'options':
                options.update(value)
            else:
                options[key] = value

        thumbnail = get_thumbnail(file_, geometry, **options)

        if not thumbnail or (isinstance(thumbnail, DummyImageFile) and self.nodelist_empty):
            if self.nodelist_empty:
                return self.nodelist_empty.render(context)
            else:
                return ''

        if self.as_var:
            context.push()
            context[self.as_var] = thumbnail
            output = self.nodelist_file.render(context)
            context.pop()
        else:
            output = thumbnail.url

        return output
예제 #3
0
 def _create_thumbnail(self, source_image, geometry_string, options,
                       thumbnail):
     """
     Creates the thumbnail by using default.engine
     """
     logger.debug(text_type('Creating thumbnail file [%s] at [%s] with [%s]'),
                  thumbnail.name, geometry_string, options)
     ratio = default.engine.get_image_ratio(source_image, options)
     geometry = parse_geometry(geometry_string, ratio)
     image = default.engine.create(source_image, geometry, options)
     default.engine.write(image, options, thumbnail)
     # It's much cheaper to set the size here
     size = default.engine.get_image_size(image)
     thumbnail.set_size(size)
예제 #4
0
 def _create_thumbnail(self, source_image, geometry_string, options,
                       thumbnail):
     """
     Creates the thumbnail by using default.engine
     """
     logger.debug(text_type('Creating thumbnail file [%s] at [%s] with [%s]'),
                  thumbnail.name, geometry_string, options)
     ratio = default.engine.get_image_ratio(source_image, options)
     geometry = parse_geometry(geometry_string, ratio)
     image = default.engine.create(source_image, geometry, options)
     default.engine.write(image, options, thumbnail)
     # It's much cheaper to set the size here
     size = default.engine.get_image_size(image)
     thumbnail.set_size(size)
예제 #5
0
파일: tasks.py 프로젝트: hovel/sorlery
def create_thumbnail(file_, geometry_string, options, name, force=False):
    if file_:
        source = ImageFile(file_)
    else:
        return

    thumbnail = ImageFile(name, default.storage)

    # We have to check exists() because the Storage backend does not
    # overwrite in some implementations.
    if settings.THUMBNAIL_FORCE_OVERWRITE or not thumbnail.exists() or force:
        try:
            source_image = default.engine.get_image(source)
        except IOError as e:
            logger.exception(e)
            # if S3Storage says file doesn't exist remotely, don't try to
            # create it and exit early.
            # Will return working empty image type; 404'd image
            logger.warn(
                text_type('Remote file [%s] at [%s] does not exist'),
                file_, geometry_string)
            return

        # We might as well set the size since we have the image in memory
        try:
            image_info = default.engine.get_image_info(source_image)
            options['image_info'] = image_info
        except AttributeError:
            options['image_info'] = {}
        size = default.engine.get_image_size(source_image)
        source.set_size(size)

        try:
            default.backend._create_thumbnail(
                source_image, geometry_string, options, thumbnail)
            default.backend._create_alternative_resolutions(
                source_image, geometry_string, options, thumbnail.name)
        finally:
            default.engine.cleanup(source_image)

    # If the thumbnail exists we don't create it, the other option is
    # to delete and write but this could lead to race conditions so I
    # will just leave that out for now.
    default.kvstore.get_or_set(source)
    default.kvstore.set(thumbnail, source)
예제 #6
0
    def _render(self, context):
        file_ = self.file_.resolve(context)
        lazy_fill = settings.THUMBNAIL_LAZY_FILL_EMPTY
        geometry = self.geometry.resolve(context)
        options = {}
        for key, expr in self.options:
            noresolve = {u'True': True, u'False': False, u'None': None}
            value = noresolve.get(text_type(expr), expr.resolve(context))
            if key == 'options':
                options.update(value)
            else:
                options[key] = value

        if isinstance(file_, string_type):
            path = file_
            exists = re.search('^https?://', path) or os.path.exists(path)
        else:
            path = getattr(file_, 'path', None) or \
                getattr(file_, 'name', None) or ''
            exists = os.path.exists(path)

        if file_ and exists:
            thumbnail = default.backend.get_thumbnail(
                file_, geometry, **options
            )
        elif self.nodelist_empty:
            return self.nodelist_empty.render(context)
        elif settings.THUMBNAIL_DUMMY or lazy_fill:
            thumbnail = DummyImageFile(geometry)
        else:
            if self.nodelist_empty:
                return self.nodelist_empty.render(context)
            else:
                return ''

        if self.as_var:
            context.push()
            context[self.as_var] = thumbnail
            output = self.nodelist_file.render(context)
            context.pop()
        else:
            output = thumbnail.url

        return output
예제 #7
0
 def _colorspace(self, image, colorspace):
     if colorspace == 'RGB':
         if image.mode == 'RGBA':
             return image  # RGBA is just RGB + Alpha
         if image.mode == 'LA' or (image.mode == 'P' and 'transparency' in image.info):
             newimage = image.convert('RGBA')
             transparency = image.info.get('transparency')
             if transparency is not None:
                 try:
                     mask = Image.new('L', image.size, color=transparency)
                 except ValueError as e:
                     logger.info(text_type('Skip setting transparency, reason: %s'), e)
                 else:
                     newimage.putalpha(mask)
             return newimage
         return image.convert('RGB')
     if colorspace == 'GRAY':
         return image.convert('L')
     return image
예제 #8
0
    def _render(self, context):
        file_ = self.file_.resolve(context)
        lazy_fill = settings.THUMBNAIL_LAZY_FILL_EMPTY
        geometry = self.geometry.resolve(context)
        options = {}
        for key, expr in self.options:
            noresolve = {u'True': True, u'False': False, u'None': None}
            value = noresolve.get(text_type(expr), expr.resolve(context))
            if key == 'options':
                options.update(value)
            else:
                options[key] = value

        # logic arranged to ensure we're not doing any unecessary calls to os.path.exists
        if file_ and (not lazy_fill
                      or lazy_fill and os.path.exists(file_.path)):
            thumbnail = default.backend.get_thumbnail(file_, geometry,
                                                      **options)
        elif self.nodelist_empty:
            return self.nodelist_empty.render(context)
        elif settings.THUMBNAIL_DUMMY or lazy_fill:
            thumbnail = DummyImageFile(geometry)
        else:
            if self.nodelist_empty:
                return self.nodelist_empty.render(context)
            else:
                return ''

        if self.as_var:
            context.push()
            context[self.as_var] = thumbnail
            output = self.nodelist_file.render(context)
            context.pop()
        else:
            output = thumbnail.url

        return output
예제 #9
0
    def _render(self, context):
        file_ = self.file_.resolve(context)
        lazy_fill = settings.THUMBNAIL_LAZY_FILL_EMPTY
        geometry = self.geometry.resolve(context)
        options = {}
        for key, expr in self.options:
            noresolve = {u'True': True, u'False': False, u'None': None}
            value = noresolve.get(text_type(expr), expr.resolve(context))
            if key == 'options':
                options.update(value)
            else:
                options[key] = value

        # logic arranged to ensure we're not doing any unecessary calls to os.path.exists
        if file_ and (not lazy_fill or lazy_fill and os.path.exists(file_.path)):
            thumbnail = default.backend.get_thumbnail(
                file_, geometry, **options
            )
        elif self.nodelist_empty:
            return self.nodelist_empty.render(context)
        elif settings.THUMBNAIL_DUMMY or lazy_fill:
            thumbnail = DummyImageFile(geometry)
        else:
            if self.nodelist_empty:
                return self.nodelist_empty.render(context)
            else:
                return ''

        if self.as_var:
            context.push()
            context[self.as_var] = thumbnail
            output = self.nodelist_file.render(context)
            context.pop()
        else:
            output = thumbnail.url

        return output
예제 #10
0
    def get_thumbnail(self, file_, geometry_string, **options):
        """
        Returns thumbnail as an ImageFile instance for file with geometry and
        options given. First it will try to get it from the key value store,
        secondly it will create it.
        """
        logger.debug(text_type('Getting thumbnail for file [%s] at [%s]'), file_, geometry_string)

        if file_:
            source = ImageFile(file_)
        elif settings.THUMBNAIL_DUMMY:
            return DummyImageFile(geometry_string)
        else:
            return None

        # preserve image filetype
        if settings.THUMBNAIL_PRESERVE_FORMAT:
            options.setdefault('format', self._get_format(source))

        for key, value in self.default_options.items():
            options.setdefault(key, value)

        # For the future I think it is better to add options only if they
        # differ from the default settings as below. This will ensure the same
        # filenames being generated for new options at default.
        for key, attr in self.extra_options:
            value = getattr(settings, attr)
            if value != getattr(default_settings, attr):
                options.setdefault(key, value)

        name = self._get_thumbnail_filename(source, geometry_string, options)
        thumbnail = ImageFile(name, default.storage)
        cached = default.kvstore.get(thumbnail)
        heroku_logger = logging.getLogger('heroku')
        heroku_logger = logging.getLogger('REDIS get {}'.format(cached))
        if cached:
            return cached

        # We have to check exists() because the Storage backend does not
        # overwrite in some implementations.
        if settings.THUMBNAIL_FORCE_OVERWRITE or not thumbnail.exists():
            try:
                source_image = default.engine.get_image(source)
            except IOError as e:
                logger.exception(e)
                if settings.THUMBNAIL_DUMMY:
                    return DummyImageFile(geometry_string)
                else:
                    # if S3Storage says file doesn't exist remotely, don't try to
                    # create it and exit early.
                    # Will return working empty image type; 404'd image
                    logger.warn(text_type('Remote file [%s] at [%s] does not exist'),
                                file_, geometry_string)

                    return thumbnail

            # We might as well set the size since we have the image in memory
            image_info = default.engine.get_image_info(source_image)
            options['image_info'] = image_info
            size = default.engine.get_image_size(source_image)
            source.set_size(size)

            try:
                self._create_thumbnail(source_image, geometry_string, options,
                                       thumbnail)
                self._create_alternative_resolutions(source_image, geometry_string,
                                                     options, thumbnail.name)
            finally:
                default.engine.cleanup(source_image)

        # If the thumbnail exists we don't create it, the other option is
        # to delete and write but this could lead to race conditions so I
        # will just leave that out for now.
        default.kvstore.get_or_set(source)
        default.kvstore.set(thumbnail, source)
        return thumbnail
예제 #11
0
    def get_thumbnail(self, file_, geometry_string, **options):

        # PATCHED
        lazy = options.pop('lazy', False)
        """
        Returns thumbnail as an ImageFile instance for file with geometry and
        options given. First it will try to get it from the key value store,
        secondly it will create it.
        """
        logger.debug(text_type('Getting thumbnail for file [%s] at [%s]'),
                     file_, geometry_string)

        if isinstance(file_, CachedImageFile):
            source = file_
        else:

            if file_:
                source = ImageFile(file_)
            elif settings.THUMBNAIL_DUMMY:
                return DummyImageFile(geometry_string)
            else:
                return None

        #preserve image filetype
        if settings.THUMBNAIL_PRESERVE_FORMAT:
            options.setdefault('format', self._get_format(file_))

        for key, value in self.default_options.items():
            options.setdefault(key, value)

        # For the future I think it is better to add options only if they
        # differ from the default settings as below. This will ensure the same
        # filenames being generated for new options at default.
        for key, attr in self.extra_options:
            value = getattr(settings, attr)
            if value != getattr(default_settings, attr):
                options.setdefault(key, value)
        name = self._get_thumbnail_filename(source, geometry_string, options)
        thumbnail = ImageFile(name, default.storage)
        cached = default.kvstore.get(thumbnail)
        if cached:
            return cached
        else:

            # PATCHED
            if lazy:
                key = create_sorl_key(source, geometry_string, options)
                return LazyImageFile(key)
            else:
                if default.storage.exists(name):
                    default.kvstore.get_or_set(source)
                    default.kvstore.set(thumbnail, source)
                    return thumbnail

            # We have to check exists() because the Storage backend does not
            # overwrite in some implementations.
            # so we make the assumption that if the thumbnail is not cached, it doesn't exist
            try:
                source_image = default.engine.get_image(source)
            except IOError:
                if settings.THUMBNAIL_DUMMY:
                    return DummyImageFile(geometry_string)
                else:
                    # if S3Storage says file doesn't exist remotely, don't try to
                    # create it and exit early.
                    # Will return working empty image type; 404'd image
                    logger.warn(
                        text_type('Remote file [%s] at [%s] does not exist'),
                        file_, geometry_string)
                    return thumbnail

            # We might as well set the size since we have the image in memory
            image_info = default.engine.get_image_info(source_image)
            options['image_info'] = image_info
            size = default.engine.get_image_size(source_image)
            source.set_size(size)
            try:
                self._create_thumbnail(source_image, geometry_string, options,
                                       thumbnail)
                self._create_alternative_resolutions(source_image,
                                                     geometry_string, options,
                                                     thumbnail.name)
            finally:
                default.engine.cleanup(source_image)

        # If the thumbnail exists we don't create it, the other option is
        # to delete and write but this could lead to race conditions so I
        # will just leave that out for now.
        default.kvstore.get_or_set(source)
        default.kvstore.set(thumbnail, source)
        return thumbnail
예제 #12
0
파일: backend.py 프로젝트: hovel/sorlery
    def get_thumbnail(self, file_, geometry_string, **options):
        """
        Returns thumbnail as an ImageFile instance for file with geometry and
        options given. First it will try to get it from the key value store,
        secondly it will create it.
        """
        logger.debug(text_type('Getting thumbnail for file [%s] at [%s]'),
                     file_, geometry_string)

        async = options.pop('async', True)
        if not async:
            return super(QueuedThumbnailBackend, self).get_thumbnail(
                file_, geometry_string, **options)

        if file_:
            source = ImageFile(file_)
        elif settings.THUMBNAIL_DUMMY:
            return DummyImageFile(geometry_string)
        else:
            return None

        # preserve image filetype
        if settings.THUMBNAIL_PRESERVE_FORMAT:
            options.setdefault('format', self._get_format(source))

        for key, value in self.default_options.items():
            options.setdefault(key, value)

        # For the future I think it is better to add options only if they
        # differ from the default settings as below. This will ensure the same
        # filenames being generated for new options at default.
        for key, attr in self.extra_options:
            value = getattr(settings, attr)
            if value != getattr(default_settings, attr):
                options.setdefault(key, value)

        name = self._get_thumbnail_filename(source, geometry_string, options)
        thumbnail = ImageFile(name, default.storage)
        cached = default.kvstore.get(thumbnail)
        if cached:
            return cached

        # We cannot check if the file exists, as remote storage is slow. If
        # we have reached this point, the image does not exist in our kvstore
        # so create the entry and queue the generation of the image.
        #
        # Note: If the thumbnail file has been deleted, you will need to manually
        # clear the corresponding row from the kvstore to have thumbnail rebuilt.
        job = create_thumbnail.delay(file_, geometry_string, options, name)
        if isinstance(file_, string_type):
            filename = file_.split('/')[-1]
        else:
            filename = file_.name
        if job:
            geometry = (0, 0)
            # We can't add a source row to the kvstore without the size
            # information being looked up, so add dummy information here
            # We'll need to correct this information when we generate the thumbnail
            source.set_size(geometry)
            default.kvstore.get_or_set(source)

            # We don't want to do any file access in this thread, so we tell sorlery
            # to proceed as normal and cheekily update the name and storage after
            # the hash has been calculated.
            thumbnail.set_size(geometry)
            default.kvstore.set(thumbnail, source)

            # Now we go back and manually update the thumbnail to point at the source image
            # Hopefully someone can suggest a better way to do this ... but the sorl internals
            # don't make it easy to.
            rawvalue = default.kvstore._get_raw(add_prefix(thumbnail.key))
            rawvaluearr = deserialize(rawvalue)
            rawvaluearr['name'] = filename
            default.kvstore._set_raw(add_prefix(thumbnail.key),
                                     serialize(rawvaluearr))

        thumbnail.name = filename
        return thumbnail
예제 #13
0
    def get_thumbnail(self, file_, geometry_string, **options):
        """
        Returns thumbnail as an ImageFile instance for file with geometry and
        options given. First it will try to get it from the key value store,
        secondly it will create it.
        """
        logger.debug(text_type('Getting thumbnail for file [%s] at [%s]'),
                     file_, geometry_string)

        async = options.pop('async', True)
        if not async:
            return super(QueuedThumbnailBackend,
                         self).get_thumbnail(file_, geometry_string, **options)

        if file_:
            source = ImageFile(file_)
        elif settings.THUMBNAIL_DUMMY:
            return DummyImageFile(geometry_string)
        else:
            return None

        # preserve image filetype
        if settings.THUMBNAIL_PRESERVE_FORMAT:
            options.setdefault('format', self._get_format(source))

        for key, value in self.default_options.items():
            options.setdefault(key, value)

        # For the future I think it is better to add options only if they
        # differ from the default settings as below. This will ensure the same
        # filenames being generated for new options at default.
        for key, attr in self.extra_options:
            value = getattr(settings, attr)
            if value != getattr(default_settings, attr):
                options.setdefault(key, value)

        name = self._get_thumbnail_filename(source, geometry_string, options)
        thumbnail = ImageFile(name, default.storage)
        cached = default.kvstore.get(thumbnail)
        if cached:
            return cached

        # We cannot check if the file exists, as remote storage is slow. If
        # we have reached this point, the image does not exist in our kvstore
        # so create the entry and queue the generation of the image.
        #
        # Note: If the thumbnail file has been deleted, you will need to manually
        # clear the corresponding row from the kvstore to have thumbnail rebuilt.
        job = create_thumbnail.delay(file_, geometry_string, options, name)
        if isinstance(file_, string_type):
            filename = file_.split('/')[-1]
        else:
            filename = file_.name
        if job:
            geometry = (0, 0)
            # We can't add a source row to the kvstore without the size
            # information being looked up, so add dummy information here
            # We'll need to correct this information when we generate the thumbnail
            source.set_size(geometry)
            default.kvstore.get_or_set(source)

            # We don't want to do any file access in this thread, so we tell sorlery
            # to proceed as normal and cheekily update the name and storage after
            # the hash has been calculated.
            thumbnail.set_size(geometry)
            default.kvstore.set(thumbnail, source)

            # Now we go back and manually update the thumbnail to point at the source image
            # Hopefully someone can suggest a better way to do this ... but the sorl internals
            # don't make it easy to.
            rawvalue = default.kvstore._get_raw(add_prefix(thumbnail.key))
            rawvaluearr = deserialize(rawvalue)
            rawvaluearr['name'] = filename
            default.kvstore._set_raw(add_prefix(thumbnail.key),
                                     serialize(rawvaluearr))

        thumbnail.name = filename
        return thumbnail
예제 #14
0
    def get_thumbnail(self, file_, geometry_string, **options):
        """
        Return thumbnails as base64 url if not exists in cache and delay convert process.
        Modified version of original get_thumbnail method.
        """
        if not options.pop('lazy', False):
            return super(LazyThumbnailBackend, self).get_thumbnail(file_, geometry_string, **options)

        logger.debug(text_type('Getting thumbnail for file [%s] at [%s]'), file_, geometry_string)

        if file_:
            source = ImageFile(file_)
        elif settings.THUMBNAIL_DUMMY:
            return DummyImageFile(geometry_string)
        else:
            return None

        # preserve image filetype
        if settings.THUMBNAIL_PRESERVE_FORMAT:
            options.setdefault('format', self._get_format(source))

        for key, value in self.default_options.items():
            options.setdefault(key, value)

        # For the future I think it is better to add options only if they
        # differ from the default settings as below. This will ensure the same
        # filenames being generated for new options at default.
        for key, attr in self.extra_options:
            value = getattr(settings, attr)
            if value != getattr(default_settings, attr):
                options.setdefault(key, value)

        name = self._get_thumbnail_filename(source, geometry_string, options)
        thumbnail = ImageFile(name, default.storage)
        cached = default.kvstore.get(thumbnail)

        if cached:
            return cached

        # MODIFIED CODE. Overwriting storage for lazy base64
        thumbnail = ImageFile(name, lazy_storage)
        generate_thumbnail_lazy.delay(file_, geometry_string, **options)
        # End of MODIFIED CODE

        try:
            source_image = default.engine.get_image(source)
        except IOError as e:
            logger.exception(e)
            if settings.THUMBNAIL_DUMMY:
                return DummyImageFile(geometry_string)
            else:
                # if S3Storage says file doesn't exist remotely, don't try to
                # create it and exit early.
                # Will return working empty image type; 404'd image
                logger.warn(text_type('Remote file [%s] at [%s] does not exist'),
                            file_, geometry_string)

                return thumbnail

        # We might as well set the size since we have the image in memory
        image_info = default.engine.get_image_info(source_image)
        options['image_info'] = image_info
        size = default.engine.get_image_size(source_image)
        source.set_size(size)

        try:
            self._create_thumbnail(source_image, geometry_string, options,
                                   thumbnail)
        finally:
            default.engine.cleanup(source_image)

        return thumbnail