def draw_circles(C): """ This function draws the shaded circles to the screen. We are drawing them in a function so we can reuse them quickly for blending. """ # Palette #19 is a good predefined palette with whites and blues pal = ph.palette(19) # The base radius of our circles. Everything will scale from this radius = 1.60 offset = 0.50 tc = 0.2 # Base thickness # All the circles will have a linear gradient from top to bottom, # or bottom to top (we use theta for that). The second parameter [1, 0] # controls the alpha (the transparency). The sizing and thickness was # choosen by hand to get a nice effect. lg = ph.gradient.linear([pal[0], pal[1]], [1, 0], theta=-np.pi / 2) C += circle(0, 0, radius + offset, thickness=tc, gradient=lg) lg = ph.gradient.linear([pal[0], pal[1]], [1, 0], theta=np.pi / 2) C += circle(0, 0, radius - 2 * offset, thickness=tc / 2, gradient=lg) lg = ph.gradient.linear([pal[2], pal[1]], [1, 0], theta=-np.pi / 2) C += circle(0, 0, radius - offset, thickness=tc / 2, gradient=lg) lg = ph.gradient.linear([pal[2], pal[1]], [1, 0], theta=np.pi / 2) C += circle(0, 0, radius + 1.5 * offset, thickness=tc / 2, gradient=lg)
def gridstack_test(self): """ dstack_test: Draw an image, stack it, and make sure it's the same as the numpy operation. """ C1 = ph.Canvas() C2 = ph.Canvas() C3 = ph.Canvas() C1 += ph.circle() C2 += ph.rectangle() C3 += ph.circle(x=1) # Make sure something was drawn assert_true(C1.img.sum() != 0) assert_true(C2.img.sum() != 0) assert_true(C3.img.sum() != 0) X = ph.gridstack([[C1, C2], [C2, C3]]) img_stack = np.vstack( [np.hstack([C1.img, C2.img]), np.hstack([C2.img, C3.img])]) assert_true(np.isclose(img_stack, X.img).all())
def rotating_circles(): A = Animation(**animation_args) x = motion.easeReturn("easeInOutQuad", -1, 1, len(A)) A(circle(x, 1, r=1.25, color=[0, 250, 150], mode="add")) A(circle(-x, -1, r=1.25, color=[255, 5, 100], mode="add")) return A
def rotating_circles(): A = Animation(**animation_args) x = motion.easeInOutQuad(-1, 1, flip=True) A(circle(x, 1, r=2.5, color=[0, 250, 150], mode="add")) A(circle(-x, -1, r=2.5, color=[255, 5, 100], mode="add")) return A
def layer_test(self): """ layer_test: Tests ONLY if the API is working, not a complete test. """ A = ph.Animation() A += ph.circle(color="r") with A.layer() as AX: AX += ph.circle(y=1, color="b") AX += ph.transform.translate(x=1) A.render_all()
def simple_circles(): C = Canvas(**canvas_args) n = 3 t = np.arange(0, 2 * np.pi, 2 * np.pi / n) + np.pi / 6 x, y = np.cos(t), np.sin(t) C += circle(x[0], y[0], 1, color=[0, 255, 0], mode="add") C += circle(x[1], y[1], 1, color=[255, 0, 0], mode="add") C += circle(x[2], y[2], 1, color=[0, 0, 255], mode="add") # An example of not saturating the images together C += circle(0, 0, 0.25, color=[155, 155, 155]) return C
def check_draw_if_offscreen_is_ok_test(self): g = ph.gradient.linear(["r", "b"]) C = ph.Canvas() C += ph.circle(x=C.xmax + 20, y=C.ymax + 20, r=1, gradient=g) # Check that nothing was drawn assert (C.img[:, :, :3] == C.transform_color(C.bg)[:3]).all()
def combine_canvas_test(self): """ combine_canvas_test: Try to add two canvas together with blend, add, subtract modes. """ C1 = ph.Canvas() C1 += ph.circle(color="w") C2 = ph.Canvas() C2 += ph.circle(x=-0.5, color="b") C3 = C1.copy().combine(C2, mode="blend") C4 = C1.copy().combine(C2, mode="add") C5 = C1.copy().combine(C2, mode="subtract") # Now check that none of them are equal for x, y in itertools.combinations([C1, C3, C4, C5], r=2): assert_false((x.img == y.img).all())
def logo_animation(logo_text): pal = ph.palette(3) A = ph.Animation(fps=24, duration=1.5, width=800, height=800, bg=pal[2]) lg = ph.gradient.linear([pal[0], pal[1]], theta=-np.pi / 4) A += ph.circle(color=pal[3]) A += ph.filters.gaussian_blur() A += ph.circle(color=pal[3]) y = ph.motion.easeInOutQuad(0, 1, flip=True) for i in np.arange(-6, 6, 1.0): A += ph.text(logo_text, y=i * y, gradient=lg, font_size=1.0) return A
def zero_weight_test(self): C0 = ph.Canvas() C0 += ph.circle(color=[20, 30, 40, 50]) C1 = C0.copy() C1 += ph.filters.instafilter("1977", weight=0) # Check that they are equal assert_true(np.isclose(C0.img, C1.img).all())
def instagram_filters(): f_sample = "pixelhouse/filter/insta/samples/Normal.jpg" C = Canvas(bg="w", **canvas_args).load(f_sample) C += scale(fx=0.25) C += circle(r=0.50, color="r") C += instafilter("Ludwig", weight=0.80) return C
def simple_all_frames_the_same_test(self): """ simple_all_frames_the_same_test: Draw a circle and make sure all frames are the same """ canvas = ph.Animation() canvas += ph.circle() canvas.render_all() for rhs in canvas.frames[1:]: assert_true((rhs.img == canvas.frames[0].img).all())
def setup(self): kwargs = { "width": 200, "height": 200, "extent": 4.0, "bg": "black", "shift": 8, } self.source = ph.Canvas(**kwargs) self.source += ph.circle(x=1, y=-0.5, color=[50, 75, 100, 100]) self.source += ph.rectangle(x=-1, y=0.5, color=[70, 75, 100, 100]) self.target = self.source.copy()
def something_moved_test(self): """ something_moved_test: Draw a circle and make sure it moved """ canvas = ph.Animation() x = np.linspace(0, 1, 10) canvas += ph.circle(x=x) canvas.render_all() for rhs in canvas.frames[1:]: assert_true((rhs.img != canvas.frames[0].img).any())
def blank_doesnt_modify_in_place_test(self): """ blank_doesnt_modify_in_place_test: If the canvas has not had anything painted on it, its sum is 0 If the canvas has been blanked out, its sum is 0 Otherwise, its sum should be > 0 """ canvas = ph.Canvas() assert_true(canvas.img.sum() == 0) canvas += ph.circle() assert_true(canvas.img.sum() > 0) canvas.blank() assert_true(canvas.img.sum() > 0) assert_true(canvas.blank().img.sum() == 0)
def layer_test(self): """ layer_test: Test if layers work by testing order of operations """ C1 = ph.Canvas() C2 = ph.Canvas() C1 += ph.circle(color="r") C1 += ph.circle(y=1, color="b") C1 += ph.transform.translate(x=1) C2 += ph.circle(color="r") with C2.layer() as CX: CX += ph.circle(y=1, color="b") CX += ph.transform.translate(x=1) img1, img2 = C1.img, C2.img # First make sure something was drawn in each case assert_true(img1.sum() > 0) assert_true(img2.sum() > 0) # Now check that they aren't equal assert_false((img1 == img2).all())
def direct_load_test(self): """ direct_load_test: Load an image without creating a canvas. """ C = ph.Canvas(bg="yellow") C += ph.circle(color="g") C2 = ph.Canvas() with tempfile.NamedTemporaryFile(suffix=".png") as F: C.save(F.name) C2 = ph.load(F.name) dist = C.img[:, :, :3] - C2.img[:, :, :3] dist = dist.astype(float) / 255 assert_equal(dist.sum(), 0)
def save_load_test(self): """ save_load_test: Create an image, save it to a tmp location and try to load it back in. Make sure we check in PNG (lossless) and don't try to check the alpha channel. """ C = ph.Canvas(bg="yellow") C += ph.circle(color="g") C2 = ph.Canvas() with tempfile.NamedTemporaryFile(suffix=".png") as F: C.save(F.name) C2.load(F.name) dist = C.img[:, :, :3] - C2.img[:, :, :3] dist = dist.astype(float) / 255 assert_equal(dist.sum(), 0)
def teyleen_116(): C = Canvas(**canvas_args) pal = ph.palette(152) x = 0.25 C += circle(x, x, r=x / 2, color=pal[0]) C += circle(-x, x, r=x / 2, color=pal[1]) C += circle(x, -x, r=x / 2, color=pal[2]) C += circle(-x, -x, r=x / 2, color=pal[3]) C += circle(y=x / 2, r=2 - x, color=pal[4], thickness=x / 20) C += circle(y=-x / 2, r=2 - x, color=pal[4], thickness=x / 20) return C
def checkerboard(): A = Animation(**animation_args) z = motion.easeReturn("easeInOutQuad", 0, 1, len(A)) r = 0.20 c = [150, 250, 0] coord = [-2, 0, 2] args = {"r": r, "color": c, "mode": "add"} for dx, dy in itertools.product(coord, repeat=2): A += circle(z + dx, z + dy, **args) A += circle(z + dx, -z + dy, **args) A += circle(-z + dx, -z + dy, **args) A += circle(-z + dx, z + dy, **args) A += circle(dx, z + dy, **args) A += circle(z + dx, dy, **args) A += circle(dx, -z + dy, **args) A += circle(-z + dx, dy, **args) return A
# Setup our canvas! Make it 400 by 400 pixels, # and use the first palette color as the background. canvas = ph.Canvas(400, 400, bg=background_color) # Now draw some circles on the screen. We want to loop over this twice, # once for the vertical direction and the other for the horizontal. # To give it a wavy feel, we want every other circle to be offset a bit. radius = 0.40 for k, y in enumerate(np.arange(-6, 6, radius)): for x in np.arange(-6, 6, radius * 2.5): # If k is odd (eg. every other one), offset it! if k % 2: x += radius / 2 # Pick a random color for the circle from our palette color = random.choice(primary_colors) # Draw a circle to the canvas by "adding" to it canvas += ph.circle(x=x, y=y, r=radius, color=color) # Save the image. canvas.save("figures/circle_lines.png") # Display the image. It'll stay open until you press a key. canvas.show()
# A working file to test various aspects of the module import numpy as np from pixelhouse import Artist from pixelhouse import Canvas, Animation, circle, motion from pixelhouse.transform.simple import translate, rotate from pixelhouse.transform.elastic import distort A = Canvas() A = Animation(duration=2, fps=15) A += circle(color="w") A += circle(-1, 0, 0.25, color="purple") theta = motion.easeReturn("easeInOutQuad", 0, np.pi, len(A)) A += rotate(theta) z = motion.easeReturn("easeInOutQuad", 0, 10, len(A)) A += distort(seed=42, sigma=0.05, alpha=z) A.show()
# A working file to test various aspects of the module import numpy as np import pixelhouse as ph # A = ph.Canvas(width=300, height=300) A = ph.Animation(width=400, height=400, fps=2) A += ph.circle(r=1.0, color="darkorange") A += ph.circle(r=0.8, color="w", mode="direct") z = ph.motion.easeInOutQuad(0, 2 * np.pi) A += ph.transform.motion_lines(0.4, theta=z) A += ph.transform.motion_lines(0.4) A += ph.transform.rotate(z) A.show()
# Testing chained animation import numpy as np import random import pixelhouse as ph from pixelhouse.filters import gaussian_blur pal = ph.palette(0) random.seed(44) x = np.linspace(0, 2, 100) C = ph.Animation(400, 400, bg=pal[0]) C += ph.rectangle(x=x, x1=x + 1, color=pal[3]) C2 = C.blank(duration=1) C2 += ph.circle(x=x, color=pal[2]) C2 += gaussian_blur() C += C2 C.show()
dx = dist * (-acc[0]) dy = 0 * (dist * acc[1]) # print(c0,c1,c2) print(t, acc[1]) # print(dx.max()) self.transform(cvs, dy, dx, coords, "nearest", order=0) """ import pylab as plt plt.imshow(dx[:,:,0]) plt.colorbar() plt.show() exit() print(acc) """ C = ph.Animation(400, 200, fps=20) b = ph.motion.easeInOutQuad(-2, 2, flip=True) q = ph.circle(x=b, y=0, r=0.5, gradient=g) C += q C += squish(q) C.show()
def check_API_clipped_transparency_test(self): """ Check if the API for RGB interpolation works. """ g = ph.gradient.linear(["r", "b"], transparency=[0.5, 2.0]) self.canvas += ph.circle(gradient=g)
# A working file to test various aspects of the module import numpy as np import pixelhouse as ph pal = ph.palette(4) C = ph.Canvas(width=400, height=400, bg=pal[0]) C = ph.Animation(width=400, height=400, bg=pal[0]) C += ph.circle(x=1, y=-0.5, r=2, color=pal[1]) theta = np.linspace(0, 2 * np.pi) with C.layer() as CX: CX += ph.polyline(color="k") CX += ph.transform.rotate(theta) CX += ph.filters.gaussian_blur(0.25, theta / 6) C += ph.circle(x=-1, r=1.0) C.show()
def check_API_LAB_test(self): """ Check if the API for LAB interpolation works. """ g = ph.gradient.linear(["r", "b"], interpolation="LAB") self.canvas += ph.circle(gradient=g)
def circle_test(self): C = Canvas() C += circle() assert_true(C._img.sum() > 0)
def check_API_discrete_test(self): """ Check if the API for RGB interpolation works. """ g = ph.gradient.linear(["r", "b"], interpolation="discrete") self.canvas += ph.circle(gradient=g)