Exemplo n.º 1
0
def optimize_from_buffer(data):
    """Optimize an image that has not been saved to a file."""
    # NOTE: this optional setting defines image file extensions that should
    # be ignored during optimization. If it is not set or is set to an
    # empty list, all file types will be optimized.
    IGNORED_EXTENSIONS = getattr(settings, 'OPTIMIZED_IMAGE_IGNORE_EXTENSIONS', [])
    if not is_testing_mode():
        base_extension = data.name.split('.')[-1]

        # If this file's extension is in the list of file extensions
        # that should be ignored, just return the data unmodified,
        # the same as we do if ``is_testing_mode()`` is True.
        if base_extension.lower() in [ext.lower() for ext in IGNORED_EXTENSIONS]:
            return data

        if settings.OPTIMIZED_IMAGE_METHOD == 'pillow':
            image = Image.open(data)
            bytes_io = BytesIO()
            if base_extension.lower() != 'jpg':
                extension = base_extension.upper()
            else:
                extension = 'JPEG'
            image.save(bytes_io, format=extension, optimize=True)
            data.seek(0)
            data.file.write(bytes_io.getvalue())
            data.file.truncate()
        elif settings.OPTIMIZED_IMAGE_METHOD == 'tinypng':
            tinify.key = settings.TINYPNG_KEY
            optimized_buffer = tinify.from_buffer(data.file.read()).to_buffer()
            data.seek(0)
            data.file.write(optimized_buffer)
            data.file.truncate()
    return data
Exemplo n.º 2
0
def save_image():
    if "image" not in request.files:
        return jsonify({"error": "No file passed to server"}), 400

    file = request.files["image"]
    if not file.filename:
        return jsonify({"error": "File must have a filename"}), 400

    # Validate account
    try:
        account_id = request.form.get("account")
        account = PostAccount.get_account(account_id)
    except ValueError as e:
        return jsonify({"error": str(e)}), 400

    # if request.args.original:
    #     s3.upload_fileobj(file, "penn.mobile.portal/images/{}".format(account.name), file.filename)

    source_data = file.read()
    resized_image = tinify.from_buffer(source_data).resize(method="cover", width=600, height=300)
    aws_url = resized_image.store(
        service="s3",
        aws_access_key_id=os.environ.get("AWS_KEY"),
        aws_secret_access_key=os.environ.get("AWS_SECRET"),
        region="us-east-1",
        path="penn.mobile.portal/images/{}/{}".format(account.name, file.filename)
    ).location

    return jsonify({"image_url": aws_url})
Exemplo n.º 3
0
def buffer_tinyfy(source_data):
    """source_data=source.read()"""
    try:
        # Use the Tinify API client.
        result_data = tinify.from_buffer(source_data).to_buffer()
    except tinify.AccountError as e:
        # print("The error message is: %s" % e.message)
        # Verify your API key and account limit.
        logging.warning(traceback.format_exc())
    except tinify.ClientError as e:
        # Check your source image and request options.
        logging.warning(traceback.format_exc())
    except tinify.ServerError as e:
        # Temporary issue with the Tinify API.
        logging.warning(traceback.format_exc())
    except tinify.ConnectionError as e:
        # A network connection error occurred.
        logging.warning(traceback.format_exc())
    except Exception as e:
        # Something else went wrong, unrelated to the Tinify API.
        logging.warning(traceback.format_exc())
    else:
        compressions_this_month = tinify.compression_count
        logging.info("this month tinyfy: %s, left: %s",
                     compressions_this_month, 500 - compressions_this_month)
        if compressions_this_month < 100:
            logging.warning("this month tinyfy: %s, left: %s",
                            compressions_this_month,
                            500 - compressions_this_month)
        return result_data

    return source_data
