Exemple #1
0
def generate_image(inpath, outpath, width=None, height=None, format=JPEG,
                   fill=False, upscale=True, anchor=None, quality=80,
                   progressive=True, placeholder_reason=None):
    mkdir_p(outpath.rpartition('/')[0])
    if not os.path.isfile(inpath):
        if placeholder_reason:
            img = get_placeholder(width, height, placeholder_reason)
        else:
            raise TypeError(u'No such file {}'.format(inpath))
    else:
        img = Image.open(inpath)
    processor_kwargs = dict(width=width, height=height, upscale=upscale)

    if fill:
        processor_kwargs['anchor'] = anchor

    ResizeMethod = ResizeToFill if fill else ResizeToFit
    processor = ResizeMethod(**processor_kwargs)
    new_img = processor.process(img)

    assert (not os.path.exists(outpath), 'Path to save to already exists')

    options = {}
    if format == JPEG:
        options.update({'quality': int(quality), 'progressive': progressive})

    with open(outpath, 'w') as outfile:
        save_image(new_img, outfile, format=format, options=options)
Exemple #2
0
def create_resizes_of_image(image):
    """ Create the web and thumb, and return a list of (source, dest) images to be transferred to
    the fileserver, including the original.
    """
    event = image.event
    year = event.startdate.split('-')[0]
    dest_media_folder = os.path.join('archive', year, slugify(event.name))

    # Add original to files to be transferred
    files_to_transfer = [(image.original.path,
                          os.path.join(dest_media_folder,
                                       '%d-original.jpg' % image.id))]

    # Do the actual conversion
    pil_img = PILImage.open(image.original)
    thumb = ImageOps.fit(pil_img, (75, 75), PILImage.ANTIALIAS)
    #thumb = ResizeToFit(75, 75).process(pil_img)
    websize = ResizeToFit(1500, 800, upscale=False).process(pil_img)
    for size, appendix in [(thumb, 'thumb'), (websize, 'web')]:
        filename = '%s-%s.jpg' % (image.id, appendix)
        local_path = os.path.join(settings.MEDIA_ROOT, 'local',
                                  'raw-archive-images', filename)
        if not os.path.exists(os.path.dirname(local_path)):
            os.mkdir(os.path.dirname(local_path))
        save_image(size, local_path, 'jpeg')
        files_to_transfer.append(
            (local_path, os.path.join(dest_media_folder, filename)))

    # Set the new URL to the original image
    image.original = None
    image.original = dest_media_folder + '/%d-original.jpg' % image.id

    return files_to_transfer
Exemple #3
0
def create_resizes_of_image(image):
    """ Create the web and thumb, and return a list of (source, dest) images to be transferred to
    the fileserver, including the original.
    """
    event = image.event
    year = event.startdate.split('-')[0]
    dest_media_folder = os.path.join('archive', year, slugify(event.name))

    # Add original to files to be transferred
    files_to_transfer = [
        (image.original.path, os.path.join(dest_media_folder, '%d-original.jpg' % image.id))
    ]

    # Do the actual conversion
    pil_img = PILImage.open(image.original)
    thumb = ImageOps.fit(pil_img, (75, 75), PILImage.ANTIALIAS)
    #thumb = ResizeToFit(75, 75).process(pil_img)
    websize = ResizeToFit(1500, 800, upscale=False).process(pil_img)
    for size, appendix in [(thumb, 'thumb'), (websize, 'web')]:
        filename = '%s-%s.jpg' % (image.id, appendix)
        local_path = os.path.join(settings.MEDIA_ROOT, 'local', 'raw-archive-images', filename)
        if not os.path.exists(os.path.dirname(local_path)):
            os.mkdir(os.path.dirname(local_path))
        save_image(size, local_path, 'jpeg')
        files_to_transfer.append(
            (local_path, os.path.join(dest_media_folder, filename))
        )

    # Set the new URL to the original image
    image.original = None
    image.original = dest_media_folder + '/%d-original.jpg' % image.id

    return files_to_transfer
