Пример #1
0
def put_highlight(image, highlight, resample_highlight, opacity, cache=None):
    if cache is None:
        cache = {}
    resample_highlight = getattr(Image, resample_highlight)
    id = 'highlight_%s_w%d_h%d_o%d'\
        % (highlight, image.size[0], image.size[1], opacity)
    try:
        highlight = cache[id]
    except KeyError:
        highlight = open_image(highlight)\
            .convert('RGBA').resize(image.size, resample_highlight)
        if opacity < 100:
            #apply opacity
            highlight_alpha = imtools.get_alpha(highlight)
            opacity = (255 * opacity) / 100
            highlight.putalpha(ImageMath.eval("convert((a * o) / 255, 'L')",
                a=highlight_alpha, o=opacity))
        #store in cache
        cache[id] = highlight
    if not has_transparency(image):
        image = image.convert('RGBA')
    else:
        if has_transparency(image):
            image = image.convert('RGBA')
        alpha = imtools.get_alpha(image)
        highlight = highlight.copy()
        highlight_alpha = imtools.get_alpha(highlight)
        highlight.putalpha(ImageMath.eval("convert(min(a, b), 'L')",
            a=alpha, b=highlight_alpha))

    overlay = highlight.convert('RGB')
    paste(image, overlay, mask=highlight)
    return image
Пример #2
0
def autocontrast(image, amount=100.0, cutoff=0):
    """Apply a filter
    - amount: 0-1
    - repeat: how many times it should be repeated"""
    image = imtools.convert_safe_mode(image)
    if imtools.has_transparency(image):
        im = imtools.remove_alpha(image)
    else:
        im = image
    contrasted = ImageOps.autocontrast(im, cutoff)
    if imtools.has_transparency(image):
        imtools.put_alpha(contrasted, imtools.get_alpha(image))
    if amount < 100:
        return imtools.blend(image, contrasted, amount / 100.0)
    return contrasted
Пример #3
0
def autocontrast(image, amount=100.0, cutoff=0):
    """Apply a filter
    - amount: 0-1
    - repeat: how many times it should be repeated"""
    image = imtools.convert_safe_mode(image)
    if imtools.has_transparency(image):
        im = imtools.remove_alpha(image)
    else:
        im = image
    contrasted = ImageOps.autocontrast(im, cutoff)
    if imtools.has_transparency(image):
        imtools.put_alpha(contrasted, imtools.get_alpha(image))
    if amount < 100:
        return imtools.blend(image, contrasted, amount / 100.0)
    return contrasted
Пример #4
0
def put_contour(image,
                size=1,
                offset=0,
                contour_color=0,
                fill_color=0,
                opacity=100,
                include_image=True):
    if not has_transparency(image):
        return put_border(image, size, offset, contour_color, fill_color,
                          opacity, include_image)
    image = image.convert('RGBA')
    mask = imtools.get_alpha(image)

    w, h = image.size
    outer_mask = mask.resize(
        (w + 2 * (size + offset), h + 2 * (size + offset)), Image.ANTIALIAS)

    inner_mask = mask.resize((w + 2 * offset, h + 2 * offset), Image.ANTIALIAS)
    inner_mask = ImageOps.expand(inner_mask, border=size, fill=0)
    paste(outer_mask, (255 * opacity) / 100, mask=inner_mask)
    if include_image:
        image = ImageOps.expand(image, border=size + offset, fill=(0, 0, 0, 0))
        mask = ImageOps.expand(mask, border=size + offset, fill=0)
        paste(outer_mask, 255, mask=mask)

    contour = ImageOps.colorize(outer_mask, (255, 255, 255), contour_color)
    paste(contour, fill_color, mask=inner_mask)
    if include_image:
        paste(contour, image, mask=image)
    contour.putalpha(outer_mask)
    return contour
Пример #5
0
def warmup(image, midtone, brighten, amount=100):
    """Apply a toning filter. Move the midtones to the desired
    color while preserving blacks and whites with optional mixing
    with original image - amount: 0-100%"""

    mode = image.mode
    info = image.info

    if image.mode != "L":
        im = imtools.convert(image, "L")
    else:
        im = image

    if image.mode != "RGBA" and imtools.has_transparency(image):
        image = imtools.convert(image, "RGBA")

    luma = imtools.convert(imtools.split(im)[0], "F")
    o = []
    m = ImageColor.getrgb(midtone)
    b = brighten / 600.0
    # Calculate channels separately
    for l in range(3):
        o.append(ImageMath.eval("m*(255-i)*i+i", i=luma, m=4 * ((m[l] / 255.0) - 0.5 + b) / 255.0).convert("L"))

    colorized = Image.merge("RGB", tuple(o))

    if imtools.has_alpha(image):
        imtools.put_alpha(colorized, imtools.get_alpha(image))

    if amount < 100:
        colorized = imtools.blend(image, colorized, amount / 100.0)

    return colorized