Exemplo n.º 4
0
def shrinkImageFromData(data, filename, settings={}):
    _, extension = os.path.splitext(filename)
    extension = extension.lower()
    api_key = getattr(django_settings, 'TINYPNG_API_KEY', None)
    if not api_key or extension not in ['.png', '.jpg', '.jpeg']:
        return dataToImageFile(data)
    tinify.key = api_key
    source = tinify.from_buffer(data)
    if settings.get('resize', None) == 'fit':
        image = Image.open(cStringIO.StringIO(data))
        max_width = settings.get('max_width', django_settings.MAX_WIDTH)
        max_height = settings.get('max_height', django_settings.MAX_HEIGHT)
        min_width = settings.get('min_width', django_settings.MIN_WIDTH)
        min_height = settings.get('min_height', django_settings.MIN_HEIGHT)
        width, height = image.size
        if width > max_width:
            height = (max_width / width) * height
            width = max_width
        if height > max_height:
            width = (max_height / height) * width
            height = max_height
        if height < min_height:
            height = min_height
        if width < min_width:
            width = min_width
        source = source.resize(
            method='fit',
            width=int(width),
            height=int(height),
        )
    elif settings.get('resize', None) == 'cover':
        source = source.resize(
            method='cover',
            width=settings.get('width', 300),
            height=settings.get('height', 300),
        )
    try:
        data = source.to_buffer()
    except:  # Retry without resizing
        try:
            data = tinify.from_buffer(data).to_buffer()
        except:  # Just return the original data
            pass
    return dataToImageFile(data)
Exemplo n.º 5
0
def shrinkImageFromData(data, filename, resize=None):
    _, extension = os.path.splitext(filename)
    extension = extension.lower()
    api_key = getattr(django_settings, 'TINYPNG_API_KEY', None)
    if not api_key or extension not in ['.png', '.jpg', '.jpeg']:
        return dataToImageFile(data)
    tinify.key = api_key
    source = tinify.from_buffer(data)
    if resize == 'fit':
        image = Image.open(cStringIO.StringIO(data))
        width, height = image.size
        if width > django_settings.MAX_WIDTH:
            height = (django_settings.MAX_WIDTH / width) * height
            width = django_settings.MAX_WIDTH
        if height > django_settings.MAX_HEIGHT:
            width = (django_settings.MAX_HEIGHT / height) * width
            height = django_settings.MAX_HEIGHT
        if height < django_settings.MIN_HEIGHT:
            height = django_settings.MIN_HEIGHT
        if width < django_settings.MIN_WIDTH:
            width = django_settings.MIN_WIDTH
        source = source.resize(
            method='fit',
            width=int(width),
            height=int(height),
        )
    elif resize == 'cover':
        print 'resize cover'
        source = source.resize(
            method='cover',
            width=300,
            height=300,
        )
    try:
        data = source.to_buffer()
    except:  # Retry without resizing
        try:
            data = tinify.from_buffer(data).to_buffer()
        except:  # Just return the original data
            pass
    return dataToImageFile(data)
Exemplo n.º 6
0
def optimize(data):
    """ Compress an image using the API offered by TinyPNG """
    try:
        optimized_data = tinify.from_buffer(data).to_buffer()
        return optimized_data
    except tinify.AccountError as e:
        # This exception may rise, since a Free account is being used (only 500 requests/month)
        logger.error("There is a problem with the TinyPNG Account: {0}".format(e))
    except tinify.ServerError as e:
        logger.error("There seem to be problems in the compression server: {0}".format(e))
    except Exception as e:
        logger.error("The image could not be compressed: {0}".format(e))
    finally:
        return data
Exemplo n.º 7
0
def optimize_from_buffer(data):
    """Optimize an image that has not been saved to a file."""
    # NOTE: this optional setting defines image file extensions that should
    # be ignored during optimization. If it is not set or is set to an
    # empty list, all file types will be optimized.
    IGNORED_EXTENSIONS = getattr(settings, 'OPTIMIZED_IMAGE_IGNORE_EXTENSIONS',
                                 [])
    if not is_testing_mode():
        base_extension = data.name.split('.')[-1]

        # If this file's extension is in the list of file extensions
        # that should be ignored, just return the data unmodified,
        # the same as we do if ``is_testing_mode()`` is True.
        if base_extension.lower() in [
                ext.lower() for ext in IGNORED_EXTENSIONS
        ]:
            return data

        if settings.OPTIMIZED_IMAGE_METHOD == 'pillow':
            image = Image.open(data)
            bytes_io = BytesIO()
            if base_extension.lower() != 'jpg':
                extension = base_extension.upper()
            else:
                extension = 'JPEG'
            image.save(bytes_io, format=extension, optimize=True)
            data.seek(0)
            data.file.write(bytes_io.getvalue())
            data.file.truncate()
        elif settings.OPTIMIZED_IMAGE_METHOD == 'tinypng':
            tinify.key = settings.TINYPNG_KEY
            optimized_buffer = tinify.from_buffer(data.file.read()).to_buffer()
            data.seek(0)
            data.file.write(optimized_buffer)
            data.file.truncate()
        elif settings.OPTIMIZED_IMAGE_METHOD == 'justtesting':
            # Make a tiny image and use that instead of the input image.
            # (justtesting is NOT a publicly allowed value, it's just for internal testing.)
            bytes_io = BytesIO()
            Image.new('RGB', (10, 10), "blue").save(bytes_io, format="JPEG")
            data.seek(0)
            data.file.write(bytes_io.getvalue())
            data.file.truncate()
        # Else - just don't change it
        else:
            return data

        # We optimized it - fix the computed size
        data.size = data.file.tell()
    return data
