Beispiel #1
0
def hue_rotate(im, deg=0):
    """Applies hue rotation.

    A hue rotate operation is equivalent to the following matrix operation:

        | R' |     | a00  a01  a02  0  0 |   | R |
        | G' |     | a10  a11  a12  0  0 |   | G |
        | B' |  =  | a20  a21  a22  0  0 | * | B |
        | A' |     | 0    0    0    1  0 |   | A |
        | 1  |     | 0    0    0    0  1 |   | 1 |

    where

        | a00 a01 a02 |    [+0.213 +0.715 +0.072]
        | a10 a11 a12 | =  [+0.213 +0.715 +0.072] +
        | a20 a21 a22 |    [+0.213 +0.715 +0.072]
                                [+0.787 -0.715 -0.072]
        cos(hueRotate value) *  [-0.213 +0.285 -0.072] +
                                [-0.213 -0.715 +0.928]
                                [-0.213 -0.715+0.928]
        sin(hueRotate value) *  [+0.143 +0.140-0.283]
                                [-0.787 +0.715+0.072]

    See the W3C document:
    https://www.w3.org/TR/SVG11/filters.html#feColorMatrixValuesAttribute

    Arguments:
        im: An input image.
        amount: An optional integer/float. The hue rotate value (degrees).
            Defaults to 0.

    Returns:
        The output image.
    """

    cos_hue = math.cos(deg * math.pi / 180)
    sin_hue = math.sin(deg * math.pi / 180)

    matrix = [
        .213 + cos_hue * .787 - sin_hue * .213,
        .715 - cos_hue * .715 - sin_hue * .715,
        .072 - cos_hue * .072 + sin_hue * .928,
        0,
        .213 - cos_hue * .213 + sin_hue * .143,
        .715 + cos_hue * .285 + sin_hue * .140,
        .072 - cos_hue * .072 - sin_hue * .283,
        0,
        .213 - cos_hue * .213 - sin_hue * .787,
        .715 - cos_hue * .715 + sin_hue * .715,
        .072 + cos_hue * .928 + sin_hue * .072,
        0,
    ]

    rotated = util.or_convert(im, 'RGB').convert('RGB', matrix)
    return util.or_convert(rotated, im.mode)
Beispiel #2
0
def brooklyn(im):
    """Applies Brooklyn filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs1 = util.fill(cb.size, [168, 223, 193, .4])
    cm1 = css.blending.overlay(cb, cs1)

    cs2 = util.fill(cb.size, [196, 183, 200])
    cm2 = css.blending.overlay(cb, cs2)

    gradient_mask = util.radial_gradient_mask(cb.size, length=.7)
    cr = Image.composite(cm1, cm2, gradient_mask)

    cr = css.contrast(cr, .9)
    cr = css.brightness(cr, 1.1)

    return cr
Beispiel #3
0
def nashville(im):
    """Applies Nashville filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs1 = util.fill(cb.size, [247, 176, 153])
    cm1 = ImageChops.darker(cb, cs1)
    cm1 = Image.blend(cb, cm1, .56)

    cs2 = util.fill(cb.size, [0, 70, 150])
    cm2 = ImageChops.lighter(cm1, cs2)
    cr = Image.blend(cm1, cm2, .4)

    cr = css.sepia(cr, .2)
    cr = css.contrast(cr, 1.2)
    cr = css.brightness(cr, 1.05)
    cr = css.saturate(cr, 1.2)

    return cr
Beispiel #4
0
def mayfair(im):
    """Applies Mayfair filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')
    size = cb.size
    pos = (.4, .4)

    cs1 = util.fill(size, [255, 255, 255, .8])
    cm1 = css.blending.overlay(cb, cs1)

    cs2 = util.fill(size, [255, 200, 200, .6])
    cm2 = css.blending.overlay(cb, cs2)

    cs3 = util.fill(size, [17, 17, 17])
    cm3 = css.blending.overlay(cb, cs3)

    mask1 = util.radial_gradient_mask(size, scale=.3, center=pos)
    cs = Image.composite(cm1, cm2, mask1)

    mask2 = util.radial_gradient_mask(size, length=.3, scale=.6, center=pos)
    cs = Image.composite(cs, cm3, mask2)
    cr = Image.blend(cb, cs, .4)  # opacity

    cr = css.contrast(cr, 1.1)
    cr = css.saturate(cr, 1.1)

    return cr
Beispiel #5
0
def xpro2(im):
    """Applies X-pro II filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs1 = util.fill(cb.size, [230, 231, 224])
    cs2 = util.fill(cb.size, [43, 42, 161])
    cs2 = Image.blend(cb, cs2, .6)

    gradient_mask = util.radial_gradient_mask(cb.size, length=.4, scale=1.1)
    cs = Image.composite(cs1, cs2, gradient_mask)

    # TODO: improve alpha blending
    cm1 = css.blending.color_burn(cb, cs)
    cm2 = cm1.copy()
    cm2 = Image.blend(cb, cm2, .6)
    cr = Image.composite(cm1, cm2, gradient_mask)

    cr = css.sepia(cr, .3)

    return cr