Пример #6
0
def put_contour(image, size=1, offset=0, contour_color=0, fill_color=0,
        opacity=100, include_image=True):
    if not has_transparency(image):
        return put_border(
                    image, size, offset, contour_color, fill_color,
                    opacity, include_image)
    image = image.convert('RGBA')
    mask = imtools.get_alpha(image)

    w, h = image.size
    outer_mask = mask.resize(
        (w + 2 * (size + offset), h + 2 * (size + offset)),
        Image.ANTIALIAS)

    inner_mask = mask.resize(
        (w + 2 * offset, h + 2 * offset),
        Image.ANTIALIAS)
    inner_mask = ImageOps.expand(inner_mask, border=size, fill=0)
    paste(outer_mask, (255 * opacity) / 100, mask=inner_mask)
    if include_image:
        image = ImageOps.expand(image, border=size + offset, fill=(0, 0, 0, 0))
        mask = ImageOps.expand(mask, border=size + offset, fill=0)
        paste(outer_mask, 255, mask=mask)

    contour = ImageOps.colorize(outer_mask, (255, 255, 255), contour_color)
    paste(contour, fill_color, mask=inner_mask)
    if include_image:
        paste(contour, image, mask=image)
    contour.putalpha(outer_mask)
    return contour
Пример #7
0
def mosaic(image, fill_type, fill_image, fill_folder, columns, rows,
        canvas_width, canvas_height):
    if has_transparency(image):
        image = image.convert('RGBA')
    else:
        image = image.convert('RGB')
    return _tamogen.mosaic(image, fill_type, columns, rows,
        canvas_width, canvas_height, fill_image, fill_folder)
Пример #8
0
def put_mask(image, mask, resample_mask, cache=None):
    if cache is None:
        cache = {}
    resample_mask = getattr(Image, resample_mask)
    id = mask + "_w%d_h%d" % image.size
    try:
        mask = cache[id]
    except KeyError:
        mask = cache[id] = open_image(mask).convert("L").resize(image.size, resample_mask)
    if not has_transparency(image):
        image = image.convert("RGBA")
    else:
        if has_transparency(image):
            image = image.convert("RGBA")
        alpha = imtools.get_alpha(image)
        mask = ImageMath.eval("convert(min(a, b), 'L')", a=alpha, b=mask)
    image.putalpha(mask)
    return image
Пример #9
0
def border(image,
           method,
           border_width=0,
           left=0,
           right=0,
           top=0,
           bottom=0,
           color=0,
           opacity=100):
    """

    """
    #set up sizes, and make the target img
    if method == OPTIONS[0]:
        left, right, top, bottom = (border_width, ) * 4
    else:
        left, right, top, bottom = [x for x in left, right, top, bottom]

    #new image size attributes could get really messed up by negatives...
    new_width = sum([x for x in image.size[0], left, right if x >= 0])
    new_height = sum([x for x in image.size[1], top, bottom if x >= 0])

    # only need to do conversions when preserving transparency, or when
    # dealing with transparent overlays
    negative = [x for x in left, right, top, bottom if x < 0]
    if (negative and (opacity < 100)) or has_transparency(image):
        new_image = Image.new('RGBA', (new_width, new_height), color)
    else:
        new_image = Image.new('RGB', (new_width, new_height), color)

    # now for the masking component. The size of the mask needs to be the size
    # of the original image, and totally opaque. then we will have draw in
    # negative border values with an opacity scaled appropriately.
    # NOTE: the technique here is that rotating the image allows me to do
    # this with one simple draw operation, no need to add and subtract and
    # otherwise introduce geometry errors
    if negative:
        #draw transparent overlays
        mask = Image.new('L', image.size, 255)
        drawcolor = int(255 - (opacity / 100.0 * 255))
        for val in left, top, right, bottom:
            if val < 0:
                mask_draw = ImageDraw.Draw(mask)
                mask_draw.rectangle((0, 0, abs(val), max(mask.size)),
                                    drawcolor)
                del mask_draw
            mask = mask.rotate(90)
    else:
        mask = None

    # negative paste position values mess with the result.
    left = max(left, 0)
    top = max(top, 0)
    paste(new_image, image, (left, top), mask)

    return new_image