Exemplo n.º 8
0
def post_tinyjpg(source, db):
    try:
        get_key = api_keys.query.filter(api_keys.counter < 500).first()
        tinify.key = get_key.key
    except Exception:
        new_api_key(db)
        get_key = api_keys.query.filter(api_keys.counter == 0).first()
        tinify.key = get_key.key
    source_data = source.read()
    result_data = tinify.from_buffer(source_data).to_buffer()
    get_key.counter = get_key.counter + 1
    db.session.commit()
    response = io.BytesIO(result_data)
    response.filename = source.filename
    return response
Exemplo n.º 9
0
 def compressTinypng(cls, filePath):
     """
     使用tinypng对图片进行压缩
     :param filePath 待压缩的文件路径
     :rtype: 压缩后的文件内容
     """
     try:
         import tinify
         tinify.key = 'J2N7fcrkRwEdPe2LEjfOS6dINwTOeLJj'
         with open(filePath, 'rb') as f:
             buffer = f.read()
             result = tinify.from_buffer(buffer).to_buffer()
             print('成功压缩图片: ' + filePath)
             return result
     except Exception as e:
         return False
Exemplo n.º 10
0
 def compress_tiny_png(cls, file_path):
     """
     使用tinypng对图片进行压缩
     :param file_path 待压缩的文件路径
     :rtype: 压缩后的文件内容
     """
     try:
         import tinify
         key = Config.get_compress_config(ConfigName.COMPRESS_TINIFY_KEY)
         if not key:
             return False
         tinify.key = key
         with open(file_path, 'rb') as f:
             buffer = f.read()
             result = tinify.from_buffer(buffer).to_buffer()
             return result
     except Exception as e:
         return False
Exemplo n.º 11
0
def compressing_image_overwrite_source_file(source_picture_file_location):
    '''
    传入一个图片的地址,图片经过压缩后,覆盖原来的图片文件
    '''
    tinify.key = _load_tinyPNG_api_key()
    try:
        with open(source_picture_file_location, 'rb') as source:
            source_data = source.read()
            result_data = tinify.from_buffer(source_data).to_buffer()

        with open(source_picture_file_location, "wb") as source:
            source.write(result_data)
    except:
        try:
            compressing_image_overwrite_source_file(
                source_picture_file_location)
        except:
            return
Exemplo n.º 12
0
def image_optimizer(image_data):
    """Optimize an image that has not been saved to a file."""
    if OPTIMIZED_IMAGE_METHOD == 'pillow':
        image = Image.open(image_data)
        bytes_io = BytesIO()
        extension = image.format
        image.save(bytes_io, format=extension, optimize=True)
        image_data.seek(0)
        image_data.file.write(bytes_io.getvalue())
        image_data.file.truncate()
    elif OPTIMIZED_IMAGE_METHOD == 'tinypng':
        # disable warning info
        requests.packages.urllib3.disable_warnings()

        tinify.key = TINYPNG_KEY
        optimized_buffer = tinify.from_buffer(
            image_data.file.read()).to_buffer()
        image_data.seek(0)
        image_data.file.write(optimized_buffer)
        image_data.file.truncate()
    return image_data
Exemplo n.º 13
0
def optimize_from_buffer(data):
    """Optimize an image that has not been saved to a file."""
    if not is_testing_mode():
        if settings.OPTIMIZED_IMAGE_METHOD == 'pillow':
            image = Image.open(data)
            bytes_io = BytesIO()
            if data.name.split('.')[-1].lower() != 'jpg':
                extension = data.name.split('.')[-1].upper()
            else:
                extension = 'JPEG'
            image.save(bytes_io, format=extension, optimize=True)
            data.seek(0)
            data.file.write(bytes_io.getvalue())
            data.file.truncate()
        elif settings.OPTIMIZED_IMAGE_METHOD == 'tinypng':
            tinify.key = settings.TINYPNG_KEY
            optimized_buffer = tinify.from_buffer(data.file.read()).to_buffer()
            data.seek(0)
            data.file.write(optimized_buffer)
            data.file.truncate()
    return data
