Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!python
- # -*- mode: python; Encoding: utf-8; coding: utf-8 -*-
- # Last updated: <2017/04/27 09:46:11 +0900>
- u"""
- tinypixelargrad.py - generate tiny pixelart.
- Drawing with cairo(pycairo).
- testing environment :
- Windows10 x64 + Python 2.7.13 32bit + pycairo 1.8.10
- Author: mieki256
- License: CC0 / Public Domain
- """
- import cairo
- import random
- import colorsys
- import math
- class TinyPixelartGrad(object):
- """Generate tiny pixelart."""
- def __init__(self, w, h, seed=None,
- x_mirror=None, y_mirror=None, hue=None,
- border_width=1.0, border_alpha=1.0):
- """Generate tiny pixelart."""
- if seed is None:
- random.seed()
- else:
- random.seed(seed)
- if x_mirror is None:
- self.x_mirror = True if random.random() > 0.5 else False
- else:
- self.x_mirror = x_mirror
- if y_mirror is None:
- self.y_mirror = True if random.random() > 0.5 else False
- else:
- self.y_mirror = y_mirror
- self.border_width = border_width
- self.border_alpha = border_alpha
- self.hue_base = random.random() * 360 if hue is None else hue
- surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
- ctx = cairo.Context(surface)
- ctx.set_antialias(cairo.ANTIALIAS_NONE)
- ctx.set_line_width(self.border_width)
- ctx.set_line_join(cairo.LINE_JOIN_MITER)
- ctx.set_line_cap(cairo.LINE_CAP_SQUARE)
- cnt = random.randint(16, 32)
- for i in range(cnt):
- hue = (self.hue_base + random.random() * 45) % 360
- sat = 10 + random.random() * 90
- lum = 30 + random.random() * 70
- wh, hh = int(w * 0.8), int(x=h * 0.8)
- rx = (random.randint(0, wh - 1) +
- random.randint(0, wh - 1) +
- random.randint(0, wh - 1)) / 3
- ry = (random.randint(0, hh - 1) +
- random.randint(0, hh - 1) +
- random.randint(0, hh - 1)) / 3
- if random.random() < 0.8:
- # draw rectangle
- rw = int(random.random() * ((w - rx) / 2) + 1)
- rh = int(random.random() * ((h - ry) / 2) + 1)
- self.draw_rect(ctx, rx, ry, rw, rh, hue, sat, lum)
- else:
- # draw circle
- mm = min((rx, ry, (w - rx), (h - ry)))
- rr = int(random.random() * (mm * 0.4) + 2)
- self.draw_circle(ctx, rx, ry, rr, hue, sat, lum)
- if self.x_mirror:
- surface = self.mirror_x(surface)
- if self.y_mirror:
- surface = self.mirror_y(surface)
- self.surface = surface
- def get_linear_pattern(self, x, y, w, h, hue, sat, lum, hor, rpt):
- """Get gradation pattern."""
- hue = hue / 360.0
- sat = sat / 100.0
- l1 = lum
- l0 = max(((l1 - random.randint(20, 49)), 0)) / 100.0
- l2 = min(((l1 - random.randint(20, 49)), 100.0)) / 100.0
- l1 = l1 / 100.0
- rgb0 = colorsys.hls_to_rgb(hue, l0, sat)
- rgb1 = colorsys.hls_to_rgb(hue, l1, sat)
- rgb2 = colorsys.hls_to_rgb(hue, l2, sat)
- if hor:
- # horizontal gradation
- lg = cairo.LinearGradient(x, y, x + w, y)
- else:
- # vertical gradation
- lg = cairo.LinearGradient(x, y, x, y + h)
- if rpt:
- # repeat gradation
- lg.add_color_stop_rgb(0.0, rgb0[0], rgb0[1], rgb0[2])
- lg.add_color_stop_rgb(0.2, rgb1[0], rgb1[1], rgb1[2])
- lg.add_color_stop_rgb(0.5, rgb2[0], rgb2[1], rgb2[2])
- lg.add_color_stop_rgb(0.8, rgb1[0], rgb1[1], rgb1[2])
- lg.add_color_stop_rgb(1.0, rgb0[0], rgb0[1], rgb0[2])
- else:
- lg.add_color_stop_rgb(0.0, rgb0[0], rgb0[1], rgb0[2])
- lg.add_color_stop_rgb(0.5, rgb1[0], rgb1[1], rgb1[2])
- lg.add_color_stop_rgb(1.0, rgb2[0], rgb2[1], rgb2[2])
- return lg
- def draw_rect(self, ctx, x, y, w, h, hue, sat, lum):
- """Draw rectangle."""
- hor = True if random.random() < 0.5 else False
- rpt = True if random.random() < 0.3 else False
- if w <= 2 or h <= 2:
- # no border
- lg = self.get_linear_pattern(x, y, w, h, hue, sat, lum, hor, rpt)
- ctx.set_source(lg)
- ctx.rectangle(x, y, w, h)
- ctx.fill()
- else:
- # with border
- lg = self.get_linear_pattern(x, y, w, h, hue, sat, lum, hor, rpt)
- ctx.set_source(lg)
- ra = min((w, h)) / 3
- if ra <= 1 or random.random() < 0.5:
- # rectangle
- ctx.rectangle(x, y, w, h)
- else:
- # round rectangle
- self.draw_rounder_rectangle(ctx, x, y, w, h, ra)
- ctx.fill_preserve()
- ctx.set_source_rgba(0, 0, 0, self.border_alpha)
- ctx.stroke()
- def draw_rounder_rectangle(self, ctx, x, y, w, h, ra):
- """Set sub path rounded rectangle."""
- deg = math.pi / 180.0
- ctx.new_sub_path()
- ctx.arc(x + w - ra, y + ra, ra, -90 * deg, 0 * deg)
- ctx.arc(x + w - ra, y + h - ra, ra, 0 * deg, 90 * deg)
- ctx.arc(x + ra, y + h - ra, ra, 90 * deg, 180 * deg)
- ctx.arc(x + ra, y + ra, ra, 180 * deg, 270 * deg)
- ctx.close_path()
- def draw_circle(self, ctx, x, y, r, hue, sat, lum):
- """Draw cirlce."""
- l1 = lum
- la = random.randint(20, 49)
- l0 = max([(l1 - la), 0]) / 100.0
- l2 = max([(l1 + la), 100]) / 100.0
- l1 = l1 / 100.0
- hue = hue / 360.0
- sat = sat / 100.0
- rgb0 = colorsys.hls_to_rgb(hue, l0, sat)
- rgb1 = colorsys.hls_to_rgb(hue, l1, sat)
- rgb2 = colorsys.hls_to_rgb(hue, l2, sat)
- rg = cairo.RadialGradient(x, y, 0, x, y, r)
- rg.add_color_stop_rgb(1.0, rgb0[0], rgb0[1], rgb0[2])
- rg.add_color_stop_rgb(0.7, rgb1[0], rgb1[1], rgb1[2])
- rg.add_color_stop_rgb(0.0, rgb2[0], rgb2[1], rgb2[2])
- ctx.set_source(rg)
- ctx.arc(x, y, r, 0, 2 * math.pi)
- ctx.fill_preserve()
- ctx.set_source_rgba(0, 0, 0, self.border_alpha)
- ctx.stroke()
- def mirror_x(self, surface):
- """Surface X mirror."""
- w = surface.get_width()
- h = surface.get_height()
- src = surface.get_data()
- xx = int((w / 2.0) + 0.5)
- x = 0
- x1 = w - 1
- while x < xx:
- for y in range(h):
- for i in range(4):
- src[(y * w + x1) * 4 + i] = src[(y * w + x) * 4 + i]
- x += 1
- x1 -= 1
- fmt = cairo.FORMAT_ARGB32
- return cairo.ImageSurface.create_for_data(src, fmt, w, h, w * 4)
- def mirror_y(self, surface):
- """Surface Y mirror."""
- w = surface.get_width()
- h = surface.get_height()
- src = surface.get_data()
- yy = int((h / 2.0) + 0.5)
- y = 0
- y1 = h - 1
- while y < yy:
- for x in range(w):
- for i in range(4):
- src[(y1 * w + x) * 4 + i] = src[(y * w + x) * 4 + i]
- y += 1
- y1 -= 1
- fmt = cairo.FORMAT_ARGB32
- return cairo.ImageSurface.create_for_data(src, fmt, w, h, w * 4)
- if __name__ == '__main__':
- # testing
- art = TinyPixelartGrad(256, 256)
- surface = art.surface
- surface.write_to_png("result.png")
- print("Done.")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement