Beispiel #1
0
def main(filename="output.png",
         img_width=2000,
         img_height=2000,
         rows=20,
         columns=20,
         palette=random.choice(palettes.PALETTES)):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    col_width = img_width // columns
    row_height = img_height // rows
    for r in range(rows):
        for c in range(columns):
            hex_colors = random.choices(palette['colors'] +
                                        [palette['background']],
                                        k=2)
            color1 = palettes.hex_to_tuple(hex_colors[0])
            color2 = palettes.hex_to_tuple(hex_colors[1])
            tile(ctx, c * col_width, r * row_height, col_width, row_height,
                 color1, color2)

    ims.write_to_png(filename)
Beispiel #2
0
def draw_robot(ctx, x, y, x2, y2, palette):
    margin = int(min(x2 - x, y2 - y) / 20)
    antenna_height = draw_antennas(ctx, x, y, x2, y2, margin, palette)
    face_top = y + margin + antenna_height
    face_bottom = y2 - margin

    # Face.
    face_hex = random.choice(palette['colors'])
    non_face_palette = [c for c in palette['colors'] if c != face_hex]
    face_color = palettes.hex_to_tuple(face_hex)
    face_radius = random.randint(margin, 5 * margin)
    draw_rounded_rect(ctx, x + margin, x2 - margin, face_top, face_bottom,
                      face_radius, face_color)

    # Eyes. Ensure color different from face.
    eye_color = palettes.hex_to_tuple(random.choice(non_face_palette))
    draw_eyes(ctx, x, x2, face_top, face_bottom, margin, eye_color)

    # Mouth
    mouth_color = palettes.hex_to_tuple(random.choice(non_face_palette))
    draw_mouth(ctx, x, x2, face_top, face_bottom, margin, mouth_color)

    draw_screws(ctx, x, x2, face_top, face_bottom, margin)

    draw_ears(ctx, x, x2, face_top, face_bottom, face_color, margin)
Beispiel #3
0
def main(filename="output.png",
         img_width=2000,
         img_height=2000,
         count=40,
         layers=80,
         palette=random.choice(palettes.PALETTES)):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ctx = cairo.Context(ims)

    # Make background solid color
    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    line_width = int(img_width / count)
    layer_height = img_height // layers
    layer_offset = 0
    for l in range(layers):
        if layer_offset == 0:
            layer_offset = int(line_width / 2)
        else:
            layer_offset = 0
        for x in range(layer_offset, img_width + line_width, line_width):
            min_layer_height = l * layer_height + (line_width // 2)
            max_layer_height = (l + 1) * layer_height
            if max_layer_height <= min_layer_height:
                continue
            end = random.randint(min_layer_height, max_layer_height)
            draw_line(ctx, x, img_height, x, end, line_width,
                      palettes.hex_to_tuple(random.choice(palette['colors'])))

    ims.write_to_png(filename)
Beispiel #4
0
def color_variant(color):
    original = palettes.hex_to_tuple(color)
    adjust_by = random.uniform(0.0, 0.5)
    if random.random() < 0.5:
        return tuple(((1 - c) * adjust_by + c) for c in original)
    else:
        return tuple((c * adjust_by + c) for c in original)
Beispiel #5
0
def reed(ctx, width, height, color=palettes.BRIGHT_GREEN, vary_colors=True):
    x_min_increment = width // 100
    x_max_increment = 4 * x_min_increment
    y_min_increment = height // 12
    y_max_increment = 5 * y_min_increment

    # Draw curve
    x1 = random.randint(0, width)
    y1 = height
    lean_to_side = -1 if random.random() < 0.5 else 1
    x2 = snap_to_edges(
        x1 + lean_to_side * random.randint(x_min_increment, x_max_increment),
        width)
    y2 = height - random.randint(y_min_increment, y_max_increment)
    x3 = snap_to_edges(
        x1 -
        1 * lean_to_side * random.randint(x_min_increment, x_max_increment),
        width)
    y3 = y2 - random.randint(y_min_increment, y_max_increment)
    ctx.curve_to(x1, y1, x2, y2, x3, y3)
    line_width = random.randint(8, x_min_increment)
    ctx.set_line_width(line_width)
    current_color = color_variant(
        color) if vary_colors else palettes.hex_to_tuple(color)
    ctx.set_source_rgb(*current_color)
    ctx.stroke()

    # Ball
    ctx.arc(x3, y3, random.randint(line_width + 2, 2 * x_min_increment), 0,
            2 * math.pi)
    ctx.set_source_rgb(*current_color)
    ctx.fill()
Beispiel #6
0
def main(filename="output.png",
         step=50,
         line_width=5,
         img_width=3840,
         img_height=2160,
         palette=random.choice(palettes.PALETTES)):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ctx = cairo.Context(ims)

    # Make background solid color
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.rectangle(0, 0, img_width, img_height)
    ctx.fill()

    for x in range(0, img_width, step):
        for y in range(0, img_height, step):
            draw_line(ctx,
                      x,
                      y,
                      step,
                      step,
                      line_width=line_width,
                      palette=palette)

    ims.write_to_png(filename)
Beispiel #7
0
def main(filename="output.png",
         img_width=2000,
         img_height=2000,
         count=5,
         palette=random.choice(palettes.PALETTES)):
    while len(palette['colors']) < 3:
        print(f"Palette {palette} has too few colors. Choosing another one.")
        palette = random.choice(palettes.PALETTES)

    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ctx = cairo.Context(ims)

    # Make background solid color
    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    x_size = img_width // count
    y_size = img_width // count
    for x in range(count):
        for y in range(count):
            draw_robot(ctx, x * x_size, y * y_size, (x + 1) * x_size,
                       (y + 1) * y_size, palette)

    ims.write_to_png(filename)
Beispiel #8
0
def main(filename="output.png",
         palette=random.choice(palettes.PALETTES),
         num_columns=12,
         num_rows=12,
         num_steps=[1, 2, 3],
         line_width=4):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, IMG_WIDTH, IMG_HEIGHT)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Background
    ctx.rectangle(0, 0, IMG_WIDTH, IMG_HEIGHT)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    column_size = IMG_WIDTH // num_columns
    row_size = IMG_HEIGHT // num_rows
    for c in range(num_columns):
        for r in range(num_rows):
            if r < num_rows // 3:
                current_num_steps = num_steps[0]
            elif r < 2 * num_rows // 3:
                current_num_steps = num_steps[1]
            else:
                current_num_steps = num_steps[2]
            #p = random.choice(palettes.PALETTES)
            lines(ctx, palette['colors'], c * column_size, r * row_size,
                  column_size, row_size, current_num_steps, line_width)

    ims.write_to_png(filename)
Beispiel #9
0
def main(palette=random.choice(palettes.PALETTES), filename="output.png", img_width=3840, img_height=2160):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Background
    ctx.rectangle(0, 0, img_width, img_width)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    min_radius = int(img_height / 150)
    max_radius = int(img_height / 7)
    circles = []
    for _ in range(TOTAL_CIRCLE_ATTEMPTS):
        c = makeRandomCircle(circles, min_radius, max_radius, img_width, img_height)
        if c:
            print("New circle added. Total circles: ", len(circles))
            circles.append(c)
        else:
            print(".")

    for c in circles:
        step = random.uniform(1.1, 5)
        concentric(ctx, c, palette, min_radius, step=step)

    ims.write_to_png(filename)
Beispiel #10
0
def cell(ctx,
         x,
         y,
         width,
         height,
         palette,
         min_width=1,
         max_width=random.randint(8, 15),
         line_count=100):
    for _ in range(line_count):
        if random.random() <= 0.5:
            # Left to right
            start_x = x
            start_y = random.randint(y, y + height)
            end_x = x + width
            end_y = random.randint(y, y + height)
        else:
            # Top to bottom
            start_x = random.randint(x, x + width)
            start_y = y
            end_x = random.randint(x, x + width)
            end_y = y + height
        ctx.move_to(start_x, start_y)
        ctx.line_to(end_x, end_y)
        ctx.set_source_rgb(
            *palettes.hex_to_tuple(random.choice(palette['colors'])))
        ctx.set_line_width(random.randint(min_width, max_width))
        ctx.stroke()