Exemplo n.º 14
0
def convert_for_product(product, old):
    # has original
    if not product.image_original:
        product.image_compressed = None
        return
    # make sure image has been changed
    if product.image_original == old.image_original and old.image_compressed_with_tinypng:
        return

    img = Image.open(product.image_original)
    bg_color = int(IMAGE_BACKGROUND_COLOR[1:3], base=16), int(IMAGE_BACKGROUND_COLOR[3:5], base=16), int(IMAGE_BACKGROUND_COLOR[5:7], base=16)
    img = remove_transparency(img, bg_color=bg_color)

    try:
        img_io = StringIO.StringIO()
        img.save(img_io, format='PNG')
        source = tinify.from_buffer(img_io.getvalue())
        data = source.to_buffer()
        img_content = ContentFile(data, product.image_original.name)
        product.image_compressed = img_content
        product.image_compressed_with_tinypng = True
    except tinify.Error:
        log.exception("Unable to use TinyPNG for image, fallback to server's algorithm")
        # This gives much more coarse results then TinyPNG
        # See API https://tinypng.com/developers/reference/python
        img_8bit = img.convert(
            mode='P',
            palette=Image.ADAPTIVE,
            colors=256,
        )
        img_io = StringIO.StringIO()
        img_8bit.save(
            img_io,
            format='PNG',
            optimize=True,
        )
        img_content = ContentFile(img_io.getvalue(), product.image_original.name)
        product.image_compressed = img_content
        product.image_compressed_with_tinypng = False
Exemplo n.º 15
0
import tinify
import os
import os.path

tinify.key = "your AppKey" # AppKey
fromFilePath = "/Users/tangjr/Desktop/test1" # 源路径
toFilePath = "/Users/tangjr/Desktop/test2" # 输出路径

for root, dirs, files in os.walk(fromFilePath):
	for name in files:
		fileName, fileSuffix = os.path.splitext(name)
		if fileSuffix == '.png' or fileSuffix == '.jpg':
			toFullPath = toFilePath + root[len(fromFilePath):]
			toFullName = toFullPath + '/' + name

			if os.path.isdir(toFullPath):
				pass
			else:
				os.mkdir(toFullPath)
			
			with open(toFullName, 'rb') as source:
			    source_data = source.read()
			    result_data = tinify.from_buffer(source_data).to_buffer()
Exemplo n.º 16
0
def optimize_legacy_images_in_model_fields(list_of_models, verbosity=0):
    """
    Call this function to go through models and optimize images.

    This is best done after changing your model fields from ImageField to
    OptimizedImageField, and migrating the models. This function goes through
    the list_of_models in the params, finds all of their OptimizedImageFields,
    and optimizes the images in those fields. Note: there is a 500 image/month
    limit on a free TinyPNG API key, so use this function wisely.
    """
    for model in list_of_models:
        if verbosity == 1:
            sys.stdout.write('\nOptimizing for model: {}'.format(model))

        field_names_to_optimize = []
        for field in model._meta.get_fields():
            if type(field) == OptimizedImageField:
                field_names_to_optimize.append(field.attname)

        if verbosity == 1:
            sys.stdout.write('\nWill check the following fields: {}'.format(
                field_names_to_optimize))

        model_instances = model.objects.all()
        for model_instance in model_instances:
            for field_name in field_names_to_optimize:
                if verbosity == 1:
                    sys.stdout.write(
                        '\nChecking for instance id {} field {}'.format(
                            model_instance.pk, field_name))

                # If the instance's field has an image, optimize it
                image_file = getattr(model_instance, field_name)
                if image_file.name not in [None, '']:
                    if verbosity == 1:
                        sys.stdout.write('\nImage found. Optimizing.')

                    try:
                        # Use the OPTIMIZED_IMAGE_METHOD from settings to determine
                        # which way to optimize the image file.
                        if settings.OPTIMIZED_IMAGE_METHOD == 'pillow':
                            # Open the image
                            input_file = BytesIO(image_file.read())
                            image = Image.open(input_file)
                            output_file = BytesIO()
                            # Find the extension of the file to pass to PIL.Image.save()
                            if image_file.name.split('.')[-1].lower() != 'jpg':
                                extension = image_file.name.split(
                                    '.')[-1].upper()
                            else:
                                extension = 'JPEG'
                            # Optimize the image
                            image.save(output_file,
                                       format=extension,
                                       optimize=True)
                            # Save the image in place of the unoptimized one
                            content_file = ContentFile(output_file.getvalue())
                            image_name = os.path.relpath(
                                image_file.name, image_file.field.upload_to)
                            image_file.save(image_name, content_file)
                        elif settings.OPTIMIZED_IMAGE_METHOD == 'tinypng':
                            tinify.key = settings.TINYPNG_KEY
                            # Use TinyPNG to optimize the file from a buffer
                            optimized_buffer = tinify.from_buffer(
                                image_file.read()).to_buffer()
                            # Save the image in place of the unoptimized one
                            content_file = ContentFile(optimized_buffer)
                            image_name = os.path.relpath(
                                image_file.name, image_file.field.upload_to)
                            image_file.save(image_name, content_file)
                    except:
                        # If the optimization failed for any reason, write this
                        # to stdout.
                        sys.stdout.write(
                            '\nOptimization failed for {}.'.format(
                                image_file.name))

                    if verbosity == 1:
                        sys.stdout.write('\nOptimized and saved image.')