Beispiel #6
0
def test_or_convert_different_mode():
    w, h = (4, 4)
    im = util.fill((w, h), [0, 127, 255, .5])  # RGBA
    converted = util.or_convert(im, 'RGB')

    assert converted != im
    assert converted.mode == 'RGB'
Beispiel #7
0
def rise(im):
    """Applies Rise filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs1 = util.fill(cb.size, [236, 205, 169, .15])
    cm1 = css.blending.multiply(cb, cs1)

    cs2 = util.fill(cb.size, [50, 30, 7, .4])
    cm2 = css.blending.multiply(cb, cs2)

    gradient_mask1 = util.radial_gradient_mask(cb.size, length=.55)
    cm = Image.composite(cm1, cm2, gradient_mask1)

    cs3 = util.fill(cb.size, [232, 197, 152, .8])
    cm3 = css.blending.overlay(cm, cs3)

    gradient_mask2 = util.radial_gradient_mask(cb.size, scale=.9)
    cm_ = Image.composite(cm3, cm, gradient_mask2)
    cr = Image.blend(cm, cm_, .6)  # opacity

    cr = css.brightness(cr, 1.05)
    cr = css.sepia(cr, .2)
    cr = css.contrast(cr, .9)
    cr = css.saturate(cr, .9)

    return cr
Beispiel #8
0
def test_or_convert_same_mode():
    w, h = (4, 4)
    im = util.fill((w, h), [0, 127, 255])  # RGB
    converted = util.or_convert(im, 'RGB')

    assert converted == im  # should be the same instance
    assert converted.mode == 'RGB'
Beispiel #9
0
def grayscale(im, amount=1):
    """Converts image to grayscale.

    A grayscale operation is equivalent to the following matrix operation:

    | R' |     |0.2126+0.7874g  0.7152-0.7152g  0.0722-0.0722g 0  0 |   | R |
    | G' |     |0.2126-0.2126g  0.7152+0.2848g  0.0722-0.0722g 0  0 |   | G |
    | B' |  =  |0.2126-0.2126g  0.7152-0.7152g  0.0722+0.9278g 0  0 | * | B |
    | A' |     |            0               0               0  1  0 |   | A |
    | 1  |     |            0               0               0  0  1 |   | 1 |

    See the W3C document:
    https://www.w3.org/TR/filter-effects-1/#grayscaleEquivalent

    Arguments:
        im: An input image.
        amount: An optional integer/float. The filter amount (percentage).
            Defaults to 1.

    Returns:
        The output image.

    Raises:
        AssertionError: if `amount` is less than 0.
    """

    assert amount >= 0

    g = 1 - min(amount, 1)
    matrix = [
        .2126 + .7874 * g,
        .7152 - .7152 * g,
        .0722 - .0722 * g,
        0,
        .2126 - .2126 * g,
        .7152 + .2848 * g,
        .0722 - .0722 * g,
        0,
        .2126 - .2126 * g,
        .7152 - .7152 * g,
        .0722 + .9278 * g,
        0,
    ]

    grayscaled = util.or_convert(im, 'RGB').convert('RGB', matrix)
    return util.or_convert(grayscaled, im.mode)
Beispiel #10
0
def saturate(im, amount=1):
    """Saturates image.

    A saturate operation is equivalent to the following matrix operation:

        | R' |     |0.213+0.787s  0.715-0.715s  0.072-0.072s 0  0 |   | R |
        | G' |     |0.213-0.213s  0.715+0.285s  0.072-0.072s 0  0 |   | G |
        | B' |  =  |0.213-0.213s  0.715-0.715s  0.072+0.928s 0  0 | * | B |
        | A' |     |           0            0             0  1  0 |   | A |
        | 1  |     |           0            0             0  0  1 |   | 1 |

    See the W3C document:
    https://www.w3.org/TR/SVG11/filters.html#feColorMatrixValuesAttribute

    Arguments:
        im: An input image.
        amount: An optional integer/float. The filter amount (percentage).
            Defaults to 1.

    Returns:
        The output image.

    Raises:
        AssertionError: if `amount` is less than 0.
    """

    assert amount >= 0

    matrix = [
        .213 + .787 * amount,
        .715 - .715 * amount,
        .072 - .072 * amount,
        0,
        .213 - .213 * amount,
        .715 + .285 * amount,
        .072 - .072 * amount,
        0,
        .213 - .213 * amount,
        .715 - .715 * amount,
        .072 + .928 * amount,
        0,
    ]

    saturated = util.or_convert(im, 'RGB').convert('RGB', matrix)
    return util.or_convert(saturated, im.mode)
Beispiel #11
0
def sepia(im, amount=1):
    """Converts image to sepia.

    A sepia operation is equivalent to the following matrix operation:

    | R' |     |0.393+0.607s  0.769-0.769s  0.189-0.189s 0  0 |   | R |
    | G' |     |0.349-0.349s  0.686+0.314s  0.168-0.168s 0  0 |   | G |
    | B' |  =  |0.272-0.272g  0.534-0.534g  0.131+0.869g 0  0 | * | B |
    | A' |     |          0             0             0  1  0 |   | A |
    | 1  |     |          0             0             0  0  1 |   | 1 |

    See the W3C document:
    https://www.w3.org/TR/filter-effects-1/#sepiaEquivalent

    Arguments:
        im: An input image.
        amount: An optional integer/float. The filter amount (percentage).
            Defaults to 1.

    Returns:
        The output image.

    Raises:
        AssertionError: if `amount` is less than 0.
    """

    assert amount >= 0

    amount = 1 - min(amount, 1)
    matrix = [
        .393 + .607 * amount, .769 - .769 * amount, .189 - .189 * amount, 0,
        .349 - .349 * amount, .686 + .314 * amount, .168 - .168 * amount, 0,
        .272 - .272 * amount, .534 - .534 * amount, .131 + .869 * amount, 0,
    ]

    sepia_toned = util.or_convert(im, 'RGB').convert('RGB', matrix)
    return util.or_convert(sepia_toned, im.mode)
Beispiel #12
0
def perpetua(im):
    """Applies Perpetua filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.linear_gradient(cb.size, [0, 91, 154], [230, 193, 61], False)
    cs = css.blending.soft_light(cb, cs)
    cr = Image.blend(cb, cs, .5)  # opacity

    return cr