Beispiel #11
0
def draw_screw(ctx, x, y, radius, margin):
    line_width = margin // 12
    ctx.save()
    ctx.translate(x, y)
    ctx.rotate(pi / 4)

    # Grey circle
    ctx.arc(0, 0, radius, 0, 2 * pi)
    ctx.set_source_rgb(*palettes.hex_to_tuple('#acb4bf'))
    ctx.fill()

    # Outline
    ctx.arc(0, 0, radius, 0, 2 * pi)
    ctx.set_source_rgb(0, 0, 0)
    ctx.set_line_width(line_width)
    ctx.stroke()

    # Cross-threads
    space_from_edge = 2 + line_width
    draw_line(ctx, 0, -radius + space_from_edge, 0, radius - space_from_edge,
              line_width, (0, 0, 0))
    draw_line(ctx, -radius + space_from_edge, 0, radius - space_from_edge, 0,
              line_width, (0, 0, 0))

    ctx.restore()
Beispiel #12
0
def main(filename="output.png",
         palette=random.choice(palettes.PALETTES),
         shape_count=100):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, IMG_WIDTH, IMG_HEIGHT)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Background
    ctx.rectangle(0, 0, IMG_WIDTH, IMG_HEIGHT)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    for _ in range(shape_count):
        color = palettes.hex_to_tuple(random.choice(palette['colors']))
        shape(ctx, color)

    ims.write_to_png(filename)
Beispiel #13
0
def main(filename="output.png",
         palette=random.choice(palettes.PALETTES),
         lines=20):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, IMG_WIDTH, IMG_HEIGHT)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Background
    ctx.rectangle(0, 0, IMG_WIDTH, IMG_HEIGHT)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    line_interval = IMG_HEIGHT // lines
    for y in range(line_interval, IMG_HEIGHT, line_interval):
        color = palettes.hex_to_tuple(random.choice(palette['colors']))
        line(ctx, y, line_interval, color)

    ims.write_to_png(filename)
Beispiel #14
0
def main(filename="output.png", img_width=2000, img_height=2000, palette=random.choice(palettes.PALETTES), rows=20, columns=20, line_width=20):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Background
    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    cell_width = img_width // columns
    cell_height = img_width // rows
    for x in range(0, img_width, cell_width):
        for y in range(0, img_height, cell_height):
            color = palettes.hex_to_tuple(random.choice(palette['colors']))
            ess(ctx, x, y, cell_width, cell_height, color, line_width)

    ims.write_to_png(filename)
Beispiel #15
0
def main(filename="output.png", img_width=2000, n=10, palette=random.choice(palettes.PALETTES), fill=True):
    img_height = img_width   # Work only with square images
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    size = img_width / n
    for r in range(n):
        for c in range(n):
            hex_colors = random.choices(palette['colors'], k=2)
            color1 = palettes.hex_to_tuple(hex_colors[0])
            color2 = palettes.hex_to_tuple(hex_colors[1])
            tile(ctx, c * size, r * size, size, color1, color2, fill)

    ims.write_to_png(filename)