Exemplo n.º 17
0
 def test_should_return_source(self):
     httpretty.register_uri(httpretty.POST,
                            'https://api.tinify.com/shrink',
                            location='https://api.tinify.com/some/location')
     tinify.key = 'valid'
     self.assertIsInstance(tinify.from_buffer('png file'), tinify.Source)
 def make_compress_img(self, buffer_img, imgp):
     """压缩图片文件事件处理函数"""
     global APIKEY
     tinify.key = APIKEY
     tinify.from_buffer(buffer_img).to_file(imgp)
Exemplo n.º 19
0
 def load_buffer(self, buffer):
     self._tiny_ref = tinify.from_buffer(buffer.read())
Exemplo n.º 20
0
 def test_should_return_source(self):
     httpretty.register_uri(httpretty.POST, 'https://api.tinify.com/shrink',
         location='https://api.tinify.com/some/location')
     tinify.key = 'valid'
     self.assertIsInstance(tinify.from_buffer('png file'), tinify.Source)
Exemplo n.º 21
0
import tinify
import base64

with open("real.jpg", "rb") as imageFile:
    str = base64.b64encode(imageFile.read())
    print(str)

with open("real.jpg", 'rb') as source:
    source_data = source.read()
    result_data = tinify.from_buffer(source_data).to_buffer()
    print(result_data)
Exemplo n.º 22
0
def tinify_bake_io(img: bytes, resolution: int) -> bytes:
    source = tinify.from_buffer(img)
    if resolution > 0:
        return source.resize(method='scale', width=resolution).to_buffer()
    else:
        return source.to_buffer()
Exemplo n.º 23
0
def image_optimizer(image_data, output_size=None, resize_method=None):
    """Optimize an image that has not been saved to a file."""
    if OPTIMIZED_IMAGE_METHOD == 'pillow':
        image = Image.open(image_data)
        bytes_io = BytesIO()

        file_name = image_data.name
        extension = get_file_extension(file_name)

        # If output_size is set, resize the image with the selected
        # resize_method. 'thumbnail' is used by default
        if output_size is not None:

            if resize_method is None:
                pass

            elif resize_method is 'thumbnail':
                image = resizeimage.resize_thumbnail(image,
                                                     output_size,
                                                     resample=Image.LANCZOS)

            elif resize_method is 'cover':
                image = resizeimage.resize_cover(image,
                                                 output_size,
                                                 validate=False)

            else:
                raise Exception(
                    'optimized_image_resize_method misconfigured, it\'s value must be \'thumbnail\', \'cover\' or None'
                )

            output_image = Image.new('RGBA', output_size,
                                     BACKGROUND_TRANSPARENT)

            output_image_center = (int((output_size[0] - image.size[0]) / 2),
                                   int((output_size[1] - image.size[1]) / 2))

            output_image.paste(image, output_image_center)

        # If output_size is None the output_image would be the same as source
        else:
            output_image = image

        # If the file extension is JPEG, convert the output_image to RGB
        if extension == 'JPEG':
            output_image = output_image.convert("RGB")

        output_image.save(bytes_io, format=extension, optimize=True)

        image_data.seek(0)
        image_data.file.write(bytes_io.getvalue())
        image_data.file.truncate()

    elif OPTIMIZED_IMAGE_METHOD == 'tinypng':
        # disable warning info
        requests.packages.urllib3.disable_warnings()

        tinify.key = TINYPNG_KEY
        optimized_buffer = tinify.from_buffer(
            image_data.file.read()).to_buffer()
        image_data.seek(0)
        image_data.file.write(optimized_buffer)
        image_data.file.truncate()
    return image_data
