def test_set_lum(): im1 = util.fill((1, 1), [0, 128, 255]) im2 = util.fill((1, 1), [128, 128, 128]) r1, g1, b1 = im1.split() r2, g2, b2 = im2.split() c1 = '(float(r1), float(g1), float(b1))' c2 = '(float(r2), float(g2), float(b2))' bands = ImageMath.eval('set_lum({}, lum({}))'.format(c1, c2), set_lum=set_lum, lum=lum, r1=r1, g1=g1, b1=b1, r2=r2, b2=b2, g2=g2) expected1 = [ [pytest.approx(41.13881001122631, 1e-6)], [pytest.approx(148.48874067225782, 1e-6)], [255], ] assert [list(band.im.getdata()) for band in bands] == expected1 im_set_lum = Image.merge('RGB', [_convert(band, 'L').im for band in bands]) expected2 = [(floor(41.13881001122631), floor(148.48874067225782), 255)] assert list(im_set_lum.getdata()) == expected2
def linear_gradient(size, start, end, is_horizontal=True): """Creates linear gradient image. Arguments: size: A tuple/list of 2 integers. The size of output image. start: A tuple/list of 3 integers. The starting point color. The point is left-side when `is_horizontal` is True, top otherwise. end: A tuple/list of 3 integers. The ending point color. The point is right-side when `is_horizontal` is True, the bottom otherwise. is_horizontal: An optional boolean. The direction of gradient line. Left to right if True, top to bottom else. Returns: The output image. Raises: AssertionError: if `size`, `start` and/or `end` have invalid size. """ assert len(size) == 2 assert len(start) == 3 assert len(end) == 3 im_start = fill(size, start) im_end = fill(size, end) mask = linear_gradient_mask(size, is_horizontal=is_horizontal) return Image.composite(im_start, im_end, mask)
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
def test_alpha_blend_normal_opaque_backdrop_with_transparent_source(): cb = util.fill((2, 2), [0, 128, 255, 1]) cs = util.fill((2, 2), [255, 128, 0, 0]) cr = alpha_blend(cb, cs, _normal) expected = split_alpha(cb)[0] assert cr == expected
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
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
def test_screen(): cb = util.fill((2, 2), [255, 128, 0]) cs = util.fill((2, 2), [0, 128, 255]) actual = css.blending.screen(cb, cs) expected = ImageChops.screen(cb, cs) assert actual == expected
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
def test_overlay2(): cb = util.fill((2, 2), [0, 128, 255]) cs = util.fill((2, 2), [255, 128, 0]) actual = css.blending.overlay(cb, cs) expected = css.blending.hard_light(cs, cb) assert actual == expected
def test_subtract2(): im1 = util.fill((2, 2), [0, 127, 255]) im2 = util.fill((2, 2), [255, 127, 0]) actual = util.subtract(im1, im2) expected = ImageChops.subtract(im1, im2) assert actual == expected
def test_difference(): cb = util.fill((2, 2), [255, 128, 0]) cs = util.fill((2, 2), [0, 128, 255]) actual = css.blending.difference(cb, cs) expected = ImageChops.difference(cb, cs) assert actual == expected
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
def test_add2(): im1 = util.fill((2, 2), [0, 127, 255]) im2 = util.fill((2, 2), [0, 127, 255]) actual = util.add(im1, im2) expected = ImageChops.add(im1, im2) assert actual == expected
def test_add(): im1 = util.fill((2, 2), [0, 127, 255]) im2 = util.fill((2, 2), [0, 127, 255]) actual = util.add(im1, im2) expected = util.fill((2, 2), [0, 254, 255]) assert actual == expected
def test_normal(): cb = util.fill((2, 2), [255, 128, 0]) cs = util.fill((2, 2), [0, 128, 255]) actual = css.blending.normal(cb, cs) expected = cs assert actual == expected
def test_alpha_blend_normal_rgb_with_opaque_source(): cb = util.fill((2, 2), [0, 128, 255]) cs = util.fill((2, 2), [255, 128, 0, 1]) cr = alpha_blend(cb, cs, _normal) expected = split_alpha(cs)[0] assert cr == expected
def test_contrast_0(): im = util.fill((4, 4), [174, 56, 3]) im2 = util.fill((4, 4), [128] * 3) contrasted_im = css.contrast(im, 0) assert list(contrasted_im.getdata()) == list(im2.getdata()) assert contrasted_im.size == im.size assert contrasted_im.mode == im.mode
def test_brightness_0(): im = util.fill((4, 4), [174, 56, 3]) black = util.fill((4, 4), [0] * 3) im_b = css.brightness(im, 0) assert list(im_b.getdata()) == list(black.getdata()) assert im_b.size == im.size assert im_b.mode == im.mode
def test_alpha_blend_call_blending(mocker): cb = util.fill((2, 2), [0, 128, 255, 1]) cs = util.fill((2, 2), [255, 128, 0, 1]) return_value, _ = split_alpha(cs) normal_stub = mocker.Mock(return_value=return_value) alpha_blend(cb, cs, normal_stub) # TODO: assert with parameters normal_stub.assert_called_once()
def test_sepia_0(): im = util.fill((4, 4), [174, 56, 3]) sepiaed_im = css.sepia(im, 0) assert list(sepiaed_im.getdata()) == list(im.getdata()) assert sepiaed_im.size == im.size assert sepiaed_im.mode == im.mode
def test_grayscale_0(): im = util.fill((4, 4), [174, 56, 3]) grayscaled_im = css.grayscale(im, 0) assert list(grayscaled_im.getdata()) == list(im.getdata()) assert grayscaled_im.size == im.size assert grayscaled_im.mode == im.mode
def test_hue_rotate(): im = util.fill((4, 4), [174, 56, 3]) hue_rotated_im = css.hue_rotate(im) assert list(hue_rotated_im.getdata()) == list(im.getdata()) assert hue_rotated_im.size == im.size assert hue_rotated_im.mode == im.mode
def test_brightness(): im = util.fill((4, 4), [174, 56, 3]) im_b = css.brightness(im) assert list(im_b.getdata()) == list(im.getdata()) assert im_b.size == im.size assert im_b.mode == im.mode
def test_fill_alpha(): w, h = (4, 4) im = util.fill((w, h), [0, 127, 255, .5]) assert list(im.getdata()) == [(0, 127, 255, 128)] * (w * h) assert im.size == (w, h) assert im.mode == 'RGBA'
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'
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'
def test_contrast_greater_than_1(): im = util.fill((4, 4), [174, 56, 3]) contrasted_im = css.contrast(im, 2) contrasted_im2 = css.contrast(im, 1) assert list(contrasted_im.getdata()) != list(contrasted_im2.getdata()) assert contrasted_im.size == im.size assert contrasted_im.mode == im.mode
def test_grayscale_greater_than_1(): im = util.fill((4, 4), [174, 56, 3]) grayscaled_im = css.grayscale(im, 2) grayscaleed_im2 = css.grayscale(im, 1) assert list(grayscaled_im.getdata()) == list(grayscaleed_im2.getdata()) assert grayscaled_im.size == im.size assert grayscaled_im.mode == im.mode
def test_sepia_greater_than_1(): im = util.fill((4, 4), [174, 56, 3]) sepiaed_im = css.sepia(im, 2) sepiaed_im2 = css.sepia(im, 1) assert list(sepiaed_im.getdata()) == list(sepiaed_im2.getdata()) assert sepiaed_im.size == im.size assert sepiaed_im.mode == im.mode
def test_hue_rotate_less_than_0(): im = util.fill((4, 4), [174, 56, 3]) hue_rotated_im = css.hue_rotate(im, -42) hue_rotated_im2 = css.hue_rotate(im) assert list(hue_rotated_im.getdata()) != list(hue_rotated_im2.getdata()) assert hue_rotated_im.size == im.size assert hue_rotated_im.mode == im.mode