Пример #10
0
def put_mask(image, mask, resample_mask, cache=None):
    if cache is None:
        cache = {}
    resample_mask = getattr(Image, resample_mask)
    id = mask + '_w%d_h%d' % image.size
    try:
        mask = cache[id]
    except KeyError:
        mask = cache[id] = open_image(mask).convert('L').resize(
            image.size, resample_mask)
    if not has_transparency(image):
        image = image.convert('RGBA')
    else:
        if has_transparency(image):
            image = image.convert('RGBA')
        alpha = imtools.get_alpha(image)
        mask = (ImageMath.eval("convert(min(a, b), 'L')", a=alpha, b=mask))
    image.putalpha(mask)
    return image
Пример #11
0
def reflect(image,
            depth,
            opacity,
            background_color,
            background_opacity,
            scale_method,
            gap=0,
            scale_reflection=False,
            blur_reflection=False,
            cache=None):
    if has_transparency(image):
        image = image.convert('RGBA')
    else:
        image = image.convert('RGB')
    if cache is None:
        cache = {}
    opacity = (255 * opacity) / 100
    background_opacity = (255 * background_opacity) / 100
    scale_method = getattr(Image, scale_method)
    if background_opacity == 255:
        mode = 'RGB'
        color = background_color
    else:
        mode = 'RGBA'
        color = HTMLColorToRGBA(background_color, background_opacity)
    width, height = image.size
    depth = min(height, depth)
    #make reflection
    if has_alpha(image) and background_opacity > 0:
        reflection = Image.new(mode, image.size, color)
        paste(reflection, image, (0, 0), image)
    else:
        reflection = image
    reflection = reflection.transpose(Image.FLIP_TOP_BOTTOM)
    if scale_reflection:
        reflection = reflection.resize((width, depth), scale_method)
    else:
        reflection = reflection.crop((0, 0, width, depth))
    if blur_reflection:
        reflection = reflection.filter(ImageFilter.BLUR)
    mask = gradient_mask((width, depth), opacity, cache)
    #composite
    total_size = (width, height + gap + depth)
    total = Image.new(mode, total_size, color)
    paste(total, image, (0, 0), image)
    paste(total, reflection, (0, height + gap), mask)
    return total
Пример #12
0
def background(image, fill, mark, color,
        horizontal_offset=None, vertical_offset=None,
        horizontal_justification=None, vertical_justification=None,
        orientation=None, method=None, opacity=100):
    if not has_transparency(image):
        return image
    if image.mode == 'P':
        image = image.convert('RGBA')
    if fill == FILL_CHOICES[0]:
        opacity = (255 * opacity) / 100
        return fill_background_color(image, HTMLColorToRGBA(color,
            opacity))
    elif fill == FILL_CHOICES[1]:
        layer = generate_layer(image.size, mark, method,
                               horizontal_offset, vertical_offset,
                               horizontal_justification,
                               vertical_justification,
                               orientation, opacity)
        paste(layer, image, mask=image)
        return layer
Пример #13
0
def reflect(image, depth, opacity, background_color, background_opacity,
        scale_method, gap=0, scale_reflection=False,
        blur_reflection=False, cache=None):
    if has_transparency(image):
        image = image.convert('RGBA')
    else:
        image = image.convert('RGB')
    if cache is None:
        cache = {}
    opacity = (255 * opacity) / 100
    background_opacity = (255 * background_opacity) / 100
    scale_method = getattr(Image, scale_method)
    if background_opacity == 255:
        mode = 'RGB'
        color = background_color
    else:
        mode = 'RGBA'
        color = HTMLColorToRGBA(background_color, background_opacity)
    width, height = image.size
    depth = min(height, depth)
    #make reflection
    if has_alpha(image) and background_opacity > 0:
        reflection = Image.new(mode, image.size, color)
        paste(reflection, image, (0, 0), image)
    else:
        reflection = image
    reflection = reflection.transpose(Image.FLIP_TOP_BOTTOM)
    if scale_reflection:
        reflection = reflection.resize((width, depth), scale_method)
    else:
        reflection = reflection.crop((0, 0, width, depth))
    if blur_reflection:
        reflection = reflection.filter(ImageFilter.BLUR)
    mask = gradient_mask((width, depth), opacity, cache)
    #composite
    total_size = (width, height + gap + depth)
    total = Image.new(mode, total_size, color)
    paste(total, image, (0, 0), image)
    paste(total, reflection, (0, height + gap), mask)
    return total