Exemplo n.º 24
0
def optimize_legacy_images_in_model_fields(list_of_models, verbosity=0):
    """
    Call this function to go through models and optimize images.

    This is best done after changing your model fields from ImageField to
    OptimizedImageField, and migrating the models. This function goes through
    the list_of_models in the params, finds all of their OptimizedImageFields,
    and optimizes the images in those fields. Note: there is a 500 image/month
    limit on a free TinyPNG API key, so use this function wisely.
    """
    # NOTE: this optional setting defines image file extensions that should
    # be ignored during optimization. If it is not set or is set to an
    # empty list, all file types will be optimized.
    IGNORED_EXTENSIONS = getattr(settings, 'OPTIMIZED_IMAGE_IGNORE_EXTENSIONS', [])
    for model in list_of_models:
        if verbosity == 1:
            sys.stdout.write('\nOptimizing for model: {}'.format(model))

        field_names_to_optimize = []
        for field in model._meta.get_fields():
            if type(field) == OptimizedImageField:
                field_names_to_optimize.append(field.attname)

        if verbosity == 1:
            sys.stdout.write('\nWill check the following fields: {}'.format(field_names_to_optimize))

        model_instances = model.objects.all()
        for model_instance in model_instances:
            for field_name in field_names_to_optimize:
                if verbosity == 1:
                    sys.stdout.write('\nChecking for instance id {} field {}'.format(model_instance.pk, field_name))

                # If the instance's field has an image, optimize it
                image_file = getattr(model_instance, field_name)
                image_file_extension = image_file.name.split('.')[-1]

                # If the file extension is in the list of file extensions
                # that should be ignored for optimization, exit this iteration
                # of the inner ``for`` loop, skipping the file.
                if image_file_extension.lower() in [ext.lower() for ext in IGNORED_EXTENSIONS]:
                    sys.stdout.write(
                        '\nImage has extension {ext}. Ignoring.'.format(ext=image_file_extension)
                    )
                    continue

                if image_file.name not in [None, '']:
                    if verbosity == 1:
                        sys.stdout.write('\nImage found. Optimizing.')

                    try:
                        # Use the OPTIMIZED_IMAGE_METHOD from settings to determine
                        # which way to optimize the image file.
                        if settings.OPTIMIZED_IMAGE_METHOD == 'pillow':
                            # Open the image
                            input_file = BytesIO(image_file.read())
                            image = Image.open(input_file)
                            output_file = BytesIO()
                            # Find the extension of the file to pass to PIL.Image.save()
                            if image_file_extension.lower() != 'jpg':
                                extension = image_file_extension.upper()
                            else:
                                extension = 'JPEG'
                            # Optimize the image
                            image.save(output_file, format=extension, optimize=True)
                            # Save the image in place of the unoptimized one
                            content_file = ContentFile(output_file.getvalue())
                            image_name = os.path.relpath(image_file.name, image_file.field.upload_to)
                            image_file.save(image_name, content_file)
                        elif settings.OPTIMIZED_IMAGE_METHOD == 'tinypng':
                            tinify.key = settings.TINYPNG_KEY
                            # Use TinyPNG to optimize the file from a buffer
                            optimized_buffer = tinify.from_buffer(image_file.read()).to_buffer()
                            # Save the image in place of the unoptimized one
                            content_file = ContentFile(optimized_buffer)
                            image_name = os.path.relpath(image_file.name, image_file.field.upload_to)
                            image_file.save(image_name, content_file)
                    except:
                        # If the optimization failed for any reason, write this
                        # to stdout.
                        sys.stdout.write('\nOptimization failed for {}.'.format(image_file.name))

                    if verbosity == 1:
                        sys.stdout.write('\nOptimized and saved image.')