Beispiel #13
0
def inkwell(im):
    """Applies Inkwell filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cr = css.sepia(cb, .3)
    cr = css.contrast(cr, 1.1)
    cr = css.brightness(cr, 1.1)
    cr = css.grayscale(cr)

    return cr
Beispiel #14
0
def brannan(im):
    """Applies Brannan filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')
    cs = util.fill(cb.size, [161, 44, 199, .31])
    cr = css.blending.lighten(cb, cs)

    cr = css.sepia(cr, .5)
    cr = css.contrast(cr, 1.4)

    return cr
Beispiel #15
0
def toaster(im):
    """Applies Toaster filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.radial_gradient(cb.size, [(128, 78, 15), (59, 0, 59)])
    cr = css.blending.screen(cb, cs)

    cr = css.contrast(cr, 1.5)
    cr = css.brightness(cr, .9)

    return cr
Beispiel #16
0
def kelvin(im):
    """Applies Kelvin filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs1 = util.fill(cb.size, [56, 44, 52])
    cs = css.blending.color_dodge(cb, cs1)

    cs2 = util.fill(cb.size, [183, 125, 33])
    cr = css.blending.overlay(cs, cs2)

    return cr
Beispiel #17
0
def gingham(im):
    """Applies Gingham filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.fill(cb.size, [230, 230, 250])
    cr = css.blending.soft_light(cb, cs)

    cr = css.brightness(cr, 1.05)
    cr = css.hue_rotate(cr, -10)

    return cr
Beispiel #18
0
def clarendon(im):
    """Applies Clarendon filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.fill(cb.size, [127, 187, 227, .2])
    cr = css.blending.overlay(cb, cs)

    cr = css.contrast(cr, 1.2)
    cr = css.saturate(cr, 1.35)

    return cr