Пример #14
0
def warmup(image, midtone, brighten, amount=100):
    """Apply a toning filter. Move the midtones to the desired
    color while preserving blacks and whites with optional mixing
    with original image - amount: 0-100%"""

    mode = image.mode
    info = image.info

    if image.mode != 'L':
        im = imtools.convert(image, 'L')
    else:
        im = image

    if image.mode != 'RGBA' and imtools.has_transparency(image):
        image = imtools.convert(image, 'RGBA')

    luma = imtools.convert(imtools.split(im)[0], 'F')
    o = []
    m = ImageColor.getrgb(midtone)
    b = brighten / 600.0
    # Calculate channels separately
    for l in range(3):
        o.append(
            ImageMath.eval("m*(255-i)*i+i",
                           i=luma,
                           m=4 * ((m[l] / 255.0) - 0.5 + b) /
                           255.0).convert('L'))

    colorized = Image.merge('RGB', tuple(o))

    if imtools.has_alpha(image):
        imtools.put_alpha(colorized, imtools.get_alpha(image))

    if amount < 100:
        colorized = imtools.blend(image, colorized, amount / 100.0)

    return colorized
Пример #15
0
def background(image,
               fill,
               mark,
               color,
               horizontal_offset=None,
               vertical_offset=None,
               horizontal_justification=None,
               vertical_justification=None,
               orientation=None,
               method=None,
               opacity=100):
    if not has_transparency(image):
        return image
    if image.mode == 'P':
        image = image.convert('RGBA')
    if fill == FILL_CHOICES[0]:
        opacity = (255 * opacity) / 100
        return fill_background_color(image, HTMLColorToRGBA(color, opacity))
    elif fill == FILL_CHOICES[1]:
        layer = generate_layer(image.size, mark, method, horizontal_offset,
                               vertical_offset, horizontal_justification,
                               vertical_justification, orientation, opacity)
        paste(layer, image, mask=image)
        return layer
Пример #16
0
def border(image, method, border_width=0, left=0, right=0, top=0, bottom=0,
        color=0, opacity=100):
    """

    """
    #set up sizes, and make the target img
    if method == OPTIONS[0]:
        left, right, top, bottom = (border_width, ) * 4
    else:
        left, right, top, bottom = [x for x in left, right, top, bottom]

    #new image size attributes could get really messed up by negatives...
    new_width = sum([x for x in image.size[0], left, right if x >= 0])
    new_height = sum([x for x in image.size[1], top, bottom if x >= 0])

    # only need to do conversions when preserving transparency, or when
    # dealing with transparent overlays
    negative = [x for x in left, right, top, bottom if x < 0]
    if (negative and (opacity < 100)) or has_transparency(image):
        new_image = Image.new('RGBA', (new_width, new_height), color)
    else:
        new_image = Image.new('RGB', (new_width, new_height), color)

    # now for the masking component. The size of the mask needs to be the size
    # of the original image, and totally opaque. then we will have draw in
    # negative border values with an opacity scaled appropriately.
    # NOTE: the technique here is that rotating the image allows me to do
    # this with one simple draw operation, no need to add and subtract and
    # otherwise introduce geometry errors
    if negative:
        #draw transparent overlays
        mask = Image.new('L', image.size, 255)
        drawcolor = int(255 - (opacity / 100.0 * 255))
        for val in left, top, right, bottom:
            if val < 0:
                mask_draw = ImageDraw.Draw(mask)
                mask_draw.rectangle((0, 0, abs(val), max(mask.size)),
                    drawcolor)
                del mask_draw
            mask = mask.rotate(90)
    else:
        mask = None

    # negative paste position values mess with the result.
    left = max(left, 0)
    top = max(top, 0)
    paste(new_image, image, (left, top), mask)

    return new_image

#---Phatch
CHOICES = ['-25', '-10', '-5', '-1', '0', '1', '5', '10', '25']