Exemplo n.º 25
0
def shrinkImageFromData(data, filename, settings={}):
    """
    Optimize images with TinyPNG
    """
    _, extension = os.path.splitext(filename)
    extension = extension.lower()
    api_key = getattr(django_settings, 'TINYPNG_API_KEY', None)
    if not api_key or extension not in ['.png', '.jpg', '.jpeg']:
        return dataToImageFile(data)
    tinify.key = api_key
    source = tinify.from_buffer(data)
    if settings.get('resize', None) == 'fit':
        image = Image.open(cStringIO.StringIO(data))
        max_width = settings.get('max_width', django_settings.MAX_WIDTH)
        max_height = settings.get('max_height', django_settings.MAX_HEIGHT)
        min_width = settings.get('min_width', django_settings.MIN_WIDTH)
        min_height = settings.get('min_height', django_settings.MIN_HEIGHT)
        width, height = image.size
        if width > max_width:
            height = (max_width / width) * height
            width = max_width
        if height > max_height:
            width = (max_height / height) * width
            height = max_height
        if height < min_height:
            height = min_height
        if width < min_width:
            width = min_width
        source = source.resize(
            method='fit',
            width=int(width),
            height=int(height),
        )
    elif settings.get('resize', None) == 'cover':
        source = source.resize(
            method='cover',
            width=settings.get('width', 300),
            height=settings.get('height', 300),
        )
    elif settings.get('resize', None) == 'scale':
        if settings.get('width', None):
            source = source.resize(
                method='scale',
                width=settings['width'],
            )
        if settings.get('height', None):
            source = source.resize(
                method='scale',
                height=settings['height'],
            )
    elif settings.get('resize', None) == 'thumb':
        source = source.resize(
            method='thumb',
            width=settings.get('width', 300),
            height=settings.get('height', 300),
        )
    try:
        data = source.to_buffer()
    except: # Retry without resizing
        try:
            data = tinify.from_buffer(data).to_buffer()
        except: # Just return the original data
            pass
    return dataToImageFile(data)
Exemplo n.º 26
0
def image_optimizer(image_data, output_size=None, resize_method=None):
    """
    Optimize an image that has not been saved to a file.
    :param `image_data` is image data, e.g from request.FILES['image']
    :param `output_size` is float pixel scale of image (width, height) or None, e.g: (400, 300)
    :param `resize_method` is string resize method, choices are: None, "thumbnail", or "cover".
    :return optimized image data.
    """
    if OPTIMIZED_IMAGE_METHOD == 'pillow':
        image = Image.open(image_data)
        bytes_io = BytesIO()

        extension = get_image_extension(image)

        # If output_size is set, resize the image with the selected
        # resize_method. 'thumbnail' is used by default
        if output_size is not None:

            if resize_method not in ('thumbnail', 'cover', None):
                message = 'optimized_image_resize_method misconfigured, it\'s value must be \'thumbnail\', \'cover\' or None'
                raise Exception(message)

            elif resize_method is 'thumbnail':
                image = resizeimage.resize_thumbnail(image,
                                                     output_size,
                                                     resample=Image.LANCZOS)

            elif resize_method is 'cover':
                image = resizeimage.resize_cover(image,
                                                 output_size,
                                                 validate=False)

            output_image = Image.new('RGBA', output_size,
                                     BACKGROUND_TRANSPARENT)
            output_image_center = (int((output_size[0] - image.size[0]) / 2),
                                   int((output_size[1] - image.size[1]) / 2))

            output_image.paste(image, output_image_center)

        else:
            # If output_size is None the output_image would be the same as source
            output_image = image

        # If the file extension is JPEG, convert the output_image to RGB
        if extension == 'JPEG':
            output_image = output_image.convert('RGB')

        output_image.save(bytes_io, format=extension, optimize=True)

        image_data.seek(0)
        image_data.file.write(bytes_io.getvalue())
        image_data.file.truncate()

    elif OPTIMIZED_IMAGE_METHOD == 'tinypng':
        # disable warning info
        requests.packages.urllib3.disable_warnings()

        # just info for people
        if any([output_size, resize_method]):
            message = '[django-image-optimizer] "output_size" and "resize_method" only for OPTIMIZED_IMAGE_METHOD="pillow"'
            logging.info(message)

        tinify.key = TINYPNG_KEY
        optimized_buffer = tinify.from_buffer(
            image_data.file.read()).to_buffer()
        image_data.seek(0)
        image_data.file.write(optimized_buffer)
        image_data.file.truncate()

    return image_data