Beispiel #16
0
def main(filename="output.png",
         palette=random.choice(palettes.PALETTES),
         circles=100,
         img_width=3840,
         img_height=2160):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Background
    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    for _ in range(circles):
        color = palettes.hex_to_tuple(random.choice(palette['colors']))
        circle(ctx, color, img_width, img_height, img_height // 20,
               img_height // 10)

    ims.write_to_png(filename)
Beispiel #17
0
def cell(ctx, x, y, width, height, palette):
    remaining_height = height
    current_y = y
    while remaining_height > 0:
        line_height = random.randint(0, remaining_height)
        ctx.rectangle(x, current_y, width, line_height)
        ctx.set_source_rgb(
            *palettes.hex_to_tuple(random.choice(palette['colors'])))
        ctx.fill()
        remaining_height -= line_height
        current_y += line_height
Beispiel #18
0
def main(filename="output.png",
         palette=random.choice(palettes.PALETTES),
         lines=20,
         fill_factor=1,
         brokenness_factor=0.3):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, IMG_WIDTH, IMG_HEIGHT)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Background
    ctx.rectangle(0, 0, IMG_WIDTH, IMG_HEIGHT)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    line_height = IMG_HEIGHT // lines
    x_increment = IMG_WIDTH // 40
    for y in range(line_height // 2, IMG_HEIGHT, line_height):
        color = palettes.hex_to_tuple(random.choice(palette['colors']))
        line(ctx, y, line_height, color, x_increment, fill_factor,
             brokenness_factor)

    ims.write_to_png(filename)
Beispiel #19
0
def main(filename="output.png", palette=random.choice(palettes.PALETTES), columns=15, rows=10):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, IMG_WIDTH, IMG_HEIGHT)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Background
    ctx.rectangle(0, 0, IMG_WIDTH, IMG_HEIGHT)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    for x in range(0, IMG_WIDTH, IMG_WIDTH // columns):
        for y in range(0, IMG_HEIGHT, IMG_HEIGHT // rows):
            flower(ctx, x, y, IMG_WIDTH // columns, IMG_HEIGHT // rows, random.choice(palette['colors']))

    ims.write_to_png(filename)
Beispiel #20
0
def main(filename="output.png",
         img_width=2000,
         img_height=2000,
         palette=random.choice(palettes.PALETTES)):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ctx = cairo.Context(ims)

    # Make background solid color
    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    spiral(ctx, img_height, img_width, random.choice(palette['colors']))

    ims.write_to_png(filename)
Beispiel #21
0
def petal(ctx, x, y, width, height, color):
    tl = (x, y)
    tr = (x + width, y)
    bl = (x, y + height)
    br = (x + width, y + height)
    if random.random() < 0.5:
        ctx.curve_to(*tl, *tr, *br)
        ctx.move_to(*tl)
        ctx.curve_to(*tl, *bl, *br)
    else:
        ctx.curve_to(*bl, *tl, *tr)
        ctx.move_to(*bl)
        ctx.curve_to(*bl, *br, *tr)

    ctx.set_source_rgb(*palettes.hex_to_tuple(color))
    ctx.fill()
Beispiel #22
0
def flower(ctx, x, y, width, height, color):
    center = (x + width // 2, y + height // 2)
    tl = (x, y)
    tr = (x + width, y)
    bl = (x, y + height)
    br = (x + width, y + height)
    ctx.curve_to(*center, random.randint(x, x + width), y, *tl)
    ctx.curve_to(*center, random.randint(x, x + width), y, *tr)
    ctx.curve_to(*center, x, random.randint(y, y + height), *tl)
    ctx.curve_to(*center, x, random.randint(y, y + height), *bl)
    ctx.curve_to(*center, random.randint(x, x + width), y + height, *bl)
    ctx.curve_to(*center, random.randint(x, x + width), y + height, *br)
    ctx.curve_to(*center, x + width, random.randint(y, y + height), *tr)
    ctx.curve_to(*center, x + width, random.randint(y, y + height), *br)
    ctx.set_source_rgb(*palettes.hex_to_tuple(color))
    ctx.fill()
Beispiel #23
0
def lines(ctx, colors, x, y, width, height, num_steps, line_width):
    ctx.save()
    ctx.translate(x + width / 2, y + height / 2)
    ctx.rotate(random.uniform(-math.pi / 2, math.pi / 2))
    ctx.translate(-width / 2, -height / 2)

    step_size = max(width, height) // num_steps
    current_x = 0
    while current_x < width:
        ctx.move_to(current_x, 0)
        ctx.line_to(current_x, height)
        ctx.set_source_rgb(*palettes.hex_to_tuple(random.choice(colors)))
        ctx.set_line_width(line_width)
        ctx.set_line_cap(cairo.LINE_CAP_ROUND)
        ctx.stroke()
        current_x += step_size
    ctx.restore()
Beispiel #24
0
def spiral(ctx, height, width, color):
    x = width / 2
    y = height / 2
    angle = 0.0
    delta_x = 0.2
    delta_y = 0.2
    maxPoints = [x * 0.1 for x in range(0, 390)]
    ctx.move_to(x, y)
    for i in maxPoints:
        theta = delta_y * i
        angle = delta_x * math.exp(theta)
        x = angle * math.cos(i) + width / 2
        y = angle * math.sin(i) + height / 2
        ctx.line_to(x, y)
    ctx.set_line_width(3)
    ctx.set_line_cap(cairo.LineCap.ROUND)
    ctx.set_source_rgb(*palettes.hex_to_tuple(color))
    ctx.stroke()
Beispiel #25
0
def main(filename="output.png", palette=CORAL_PALETTE, rows=6, columns=6):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, IMG_WIDTH, IMG_HEIGHT)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Make background solid color
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.rectangle(0, 0, IMG_WIDTH, IMG_HEIGHT)
    ctx.fill()

    cell_width = IMG_WIDTH // columns
    cell_height = IMG_HEIGHT // rows
    for y in range(0, IMG_HEIGHT, cell_height):
        for x in range(0, IMG_WIDTH, cell_width):
            polyp(ctx, x, y, cell_width, cell_height,
                  random.choice(palette['colors']))

    ims.write_to_png(filename)
Beispiel #26
0
def main(filename="output.png",
         img_width=2000,
         img_height=2000,
         palette=random.choice(palettes.PALETTES),
         count=50):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Background
    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    existing_shapes = Point([(0, 0), (0, 0)])
    for i in range(count):
        print("Making sphere {}".format(i))
        existing_shapes = sphere(ctx, random.choice(palette['colors']),
                                 img_width, img_height, existing_shapes)

    ims.write_to_png(filename)
Beispiel #27
0
def main(filename="output.png",
         palette=random.choice(palettes.PALETTES),
         columns=15,
         rows=10,
         img_width=3840,
         img_height=2160):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Background
    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    for x in range(0, img_width, img_width // columns):
        for y in range(0, img_height, img_height // rows):
            petal(ctx, x, y, img_width // columns, img_height // rows,
                  random.choice(palette['colors']))

    ims.write_to_png(filename)
Beispiel #28
0
def main(filename="output.png",
         img_width=2000,
         img_height=2000,
         palette=random.choice(palettes.PALETTES),
         reed_count=30,
         vary_colors=False):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ims.set_fallback_resolution(300.0, 300.0)
    ctx = cairo.Context(ims)

    # Black background
    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    for _ in range(reed_count):
        reed(ctx,
             width=img_width,
             height=img_height,
             color=random.choice(palette['colors']),
             vary_colors=vary_colors)

    ims.write_to_png(filename)
Beispiel #29
0
    def make_drop(self, x, y, width, height):
        """Make a drop inside the given bounding box."""
        self.ctx.save()
        self.ctx.translate(x, y)

        [color, inner_color] = [
            palettes.hex_to_tuple(c)
            for c in random.sample(self.palette['colors'], 2)
        ]
        radius = width // 2
        if random.choice([True, False]):
            # Pointing up
            cx = radius
            cy = height - radius
            point = (cx, 0)
        else:
            # Pointing down
            cx = radius
            cy = radius
            point = (cx, height)

        (tang1, tang2) = self.tangential_points(cx, cy, radius, *point)
        self.ctx.move_to(*point)
        self.ctx.line_to(*tang1)
        self.ctx.line_to(*tang2)
        self.ctx.set_source_rgb(*color)
        self.ctx.fill()

        self.ctx.arc(cx, cy, radius, 0, 2 * pi)
        self.ctx.set_source_rgb(*color)
        self.ctx.fill()

        if random.choice([True, False]):
            inner_radius = radius // 2
            self.ctx.arc(cx, cy, inner_radius, 0, 2 * pi)

        self.ctx.restore()
Beispiel #30
0
def main(filename="output.png",
         img_width=2000,
         img_height=2000,
         count=40,
         layers=80,
         palette=random.choice(palettes.PALETTES)):
    ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, img_width, img_height)
    ctx = cairo.Context(ims)

    # Make background solid color
    ctx.rectangle(0, 0, img_width, img_height)
    ctx.set_source_rgb(*palettes.hex_to_tuple(palette['background']))
    ctx.fill()

    line_width = int(img_width / count)
    layer_height = int(img_height / layers)
    lighten_step = 0.75 / layers
    layer_offset = 0
    for l in range(layers + 1):
        lighten_by = lighten_step * l
        if layer_offset == 0:
            layer_offset = int(line_width / 2)
        else:
            layer_offset = 0
        for x in range(layer_offset, img_width + line_width, line_width):
            end = random.randint(l * layer_height,
                                 (l + 1) * layer_height) - int(
                                     layer_height / 2)
            colors = random.choices(palette['colors'], k=2)
            color = tuple(
                ((1 - c) * lighten_by + c) for c in hex_to_tuple(colors[0]))
            color2 = tuple(
                ((1 - c) * lighten_by + c) for c in hex_to_tuple(colors[1]))
            draw_line(ctx, x, img_height, x, end, line_width, color, color2)

    ims.write_to_png(filename)