Example #1
0
def scaleImage(image,
               width=None,
               height=None,
               direction='down',
               quality=88,
               result=None):
    """Scale the given image data to another size and return the result
    as a string or optionally write in to the file-like `result` object.

    The `image` parameter can either be the raw image data (ie a `str`
    instance) or an open file.

    The `quality` parameter can be used to set the quality of the
    resulting image scales.

    The return value is a tuple with the new image, the image format and
    a size-tuple.  Optionally a file-like object can be given as the
    `result` parameter, in which the generated image scale will be stored.

    The `width`, `height`, `direction` parameters will be passed to
    :meth:`scalePILImage`, which performs the actual scaling.

    The generated image is a JPEG image, unless the original is a PNG or GIF
    image. This is needed to make sure alpha channel information is
    not lost, which JPEG does not support.
    """
    if isinstance(image, (bytes, str)):
        image = StringIO(image)
    image = PIL.Image.open(image)
    # When we create a new image during scaling we loose the format
    # information, so remember it here.
    format_ = image.format
    if format_ not in ('PNG', 'GIF'):
        # Always generate JPEG, except if format is PNG or GIF.
        format_ = 'JPEG'
    elif format_ == 'GIF':
        # GIF scaled looks better if we have 8-bit alpha and no palette
        format_ = 'PNG'

    icc_profile = image.info.get('icc_profile')
    image = scalePILImage(image, width, height, direction)

    # convert to simpler mode if possible
    colors = image.getcolors(maxcolors=256)
    if image.mode not in ('P', 'L') and colors:
        if format_ == 'JPEG':
            # check if it's all grey
            if all(rgb[0] == rgb[1] == rgb[2] for c, rgb in colors):
                image = image.convert('L')
        elif format_ == 'PNG':
            image = image.convert('P')

    if image.mode == 'RGBA' and format_ == 'JPEG':
        extrema = dict(zip(image.getbands(), image.getextrema()))
        if extrema.get('A') == (255, 255):
            # no alpha used, just change the mode, which causes the alpha band
            # to be dropped on save
            image.mode = "RGB"
        else:
            # switch to PNG, which supports alpha
            format_ = 'PNG'

    new_result = False

    if result is None:
        result = StringIO()
        new_result = True

    image.save(result,
               format_,
               quality=quality,
               optimize=True,
               progressive=True,
               icc_profile=icc_profile)

    if new_result:
        result = result.getvalue()
    else:
        result.seek(0)

    return result, format_, image.size
Example #2
0
def scaleImage(image, width=None, height=None, direction='down',
               quality=88, result=None):
    """Scale the given image data to another size and return the result
    as a string or optionally write in to the file-like `result` object.

    The `image` parameter can either be the raw image data (ie a `str`
    instance) or an open file.

    The `quality` parameter can be used to set the quality of the
    resulting image scales.

    The return value is a tuple with the new image, the image format and
    a size-tuple.  Optionally a file-like object can be given as the
    `result` parameter, in which the generated image scale will be stored.

    The `width`, `height`, `direction` parameters will be passed to
    :meth:`scalePILImage`, which performs the actual scaling.

    The generated image is a JPEG image, unless the original is a PNG or GIF
    image. This is needed to make sure alpha channel information is
    not lost, which JPEG does not support.
    """
    if isinstance(image, (bytes, str)):
        image = StringIO(image)
    image = PIL.Image.open(image)
    # When we create a new image during scaling we loose the format
    # information, so remember it here.
    format_ = image.format
    if format_ not in ('PNG', 'GIF'):
        # Always generate JPEG, except if format is PNG or GIF.
        format_ = 'JPEG'
    elif format_ == 'GIF':
        # GIF scaled looks better if we have 8-bit alpha and no palette
        format_ = 'PNG'

    icc_profile = image.info.get('icc_profile')
    image = scalePILImage(image, width, height, direction)

    # convert to simpler mode if possible
    colors = image.getcolors(maxcolors=256)
    if image.mode not in ('P', 'L') and colors:
        if format_ == 'JPEG':
            # check if it's all grey
            if all(rgb[0] == rgb[1] == rgb[2] for c, rgb in colors):
                image = image.convert('L')
        elif format_ == 'PNG':
            image = image.convert('P')

    if image.mode == 'RGBA' and format_ == 'JPEG':
        extrema = dict(zip(image.getbands(), image.getextrema()))
        if extrema.get('A') == (255, 255):
            # no alpha used, just change the mode, which causes the alpha band
            # to be dropped on save
            image.mode = "RGB"
        else:
            # switch to PNG, which supports alpha
            format_ = 'PNG'

    new_result = False

    if result is None:
        result = StringIO()
        new_result = True

    image.save(
        result,
        format_,
        quality=quality,
        optimize=True,
        progressive=True,
        icc_profile=icc_profile
    )

    if new_result:
        result = result.getvalue()
    else:
        result.seek(0)

    return result, format_, image.size