Exemplo n.º 27
0
def optimize_legacy_images_in_model_fields(list_of_models, verbosity=0):
    """
    Call this function to go through models and optimize images.

    This is best done after changing your model fields from ImageField to
    OptimizedImageField, and migrating the models. This function goes through
    the list_of_models in the params, finds all of their OptimizedImageFields,
    and optimizes the images in those fields. Note: there is a 500 image/month
    limit on a free TinyPNG API key, so use this function wisely.
    """
    # NOTE: this optional setting defines image file extensions that should
    # be ignored during optimization. If it is not set or is set to an
    # empty list, all file types will be optimized.
    IGNORED_EXTENSIONS = getattr(settings, 'OPTIMIZED_IMAGE_IGNORE_EXTENSIONS',
                                 [])
    for model in list_of_models:
        if verbosity == 1:
            sys.stdout.write('\nOptimizing for model: {}'.format(model))

        field_names_to_optimize = []
        for field in model._meta.get_fields():
            if type(field) == OptimizedImageField:
                field_names_to_optimize.append(field.attname)

        if verbosity == 1:
            sys.stdout.write('\nWill check the following fields: {}'.format(
                field_names_to_optimize))

        model_instances = model.objects.all()
        for model_instance in model_instances:
            for field_name in field_names_to_optimize:
                if verbosity == 1:
                    sys.stdout.write(
                        '\nChecking for instance id {} field {}'.format(
                            model_instance.pk, field_name))

                # If the instance's field has an image, optimize it
                image_file = getattr(model_instance, field_name)
                if not image_file or not image_file.name:
                    continue
                image_file_extension = image_file.name.split('.')[-1]
                if not image_file_extension:
                    image_file_extension = "png"

                # If the file extension is in the list of file extensions
                # that should be ignored for optimization, exit this iteration
                # of the inner ``for`` loop, skipping the file.
                if image_file_extension.lower() in [
                        ext.lower() for ext in IGNORED_EXTENSIONS
                ]:
                    sys.stdout.write(
                        '\nImage has extension {ext}. Ignoring.'.format(
                            ext=image_file_extension))
                    continue

                if image_file.name not in [None, '']:
                    if verbosity == 1:
                        sys.stdout.write('\nImage found. Optimizing.')

                    try:
                        # Use the OPTIMIZED_IMAGE_METHOD from settings to determine
                        # which way to optimize the image file.
                        if settings.OPTIMIZED_IMAGE_METHOD == 'pillow':
                            # Open the image
                            input_file = BytesIO(image_file.read())
                            image = Image.open(input_file)
                            output_file = BytesIO()
                            # Find the extension of the file to pass to PIL.Image.save()
                            if image_file_extension.lower() != 'jpg':
                                extension = image_file_extension.upper()
                            else:
                                extension = 'JPEG'
                            # Optimize the image
                            image.save(output_file,
                                       format=extension,
                                       optimize=True)
                            # Save the image in place of the unoptimized one
                            content_file = ContentFile(output_file.getvalue())
                            image_name = os.path.relpath(image_file.name)
                            image_file.save(image_name, content_file)
                        elif settings.OPTIMIZED_IMAGE_METHOD == 'tinypng':
                            tinify.key = settings.TINYPNG_KEY
                            # Use TinyPNG to optimize the file from a buffer
                            optimized_buffer = tinify.from_buffer(
                                image_file.read()).to_buffer()
                            # Save the image in place of the unoptimized one
                            content_file = ContentFile(optimized_buffer)
                            image_name = os.path.relpath(image_file.name)
                            image_file.save(image_name, content_file)
                    except:
                        if is_testing_mode():
                            # This shouldn't actually happen, so if testing, let the exception continue
                            # up the call chain so it makes the test fail.
                            raise
                        # If the optimization failed for any reason, write this
                        # to stdout.
                        sys.stdout.write(
                            '\nOptimization failed for {}.'.format(
                                image_file.name))
                        sys.stdout.write(traceback.format_exc())

                    if verbosity == 1:
                        sys.stdout.write('\nOptimized and saved image.')