class Action(models.Action):
    label = _t('Border')
    author = 'Erich'
    email = '*****@*****.**'
    init = staticmethod(init)
    pil = staticmethod(border)
    version = '0.2'
    tags = [_t('filter')]
    __doc__ = _t('Draw border inside or outside')

    def interface(self, fields):
        fields[_t('Method')] = self.ChoiceField(OPTIONS[0], choices=OPTIONS)
        fields[_t('Border Width')] = self.PixelField('1px', choices=CHOICES)
        fields[_t('Left')] = self.PixelField('0px', choices=CHOICES)
        fields[_t('Right')] = self.PixelField('0px', choices=CHOICES)
        fields[_t('Top')] = self.PixelField('0px', choices=CHOICES)
        fields[_t('Bottom')] = self.PixelField('0px', choices=CHOICES)
        fields[_t('Color')] = self.ColorField('#000000')
        fields[_t('Opacity')] = self.SliderField(100, 1, 100)

    def values(self, info):
        #pixel fields
        width, height = info['size']
        # pass absolute reference for relative pixel values such as %
        return super(Action, self).values(info, pixel_fields={
            'Border Width': (width + height) / 2,
            'Left': width,
            'Right': width,
            'Top': height,
            'Bottom': height,
        })

    def get_relevant_field_labels(self):
        """If this method is present, Phatch will only show relevant
        fields.
        :returns: list of the field labels which are relevant
        :rtype: list of strings
        .. note::
            It is very important that the list of labels has EXACTLY
            the same order as defined in the interface method.
        """
        relevant = ['Method', 'Color', 'Opacity']
        if self.get_field_string('Method') == OPTIONS[0]:
            relevant.append('Border Width')
        else:
            relevant.extend(['Left', 'Right', 'Top', 'Bottom'])
        return relevant

    icon = \
'x\xda\x01x\x0b\x87\xf4\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
Пример #17
0
def drop_shadow(image, horizontal_offset=5, vertical_offset=5,
        background_color=(255, 255, 255, 0), shadow_color=0x444444,
        border=8, shadow_blur=3, force_background_color=False, cache=None):
    """Add a gaussian blur drop shadow to an image.

    :param image: The image to overlay on top of the shadow.
    :param type: PIL Image
    :param offset:

        Offset of the shadow from the image as an (x,y) tuple.
        Can be positive or negative.

    :type offset: tuple of integers
    :param background_color: Background color behind the image.
    :param shadow_color: Shadow color (darkness).
    :param border:

        Width of the border around the image.  This must be wide
        enough to account for the blurring of the shadow.

    :param shadow_blur:

        Number of times to apply the filter.  More shadow_blur
        produce a more blurred shadow, but increase processing time.
    """
    if cache is None:
        cache = {}

    if has_transparency(image) and image.mode != 'RGBA':
        # Make sure 'LA' and 'P' with trasparency are handled
        image = image.convert('RGBA')

    #get info
    size = image.size
    mode = image.mode

    back = None

    #assert image is RGBA
    if mode != 'RGBA':
        if mode != 'RGB':
            image = image.convert('RGB')
            mode = 'RGB'
        #create cache id
        id = ''.join([str(x) for x in ['shadow_', size,
            horizontal_offset, vertical_offset, border, shadow_blur,
            background_color, shadow_color]])

        #look up in cache
        if id in cache:
            #retrieve from cache
            back, back_size = cache[id]

    if back is None:
        #size of backdrop
        back_size = (size[0] + abs(horizontal_offset) + 2 * border,
                        size[1] + abs(vertical_offset) + 2 * border)

        #create shadow mask
        if mode == 'RGBA':
            image_mask = imtools.get_alpha(image)
            shadow = Image.new('L', back_size, 0)
        else:
            image_mask = Image.new(mode, size, shadow_color)
            shadow = Image.new(mode, back_size, background_color)

        shadow_left = border + max(horizontal_offset, 0)
        shadow_top = border + max(vertical_offset, 0)
        paste(shadow, image_mask, (shadow_left, shadow_top,
                                shadow_left + size[0], shadow_top + size[1]))
        del image_mask  # free up memory

        #blur shadow mask

        #Apply the filter to blur the edges of the shadow.  Since a small
        #kernel is used, the filter must be applied repeatedly to get a decent
        #blur.
        n = 0
        while n < shadow_blur:
            shadow = shadow.filter(ImageFilter.BLUR)
            n += 1

        #create back
        if mode == 'RGBA':
            back = Image.new('RGBA', back_size, shadow_color)
            back.putalpha(shadow)
            del shadow  # free up memory
        else:
            back = shadow
            cache[id] = back, back_size

    #Paste the input image onto the shadow backdrop
    image_left = border - min(horizontal_offset, 0)
    image_top = border - min(vertical_offset, 0)
    if mode == 'RGBA':
        paste(back, image, (image_left, image_top), image)
        if force_background_color:
            mask = imtools.get_alpha(back)
            paste(back, Image.new('RGB', back.size, background_color),
                (0, 0), ImageChops.invert(mask))
            back.putalpha(mask)
    else:
        paste(back, image, (image_left, image_top))

    return back