Exemple #4
0
def generate_thumbnail(
    text,
    outname,
    box,
    bg_color=DEFAULT_CONFIG['thumb_bg_color'],
    font=DEFAULT_CONFIG['thumb_font'],
    font_color=DEFAULT_CONFIG['thumb_font_color'],
    font_size=DEFAULT_CONFIG['thumb_font_size'],
    options=None,
):
    """Create a thumbnail image."""

    kwargs = {}
    if font:
        kwargs['font'] = ImageFont.truetype(font, font_size)
    if font_color:
        kwargs['fill'] = font_color

    img = PILImage.new("RGB", box, bg_color)

    anchor = (box[0] // 2, box[1] // 2)
    d = ImageDraw.Draw(img)
    logger.info(f"kwargs: {kwargs}")
    d.text(anchor, text, anchor='mm', **kwargs)

    outformat = 'JPEG'
    logger.info('Save thumnail image: %s (%s)', outname, outformat)
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #5
0
def generate_image(source, outname, settings, options=None):
    """Image processor, rotate and resize the image.

    :param source: path to an image
    :param outname: output filename
    :param settings: settings dict
    :param options: dict with PIL options (quality, optimize, progressive)

    """

    logger = logging.getLogger(__name__)

    if settings['use_orig']:
        utils.copy(source, outname, symlink=settings['orig_link'])
        return

    img = PILImage.open(source)
    original_format = img.format

    if settings['copy_exif_data'] and settings['autorotate_images']:
        logger.warning("The 'autorotate_images' and 'copy_exif_data' settings "
                       "are not compatible because Sigal can't save the "
                       "modified Orientation tag.")

    # Preserve EXIF data
    if settings['copy_exif_data'] and _has_exif_tags(img):
        if options is not None:
            options = deepcopy(options)
        else:
            options = {}
        options['exif'] = img.info['exif']

    # Rotate the img, and catch IOError when PIL fails to read EXIF
    if settings['autorotate_images']:
        try:
            img = Transpose().process(img)
        except (IOError, IndexError):
            pass

    # Resize the image
    if settings['img_processor']:
        try:
            logger.debug('Processor: %s', settings['img_processor'])
            processor_cls = getattr(pilkit.processors,
                                    settings['img_processor'])
        except AttributeError:
            logger.error('Wrong processor name: %s', settings['img_processor'])
            sys.exit()

        processor = processor_cls(*settings['img_size'], upscale=False)
        img = processor.process(img)

    # signal.send() does not work here as plugins can modify the image, so we
    # iterate other the receivers to call them with the image.
    for receiver in signals.img_resized.receivers_for(img):
        img = receiver(img, settings=settings)

    outformat = img.format or original_format or 'JPEG'
    logger.debug(u'Save resized image to {0} ({1})'.format(outname, outformat))
    save_image(img, outname, outformat, options=options, autoconvert=True)
def generate_image(inpath, outpath, width=None, height=None, format=JPEG,
                   fill=False, upscale=True, anchor=None, quality=80,
                   progressive=True, placeholder_reason=None):
    mkdir_p(outpath.rpartition('/')[0])
    if not os.path.isfile(inpath):
        if placeholder_reason:
            img = get_placeholder(width, height, placeholder_reason)
        else:
            raise TypeError(u'No such file {}'.format(inpath))
    else:
        img = Image.open(inpath)
    processor_kwargs = dict(width=width, height=height, upscale=upscale)

    if fill:
        processor_kwargs['anchor'] = anchor

    ResizeMethod = ResizeToFill if fill else ResizeToFit
    processor = ResizeMethod(**processor_kwargs)
    new_img = processor.process(img)

    assert (not os.path.exists(outpath), 'Path to save to already exists')

    options = {}
    if format == JPEG:
        options.update({'quality': int(quality), 'progressive': progressive})

    with open(outpath, 'wb') as outfile:
        save_image(new_img, outfile, format=format, options=options)
Exemple #7
0
def generate_image(source, outname, settings, options=None):
    """Image processor, rotate and resize the image.

    :param source: path to an image
    :param outname: output filename
    :param settings: settings dict
    :param options: dict with PIL options (quality, optimize, progressive)

    """

    logger = logging.getLogger(__name__)

    if settings['use_orig']:
        utils.copy(source, outname, symlink=settings['orig_link'])
        return

    img = PILImage.open(source)
    original_format = img.format

    if settings['copy_exif_data'] and settings['autorotate_images']:
        logger.warning("The 'autorotate_images' and 'copy_exif_data' settings "
                       "are not compatible because Sigal can't save the "
                       "modified Orientation tag.")

    # Preserve EXIF data
    if settings['copy_exif_data'] and _has_exif_tags(img):
        if options is not None:
            options = deepcopy(options)
        else:
            options = {}
        options['exif'] = img.info['exif']

    # Rotate the img, and catch IOError when PIL fails to read EXIF
    if settings['autorotate_images']:
        try:
            img = Transpose().process(img)
        except (IOError, IndexError):
            pass

    # Resize the image
    if settings['img_processor']:
        try:
            logger.debug('Processor: %s', settings['img_processor'])
            processor_cls = getattr(pilkit.processors,
                                    settings['img_processor'])
        except AttributeError:
            logger.error('Wrong processor name: %s', settings['img_processor'])
            sys.exit()

        processor = processor_cls(*settings['img_size'], upscale=False)
        img = processor.process(img)

    # signal.send() does not work here as plugins can modify the image, so we
    # iterate other the receivers to call them with the image.
    for receiver in signals.img_resized.receivers_for(img):
        img = receiver(img, settings=settings)

    outformat = img.format or original_format or 'JPEG'
    logger.debug(u'Save resized image to {0} ({1})'.format(outname, outformat))
    save_image(img, outname, outformat, options=options, autoconvert=True)
    def url(self):
        """ Returns the final url for this version of the image. 
        If it doesn't exists, it generates it"""

        uploads_dir = self.get_uploads_dir()

        img = Image.open(os.path.join(uploads_dir, self.source))

        new_image_filename = self.generate_filename(img)

        # generate the full names and create directories if necesary
        base_cache_dir = os.path.join('cache', self.model, str(self.id))

        cache_dir = os.path.join(
            uploads_dir, base_cache_dir)

        cache_filename = os.path.join(
            cache_dir, new_image_filename)

        if not os.path.exists(cache_dir):
            mkdir_p(cache_dir)

        # Check if the generated image already existed
        if os.path.exists(cache_filename):
            return "/cache/" + self.model + "/" + str(self.id) + "/" + new_image_filename

        else:

            # we process the image and save it on the cache folder
            processor = ProcessorPipeline(self.processors)
            new_image = processor.process(img)

            utils.save_image(new_image, cache_filename, self.format, self.options)

            return os.path.join(base_cache_dir, new_image_filename)
Exemple #9
0
def generate_image(source, outname, settings, options=None):
    """Image processor, rotate and resize the image.

    :param source: path to an image
    :param outname: output filename
    :param settings: settings dict
    :param options: dict with PIL options (quality, optimize, progressive)

    """

    logger = logging.getLogger(__name__)
    img = PILImage.open(source)
    original_format = img.format

    if settings["copy_exif_data"] and settings["autorotate_images"]:
        logger.warning(
            "The 'autorotate_images' and 'copy_exif_data' settings "
            "are not compatible because Sigal can't save the "
            "modified Orientation tag."
        )

    # Preserve EXIF data
    if settings["copy_exif_data"] and _has_exif_tags(img):
        if options is not None:
            options = deepcopy(options)
        else:
            options = {}
        options["exif"] = img.info["exif"]

    # Rotate the img, and catch IOError when PIL fails to read EXIF
    if settings["autorotate_images"]:
        try:
            img = Transpose().process(img)
        except (IOError, IndexError):
            pass

    # Resize the image
    if settings["img_processor"]:
        try:
            logger.debug("Processor: %s", settings["img_processor"])
            processor_cls = getattr(pilkit.processors, settings["img_processor"])
        except AttributeError:
            logger.error("Wrong processor name: %s", settings["img_processor"])
            sys.exit()

        processor = processor_cls(*settings["img_size"], upscale=False)
        img = processor.process(img)

    # Adjust the image after resizing
    img = Adjust(**settings["adjust_options"]).process(img)

    if settings["copyright"]:
        add_copyright(img, settings["copyright"])

    outformat = img.format or original_format or "JPEG"
    logger.debug(u"Save resized image to {0} ({1})".format(outname, outformat))
    save_image(img, outname, outformat, options=options, autoconvert=True)
def test_save_with_filename():
    """
    Test that ``save_image`` accepts filename strings (not just file objects).
    This is a test for GH-8.

    """
    im = create_image()
    outfile = NamedTemporaryFile()
    save_image(im, outfile.name, 'JPEG')
    outfile.close()
Exemple #11
0
def test_save_with_filename():
    """
    Test that ``save_image`` accepts filename strings (not just file objects).
    This is a test for GH-8.

    """
    im = create_image()
    outfile = NamedTemporaryFile()
    save_image(im, outfile.name, 'JPEG')
    outfile.close()
Exemple #12
0
def resize_image(path, output, side=360):
    w, h, img = calculate_size(path, side)
    if img.format.lower() == 'gif':
        resize_gif(path, output, w, h)
        return w, h

    processor = processors.SmartResize(w, h)
    new_img = processor.process(img)

    utils.save_image(new_img, output, img.format)
    return w, h
Exemple #13
0
def resize_image(path, output, side=360):
    w, h, img = calculate_size(path, side)
    if img.format.lower() == 'gif':
        resize_gif(path, output, w, h)
        return w, h

    processor = processors.SmartResize(w, h)
    new_img = processor.process(img)

    utils.save_image(new_img, output, img.format)
    return w, h
Exemple #14
0
def generate_image(source, outname, settings, options=None):
    """Image processor, rotate and resize the image.

    :param source: path to an image
    :param outname: output filename
    :param settings: settings dict
    :param options: dict with PIL options (quality, optimize, progressive)

    """

    logger = logging.getLogger(__name__)
    img = PILImage.open(source)
    original_format = img.format

    # Preserve EXIF data
    if settings['copy_exif_data'] and _has_exif_tags(img):
        if options is not None:
            options = deepcopy(options)
        else:
            options = {}
        options['exif'] = img.info['exif']

    # Rotate the img, and catch IOError when PIL fails to read EXIF
    try:
        img = Transpose().process(img)
    except (IOError, IndexError):
        pass

    # Resize the image
    if settings['img_processor']:
        try:
            logger.debug('Processor: %s', settings['img_processor'])
            processor_cls = getattr(pilkit.processors,
                                    settings['img_processor'])
        except AttributeError:
            logger.error('Wrong processor name: %s', settings['img_processor'])
            sys.exit()

        processor = processor_cls(*settings['img_size'], upscale=False)
        img = processor.process(img)

    # Adjust the image after resizing
    img = Adjust(**settings['adjust_options']).process(img)

    if settings['copyright']:
        add_copyright(img, settings['copyright'])

    outformat = img.format or original_format or 'JPEG'
    logger.debug(u'Save resized image to {0} ({1})'.format(outname, outformat))
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #15
0
def generate_image(source, outname, settings, options=None):
    """Image processor, rotate and resize the image.

    :param source: path to an image
    :param outname: output filename
    :param settings: settings dict
    :param options: dict with PIL options (quality, optimize, progressive)

    """

    logger = logging.getLogger(__name__)
    img = PILImage.open(source)
    original_format = img.format

    # Preserve EXIF data
    if settings['copy_exif_data'] and _has_exif_tags(img):
        if options is not None:
            options = deepcopy(options)
        else:
            options = {}
        options['exif'] = img.info['exif']

    # Rotate the img, and catch IOError when PIL fails to read EXIF
    try:
        img = Transpose().process(img)
    except (IOError, IndexError):
        pass

    # Resize the image
    if settings['img_processor']:
        try:
            logger.debug('Processor: %s', settings['img_processor'])
            processor_cls = getattr(pilkit.processors,
                                    settings['img_processor'])
        except AttributeError:
            logger.error('Wrong processor name: %s', settings['img_processor'])
            sys.exit()

        processor = processor_cls(*settings['img_size'], upscale=False)
        img = processor.process(img)

    # Adjust the image after resizing
    img = Adjust(**settings['adjust_options']).process(img)

    if settings['copyright']:
        add_copyright(img, settings['copyright'])

    outformat = img.format or original_format or 'JPEG'
    logger.debug(u'Save resized image to {0} ({1})'.format(outname, outformat))
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #16
0
def generate_thumbnail(source, outname, box, delay, fit=True, options=None):
    """Create a thumbnail image."""

    logger = logging.getLogger(__name__)
    img = PILImage.open(source)
    original_format = img.format

    if fit:
        img = ImageOps.fit(img, box, PILImage.ANTIALIAS)
    else:
        img.thumbnail(box, PILImage.ANTIALIAS)

    outformat = img.format or original_format or 'JPEG'
    logger.debug(u'Save thumnail image: {0} ({1})'.format(outname, outformat))
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #17
0
def generate_thumbnail(source, outname, box, fit=True, options=None):
    """Create a thumbnail image."""

    logger = logging.getLogger(__name__)
    img = PILImage.open(source)
    original_format = img.format

    if fit:
        img = ImageOps.fit(img, box, PILImage.ANTIALIAS)
    else:
        img.thumbnail(box, PILImage.ANTIALIAS)

    outformat = img.format or original_format or "JPEG"
    logger.debug(u"Save thumnail image: {0} ({1})".format(outname, outformat))
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #18
0
def generate_thumbnail(source, outname, box, fit=True, options=None):
    "Create a thumbnail image"

    logger = logging.getLogger(__name__)
    img = PILImage.open(source)
    original_format = img.format

    if fit:
        img = ImageOps.fit(img, box, PILImage.ANTIALIAS)
    else:
        img.thumbnail(box, PILImage.ANTIALIAS)

    outformat = img.format or original_format or 'JPEG'
    logger.debug(u'Save thumnail image to {0} ({1})'.format(outname, outformat))
    with open(outname, 'w') as fp:
        save_image(img, fp, outformat, options=options, autoconvert=True)
Exemple #19
0
def generate_image(source, outname, settings, options=None):
    """Image processor, rotate and resize the image.

    :param source: path to an image
    :param outname: output filename
    :param settings: settings dict
    :param options: dict with PIL options (quality, optimize, progressive)

    """

    logger = logging.getLogger(__name__)
    img = PILImage.open(source)
    original_format = img.format

    # Preserve EXIF data
    if settings["copy_exif_data"] and _has_exif_tags(img):
        options = options or {}
        options["exif"] = img.info["exif"]

    # Rotate the img, and catch IOError when PIL fails to read EXIF
    try:
        img = Transpose().process(img)
    except IOError:
        pass

    # Resize the image
    if settings["img_processor"]:
        try:
            logger.debug("Processor: %s", settings["img_processor"])
            processor_cls = getattr(pilkit.processors, settings["img_processor"])
        except AttributeError:
            logger.error("Wrong processor name: %s", settings["img_processor"])
            sys.exit()

        processor = processor_cls(*settings["img_size"], upscale=False)
        img = processor.process(img)

    # Adjust the image after resizing
    img = Adjust(**settings["adjust_options"]).process(img)

    if settings["copyright"]:
        add_copyright(img, settings["copyright"])

    outformat = img.format or original_format or "JPEG"
    logger.debug(u"Save resized image to {0} ({1})".format(outname, outformat))
    with open(outname, "w") as fp:
        save_image(img, fp, outformat, options=options, autoconvert=True)
Exemple #20
0
def generate_thumbnail(source, outname, box, fit=True, options=None,
                       thumb_fit_centering=(0.5, 0.5)):
    """Create a thumbnail image."""

    logger = logging.getLogger(__name__)
    img = _read_image(source)
    original_format = img.format

    if fit:
        img = ImageOps.fit(img, box, PILImage.ANTIALIAS,
                           centering=thumb_fit_centering)
    else:
        img.thumbnail(box, PILImage.ANTIALIAS)

    outformat = img.format or original_format or 'JPEG'
    logger.debug('Save thumnail image: %s (%s)', outname, outformat)
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #21
0
def generate_thumbnail(source, outname, box, fit=True, options=None,
                       thumb_fit_centering=(0.5, 0.5)):
    """Create a thumbnail image."""

    logger = logging.getLogger(__name__)
    img = _read_image(source)
    original_format = img.format

    if fit:
        img = ImageOps.fit(img, box, PILImage.ANTIALIAS,
                           centering=thumb_fit_centering)
    else:
        img.thumbnail(box, PILImage.ANTIALIAS)

    outformat = img.format or original_format or 'JPEG'
    logger.debug('Save thumnail image: %s (%s)', outname, outformat)
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #22
0
def generate_image(source, outname, settings, options=None):
    """Image processor, rotate and resize the image.

    :param source: path to an image
    :param outname: output filename
    :param settings: settings dict
    :param options: dict with PIL options (quality, optimize, progressive)

    """
    print(f'{source} => {outname}')

    logger = logging.getLogger(__name__)

    if settings['USE_ORIG'] or source.endswith('.gif'):
        utils.copy(source, outname, symlink=settings['ORIG_LINK'])
        return
    # print(f'read image {source}')
    img = _read_image(source)

    original_format = img.format

    if settings['COPY_EXIF_DATA'] and settings['autorotate_images']:
        logger.warning("The 'autorotate_images' and 'COPY_EXIF_DATA' settings "
                       "are not compatible because Sigal can't save the "
                       "modified Orientation tag.")

    # Preserve EXIF data
    if settings['COPY_EXIF_DATA'] and _has_exif_tags(img):
        if options is not None:
            options = deepcopy(options)
        else:
            options = {}
        options['exif'] = img.info['exif']

    # signal.send() does not work here as plugins can modify the image, so we
    # iterate other the receivers to call them with the image.
    # for receiver in signals.img_resized.receivers_for(img):
    #     img = receiver(img, settings=settings)

    # first, use hard-coded output format, or PIL format, or original image
    # format, or fall back to JPEG
    outformat = settings.get(
        'IMG_FORMAT') or img.format or original_format or 'JPEG'
    logger.debug('Save resized image to %s (%s)', outname, outformat)
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #23
0
def generate_thumbnail(source, outname, box, delay, fit=True, options=None):
    """Create a thumbnail image."""

    logger = logging.getLogger(__name__)
    with warnings.catch_warnings(record = True) as caught_warnings:
        img = PILImage.open(source)
        original_format = img.format

    _handle_caught_warnings(caught_warnings, source)

    if fit:
        img = ImageOps.fit(img, box, PILImage.ANTIALIAS)
    else:
        img.thumbnail(box, PILImage.ANTIALIAS)

    outformat = img.format or original_format or 'JPEG'
    logger.debug(u'Save thumnail image: {0} ({1})'.format(outname, outformat))
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #24
0
def resize_image(path, output, side=360):
    img = Image.open(path)
    ow, oh = img.size

    if ow > oh:
        h = int(float(side) / float(ow) * float(oh))
        w = side
    else:
        h = side
        w = int(float(side) / float(oh) * float(ow))

    if img.format.lower() == 'gif':
        resize_gif(path, output, w, h)
        return

    processor = processors.SmartResize(w, h)
    new_img = processor.process(img)

    utils.save_image(new_img, output, img.format)
Exemple #25
0
    def save(self, name, content, save=True, *args, **kwargs):
        crop_size = getattr(self.field, 'crop_size', None)
        if crop_size:
            width, height = crop_size
            processor = SmartCrop(width=width, height=height)
            with PILImage.open(content.file) as image:
                cropped_image = processor.process(image)
                path, ext = os.path.splitext(name)
                save_image(
                    cropped_image,
                    outfile=content.file,
                    format=get_format(ext),
                )

        super(CropMixin, self).save(name=name,
                                    content=content,
                                    save=save,
                                    *args,
                                    **kwargs)
Exemple #26
0
 def compress_img(self, img, quality=70):
     """
     Compress PIL image file to JPEG reducing quality
     :param img: PIL image file
     :param quality:
     :return:
     """
     tmpfile = TemporaryFile()
     return Image.open(
         save_image(img, tmpfile, 'JPEG', options={'quality': quality}))
Exemple #27
0
def generate_image(source, outname, size, format, options=None,
                   autoconvert=True, copyright_text='', method='ResizeToFit',
                   copy_exif_data=True):
    """Image processor, rotate and resize the image.

    :param source: path to an image
    :param options: dict with PIL options (quality, optimize, progressive)

    """

    logger = logging.getLogger(__name__)
    img = PILImage.open(source)
    original_format = img.format

    # Preserve EXIF data
    if copy_exif_data and hasattr(img, 'info') and 'exif' in img.info:
        options = options or {}
        options['exif'] = img.info['exif']

    # Rotate the img, and catch IOError when PIL fails to read EXIF
    try:
        img = Transpose().process(img)
    except IOError:
        pass

    # Resize the image
    try:
        logger.debug('Processor: %s', method)
        processor_cls = getattr(pilkit.processors, method)
    except AttributeError:
        logger.error('Wrong processor name: %s', method)
        sys.exit()

    processor = processor_cls(*size, upscale=False)
    img = processor.process(img)

    if copyright_text:
        add_copyright(img, copyright_text)

    format = format or img.format or original_format or 'JPEG'
    logger.debug(u'Save resized image to {0} ({1})'.format(outname, format))
    save_image(img, outname, format, options=options, autoconvert=autoconvert)
def process(image_url,  processor = None, width=None, height=None, resolution=None, quality=100):
    conn = S3Connection(settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY)
    bucket = conn.get_bucket(settings.AWS_STORAGE_BUCKET_NAME) 
    if image_url[0] =='/': image_url = image_url[1:] 
    r = requests.get(image_url.replace('https', 'http'))
    img = Image.open(StringIO(r.content))
    processor = ResizeToFit(width, height)
    new_img = processor.process(img)
    new_file = StringIO()
    save_image(new_img, new_file, 'JPEG')
    new_k = Key(bucket)
    parts = urlparse(image_url)
    img_name = os.path.splitext(os.path.basename(parts.path))[0]
    new_k.key = 'il/{}x{}/{}.jpeg'.format(width, height, img_name)
    new_k.content_type = 'image/jpeg'
    new_k.set_contents_from_file(new_file, policy='public-read')
    new_image_url = new_k.generate_url(0, query_auth=False, force_http=True)
    processed_image,_ = ProcessedImage.objects.update_or_create(source_image = image_url, processed_image = new_image_url)
    return processed_image
    
    
Exemple #29
0
def save_pilimage(image, path, storage):
    """Save a pil image using django storage system.

    As a PIL image does not inherit from django file class it can not be saved
    using django storage system. So we have to load the image content to a
    django file and the save it using django storage.

    Args:
        image: a PIL image to be saved in the host.
        path: a string that indicates the file path where the image should be
            saved.
        storage: a django storage instance.

    Returns:
        A string with the path of the stored file.
    """
    content = ContentFile(b'')
    save_image(image, outfile=content, format=get_format(path))
    name = storage.save(path, content)
    content.close()
    return name
Exemple #30
0
def generate_thumbnail(source, outname, box, skip, fit=False, options=None):
    """Create a thumbnail image."""

    logger = logging.getLogger(__name__)

    extension = os.path.splitext(source)[1]
    if extension in ('.cr2'):
        raw = rawpy.imread(source)
        img = PILImage.fromarray(raw.postprocess())
        original_format = "JPEG"
    else:
        img = PILImage.open(source)
        original_format = img.format

    if fit:
        img = ImageOps.fit(img, box, PILImage.ANTIALIAS)
    else:
        img.thumbnail(box, PILImage.ANTIALIAS)

    outformat = img.format or original_format or 'JPEG'
    logger.debug(u'Save thumnail image: {0} ({1})'.format(outname, outformat))
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #31
0
def generate_image(source, outname, settings, options=None):
    """Image processor, rotate and resize the image.

    :param source: path to an image
    :param outname: output filename
    :param settings: settings dict
    :param options: dict with PIL options (quality, optimize, progressive)

    """

    logger = logging.getLogger(__name__)

    if settings['use_orig'] or source.endswith('.gif'):
        utils.copy(source, outname, symlink=settings['orig_link'])
        return

    img = _read_image(source)
    original_format = img.format

    if settings['copy_exif_data'] and settings['autorotate_images']:
        logger.warning("The 'autorotate_images' and 'copy_exif_data' settings "
                       "are not compatible because Sigal can't save the "
                       "modified Orientation tag.")

    # Preserve EXIF data
    if settings['copy_exif_data'] and _has_exif_tags(img):
        if options is not None:
            options = deepcopy(options)
        else:
            options = {}
        options['exif'] = img.info['exif']

    # Rotate the img, and catch IOError when PIL fails to read EXIF
    if settings['autorotate_images']:
        try:
            img = Transpose().process(img)
        except (OSError, IndexError):
            pass

    # Resize the image
    if settings['img_processor']:
        try:
            logger.debug('Processor: %s', settings['img_processor'])
            processor_cls = getattr(pilkit.processors,
                                    settings['img_processor'])
        except AttributeError:
            logger.error('Wrong processor name: %s', settings['img_processor'])
            sys.exit()

        width, height = settings['img_size']

        if img.size[0] < img.size[1]:
            # swap target size if image is in portrait mode
            height, width = width, height

        processor = processor_cls(width, height, upscale=False)
        img = processor.process(img)

    # signal.send() does not work here as plugins can modify the image, so we
    # iterate other the receivers to call them with the image.
    for receiver in signals.img_resized.receivers_for(img):
        img = receiver(img, settings=settings)

    # first, use hard-coded output format, or PIL format, or original image
    # format, or fall back to JPEG
    outformat = (settings.get('img_format') or img.format or original_format
                 or 'JPEG')

    logger.debug('Save resized image to %s (%s)', outname, outformat)
    save_image(img, outname, outformat, options=options, autoconvert=True)
Exemple #32
0
 def _convert_to_jpg(self, image_path):
     base = os.path.splitext(image_path)[0]
     new_image_path = base + '.jpg'
     save_image(Image.open(image_path), new_image_path, 'JPEG')
     return new_image_path
Exemple #33
0
def generate_image(inpath, outpath, width=None, height=None, format=JPEG,
                   fill=False, upscale=True, anchor=None, quality=80,
                   bgcolor=None, progressive=True, force_cache=False,
                   placeholder_reason=None, placeholder_image_path=None):
    """Generate an image with the passed in settings
    This is used by :func:`resize` and is run outside of the Flask context.

    Args:
        inpath (str):
            Path to the image to generate a new image out of.
        outpath (str):
            Where the new image will end up.
        width (Optional[:class:`int`]):
            The width to use for the generated image.
        height (Optional[:class:`str`]):
            The height to use for the generated image.
        format (str):
            Format to convert into. Defaults to "JPEG".
        fill (bool):
            Fill the entire width and height that was specified if True,
            otherwise keep the original image dimensions. Defaults to False.
        upscale (bool):
            Whether or not to allow the image to become bigger than the
            original if the request width and/or height is bigger than its
            dimensions. Defaults to True.
        anchor (str):
            Deprecated since Flask-Resize 0.6.
        quality (int):
            Quality of the output image, if the format is JPEG. Defaults to 80.
        bgcolor (Optional[:class:`str`]):
            If specified this color will be used as background.
        progressive (bool):
            Whether to use progressive encoding or not when JPEG is the
            output format.
        force_cache (bool):
            Whether to force the function to always use the image cache. If
            false, will reaise a :class:`exc.StopImageGeneration` if the
            generated image would be the same as the original. Defaults to
            False.
        placeholder_reason (Optional[:class:`str`]):
            A text to show the user if the image path could not be found.
        placeholder_image_path (Optional[:class:`str`]):
            The path to the image to use as the background of the placeholder.

    Raises:
        :class:`exc.ImageNotFoundError`:
            If the source image cannot be found or is not a file.
        :class:`exc.StopImageGeneration`:
            If force_cache is False and if the image transformation would
            result in the same image as the original.

    Returns:
        PIL.Image:
            The generated image.
    """
    if anchor:
        warnings.warn(
            "anchor has been deprecated in Flask-Resize 0.6 and doesn't do anything to the image. Will be removed in 1.0.",
            DeprecationWarning
        )

    if not os.path.isfile(inpath):
        if placeholder_reason:
            img = create_placeholder_img(width, height, placeholder_reason,
                                         placeholder_image_path)
        else:
            raise exc.ImageNotFoundError(inpath)
    else:
        img = Image.open(inpath)

    original_width, original_height = img.size
    w = width or original_width
    h = height or original_height
    if not force_cache and format == _parse_format(inpath) and fill is False:
        if (w == original_width and h == original_height) or \
           (upscale is False and \
           (w >= original_width or h >= original_height)):
            if not placeholder_reason:
                raise exc.StopImageGeneration()

    processor_kwargs = dict(width=width, height=height, upscale=upscale)
    _mkdir_p(outpath.replace('\\','/').rpartition('/')[0])

    if fill:
        if bgcolor:
            mat_color = ImageColor.getrgb(parse_rgb(bgcolor))
        elif format == JPEG:
            mat_color = (255, 255, 255, 255)  # White
        else:
            mat_color = (0, 0, 0, 0)  # Transparent
        processor_kwargs['mat_color'] = mat_color  # Transparent

    processor = ResizeToFit(**processor_kwargs)
    img = processor.process(img)

    assert (not os.path.exists(outpath)), 'Path to save to already exists'

    options = {}
    if format == JPEG:
        options.update({'quality': int(quality), 'progressive': progressive})

    if bgcolor is not None:
        img = make_opaque(img, bgcolor)

    with open(outpath, 'wb') as outfile:
        save_image(img, outfile, format=format, options=options)
    return img
Exemple #34
0
    def make_derivatives(self, overwrite=False):
        """
        create derivative images
        """
        logger = logging.getLogger(sys._getframe().f_code.co_name)   
        try:
            thumbnail = self.thumbnail
        except AttributeError:
            pass
        else:
            if not overwrite:
                return False
        master_path = os.path.join(self.path, 'master.tif')
        master_image = Image.open(master_path)
        master_profile = master_image.info.get('icc_profile')

        # make and save "maximum" image, a jpeg same resolution as the master
        maximum_image = master_image.copy()
        maximum_path = os.path.join(self.path, 'maximum.jpg')
        try:
            save_image(maximum_image, maximum_path, 'JPEG', options={'optimize':True, 'progressive':False, 'quality':95, 'icc_profile':master_profile})
        except IOError:
            save_image(preview_image, preview_path, 'JPEG', options={'optimize':True, 'progressive':False, 'icc_profile':master_profile})
        self.maximum = True
        maximum_hash = hash_of_file(maximum_path)
        self.__append_event__("Wrote derivative 'maximum' jpeg file on {0}".format(maximum_path))
        self.manifest.set('maximum.jpg', maximum_hash)
        del maximum_image # save RAM

        # make and save preview image
        # Note: the resampling algorithm that gives the highest quality result (bicubic)
        # is expensive in terms of compute time, and that expense is proportional to the
        # size of the original image and the relative size of the target image. 
        # Consequently, if the starting image is significantly larger than the desired 
        # down-sampled image, we'll make a first pass with the much less expensive 
        # "nearest neighbor" resampling algorithm to get an image that is only twice the
        # size of the target, then use "bicubic" on it to get the desired outcome. The
        # wisdom of the Internet seems to point to this as a time-saving step that 
        # sacrifices little or nothing in quality. Caveat lector. Of course, if we 
        # really wanted to do this fast, we'd write it in C.
        preview_image = master_image.copy()
        del master_image # save RAM
        size = preview_image.size
        logger.debug("master size: {0}, {1}".format(size[0], size[1]))
        if size[0] > 3* SIZEPREVIEW[0] or size[1] > 3* SIZEPREVIEW[1]:
            preview_image.thumbnail(tuple(s*2 for s in SIZEPREVIEW), Image.NEAREST)
            logger.debug("did nearest pre-shrink for preview, resulting size: {0}, {1}".format(preview_image.size[0], preview_image.size[1]))
        preview_image.thumbnail(SIZEPREVIEW)
        logger.debug("resulting preview size: {0}, {1}".format(preview_image.size[0], preview_image.size[1]))
        preview_path = os.path.join(self.path, 'preview.jpg')
        try:
            save_image(preview_image, preview_path, 'JPEG', options={'optimize':True, 'progressive':True, 'quality':80, 'icc_profile':master_profile})
        except IOError:
            save_image(preview_image, preview_path, 'JPEG', options={'optimize':True, 'progressive':True, 'icc_profile':master_profile})
            logger.warning("preview image could not be written at quality 80; using defaults")
        self.preview = True
        preview_hash = hash_of_file(preview_path)
        self.__append_event__("wrote derivative 'preview' jpeg file on {0}".format(preview_path))
        self.manifest.set('preview.jpg', preview_hash)

        # make and save thumbnail image
        # Note: use the same approach as above, but start with the preview image, which
        # is surely much smaller than the master.
        thumbnail_image = preview_image.copy()
        del preview_image # save the RAMs!
        thumbnail_image.thumbnail(SIZETHUMB)
        thumbnail_path = os.path.join(self.path, 'thumb.jpg')
        try:
            save_image(thumbnail_image, thumbnail_path, 'JPEG', options={'optimize':True, 'progressive':True, 'quality':80, 'icc_profile':master_profile})
        except IOError:
            save_image(thumbnail_image, thumbnail_path, 'JPEG', options={'optimize':True, 'progressive':True, 'icc_profile':master_profile})
            logger.warning("preview image could not be written at quality 80; using defaults")
        self.thumbnail = True
        thumbnail_hash = hash_of_file(thumbnail_path)
        self.__append_event__("wrote derivative 'thumbnail' jpeg file on {0}".format(thumbnail_path))
        self.manifest.set('thumb.jpg', thumbnail_hash)

        del thumbnail_image # probably not necessary to save the RAM here cuz gc will get it but anyway...
        return True
Exemple #35
0
    def make_derivatives(self, overwrite=False):
        """
        create derivative images
        """
        logger = logging.getLogger(sys._getframe().f_code.co_name)
        try:
            thumbnail = self.thumbnail
        except AttributeError:
            pass
        else:
            if not overwrite:
                return False
        master_path = os.path.join(self.path, 'master.tif')
        master_image = Image.open(master_path)
        master_profile = master_image.info.get('icc_profile')

        # make and save "maximum" image, a jpeg same resolution as the master
        maximum_image = master_image.copy()
        maximum_path = os.path.join(self.path, 'maximum.jpg')
        try:
            save_image(maximum_image,
                       maximum_path,
                       'JPEG',
                       options={
                           'optimize': True,
                           'progressive': False,
                           'quality': 95,
                           'icc_profile': master_profile
                       })
        except IOError:
            save_image(preview_image,
                       preview_path,
                       'JPEG',
                       options={
                           'optimize': True,
                           'progressive': False,
                           'icc_profile': master_profile
                       })
        self.maximum = True
        maximum_hash = hash_of_file(maximum_path)
        self.__append_event__(
            "Wrote derivative 'maximum' jpeg file on {0}".format(maximum_path))
        self.manifest.set('maximum.jpg', maximum_hash)
        del maximum_image  # save RAM

        # make and save preview image
        # Note: the resampling algorithm that gives the highest quality result (bicubic)
        # is expensive in terms of compute time, and that expense is proportional to the
        # size of the original image and the relative size of the target image.
        # Consequently, if the starting image is significantly larger than the desired
        # down-sampled image, we'll make a first pass with the much less expensive
        # "nearest neighbor" resampling algorithm to get an image that is only twice the
        # size of the target, then use "bicubic" on it to get the desired outcome. The
        # wisdom of the Internet seems to point to this as a time-saving step that
        # sacrifices little or nothing in quality. Caveat lector. Of course, if we
        # really wanted to do this fast, we'd write it in C.
        preview_image = master_image.copy()
        del master_image  # save RAM
        size = preview_image.size
        logger.debug("master size: {0}, {1}".format(size[0], size[1]))
        if size[0] > 3 * SIZEPREVIEW[0] or size[1] > 3 * SIZEPREVIEW[1]:
            preview_image.thumbnail(tuple(s * 2 for s in SIZEPREVIEW),
                                    Image.NEAREST)
            logger.debug(
                "did nearest pre-shrink for preview, resulting size: {0}, {1}".
                format(preview_image.size[0], preview_image.size[1]))
        preview_image.thumbnail(SIZEPREVIEW)
        logger.debug("resulting preview size: {0}, {1}".format(
            preview_image.size[0], preview_image.size[1]))
        preview_path = os.path.join(self.path, 'preview.jpg')
        try:
            save_image(preview_image,
                       preview_path,
                       'JPEG',
                       options={
                           'optimize': True,
                           'progressive': True,
                           'quality': 80,
                           'icc_profile': master_profile
                       })
        except IOError:
            save_image(preview_image,
                       preview_path,
                       'JPEG',
                       options={
                           'optimize': True,
                           'progressive': True,
                           'icc_profile': master_profile
                       })
            logger.warning(
                "preview image could not be written at quality 80; using defaults"
            )
        self.preview = True
        preview_hash = hash_of_file(preview_path)
        self.__append_event__(
            "wrote derivative 'preview' jpeg file on {0}".format(preview_path))
        self.manifest.set('preview.jpg', preview_hash)

        # make and save thumbnail image
        # Note: use the same approach as above, but start with the preview image, which
        # is surely much smaller than the master.
        thumbnail_image = preview_image.copy()
        del preview_image  # save the RAMs!
        thumbnail_image.thumbnail(SIZETHUMB)
        thumbnail_path = os.path.join(self.path, 'thumb.jpg')
        try:
            save_image(thumbnail_image,
                       thumbnail_path,
                       'JPEG',
                       options={
                           'optimize': True,
                           'progressive': True,
                           'quality': 80,
                           'icc_profile': master_profile
                       })
        except IOError:
            save_image(thumbnail_image,
                       thumbnail_path,
                       'JPEG',
                       options={
                           'optimize': True,
                           'progressive': True,
                           'icc_profile': master_profile
                       })
            logger.warning(
                "preview image could not be written at quality 80; using defaults"
            )
        self.thumbnail = True
        thumbnail_hash = hash_of_file(thumbnail_path)
        self.__append_event__(
            "wrote derivative 'thumbnail' jpeg file on {0}".format(
                thumbnail_path))
        self.manifest.set('thumb.jpg', thumbnail_hash)

        del thumbnail_image  # probably not necessary to save the RAM here cuz gc will get it but anyway...
        return True