Beispiel #19
0
def earlybird(im):
    """Applies Earlybird filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.radial_gradient(cb.size, [(208, 186, 142), (54, 3, 9),
                                        (29, 2, 16)], [.2, .85, 1])
    cr = css.blending.overlay(cb, cs)

    cr = css.contrast(cr, .9)
    cr = css.sepia(cr, .2)

    return cr
Beispiel #20
0
def _1977(im):
    """Applies 1977 filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.fill(cb.size, [243, 106, 188, .3])
    cr = css.blending.screen(cb, cs)

    cr = css.contrast(cr, 1.1)
    cr = css.brightness(cr, 1.1)
    cr = css.saturate(cr, 1.3)

    return cr
Beispiel #21
0
def lark(im):
    """Applies Lark filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs1 = util.fill(cb.size, [34, 37, 63])
    cm1 = css.blending.color_dodge(cb, cs1)

    cs2 = util.fill(cb.size, [242, 242, 242])
    cm2 = ImageChops.darker(cm1, cs2)
    cr = Image.blend(cm1, cm2, .8)

    return cr
Beispiel #22
0
def stinson(im):
    """Applies Stinson filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.fill(cb.size, [240, 149, 128, .2])
    cr = css.blending.soft_light(cb, cs)

    cr = css.contrast(cr, .75)
    cr = css.saturate(cr, .85)
    cr = css.brightness(cr, 1.15)

    return cr
Beispiel #23
0
def valencia(im):
    """Applies Valencia filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.fill(cb.size, [58, 3, 57])
    cs = css.blending.exclusion(cb, cs)
    cr = Image.blend(cb, cs, .5)

    cr = css.contrast(cr, 1.08)
    cr = css.brightness(cr, 1.08)
    cr = css.sepia(cr, .08)

    return cr
Beispiel #24
0
def maven(im):
    """Applies Maven filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.fill(cb.size, [3, 230, 26, .2])
    cr = css.blending.hue(cb, cs)

    cr = css.sepia(cr, .25)
    cr = css.brightness(cr, .95)
    cr = css.contrast(cr, .95)
    cr = css.saturate(cr, 1.5)

    return cr
Beispiel #25
0
def lofi(im):
    """Applies Lo-Fi filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.fill(cb.size, [34, 34, 34])
    cs = css.blending.multiply(cb, cs)

    mask = util.radial_gradient_mask(cb.size, length=.7, scale=1.5)
    cr = Image.composite(cb, cs, mask)

    cr = css.saturate(cr, 1.1)
    cr = css.contrast(cr, 1.5)

    return cr
Beispiel #26
0
def slumber(im):
    """Applies Slumber filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs1 = util.fill(cb.size, [69, 41, 12, .4])
    cm = css.blending.lighten(cb, cs1)

    cs2 = util.fill(cb.size, [125, 105, 24, .5])
    cr = css.blending.soft_light(cm, cs2)

    cr = css.saturate(cr, .66)
    cr = css.brightness(cr, 1.05)

    return cr
Beispiel #27
0
def hudson(im):
    """Applies Hudson filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.radial_gradient(cb.size, [(166, 177, 255), (52, 33, 52)],
                              [.5, 1])
    cs = css.blending.multiply(cb, cs)
    cr = Image.blend(cb, cs, .5)  # opacity

    cr = css.brightness(cr, 1.2)
    cr = css.contrast(cr, .9)
    cr = css.saturate(cr, 1.1)

    return cr
Beispiel #28
0
def walden(im):
    """Applies Walden filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.fill(cb.size, [0, 68, 204])
    cs = ImageChops.screen(cb, cs)
    cr = Image.blend(cb, cs, .3)

    cr = css.brightness(cr, 1.1)
    cr = css.hue_rotate(cr, -10)
    cr = css.sepia(cr, .3)
    cr = css.saturate(cr, 1.6)

    return cr
Beispiel #29
0
def reyes(im):
    """Applies Reyes filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs = util.fill(cb.size, [239, 205, 173])
    cs = css.blending.soft_light(cb, cs)
    cr = Image.blend(cb, cs, .5)

    cr = css.sepia(cr, .22)
    cr = css.brightness(cr, 1.1)
    cr = css.contrast(cr, .85)
    cr = css.saturate(cr, .75)

    return cr
Beispiel #30
0
def moon(im):
    """Applies Moon filter.

    Arguments:
        im: An input image.

    Returns:
        The output image.
    """

    cb = util.or_convert(im, 'RGB')

    cs1 = util.fill(cb.size, [160, 160, 160])
    cs = css.blending.soft_light(cb, cs1)

    cs2 = util.fill(cb.size, [56, 56, 56])
    cr = css.blending.lighten(cs, cs2)

    cr = css.grayscale(cr)
    cr = css.contrast(cr, 1.1)
    cr = css.brightness(cr, 1.1)

    return cr