Advertisement
Guest User

Untitled

a guest
Apr 27th, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.28 KB | None | 0 0
  1. #!python
  2. # -*- mode: python; Encoding: utf-8; coding: utf-8 -*-
  3. # Last updated: <2017/04/27 09:46:11 +0900>
  4.  
  5. u"""
  6. tinypixelargrad.py - generate tiny pixelart.
  7.  
  8. Drawing with cairo(pycairo).
  9.  
  10. testing environment :
  11. Windows10 x64 + Python 2.7.13 32bit + pycairo 1.8.10
  12.  
  13. Author: mieki256
  14. License: CC0 / Public Domain
  15. """
  16.  
  17. import cairo
  18. import random
  19. import colorsys
  20. import math
  21.  
  22.  
  23. class TinyPixelartGrad(object):
  24.  
  25. """Generate tiny pixelart."""
  26.  
  27. def __init__(self, w, h, seed=None,
  28. x_mirror=None, y_mirror=None, hue=None,
  29. border_width=1.0, border_alpha=1.0):
  30. """Generate tiny pixelart."""
  31. if seed is None:
  32. random.seed()
  33. else:
  34. random.seed(seed)
  35.  
  36. if x_mirror is None:
  37. self.x_mirror = True if random.random() > 0.5 else False
  38. else:
  39. self.x_mirror = x_mirror
  40.  
  41. if y_mirror is None:
  42. self.y_mirror = True if random.random() > 0.5 else False
  43. else:
  44. self.y_mirror = y_mirror
  45.  
  46. self.border_width = border_width
  47. self.border_alpha = border_alpha
  48. self.hue_base = random.random() * 360 if hue is None else hue
  49.  
  50. surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
  51. ctx = cairo.Context(surface)
  52. ctx.set_antialias(cairo.ANTIALIAS_NONE)
  53. ctx.set_line_width(self.border_width)
  54. ctx.set_line_join(cairo.LINE_JOIN_MITER)
  55. ctx.set_line_cap(cairo.LINE_CAP_SQUARE)
  56.  
  57. cnt = random.randint(16, 32)
  58. for i in range(cnt):
  59. hue = (self.hue_base + random.random() * 45) % 360
  60. sat = 10 + random.random() * 90
  61. lum = 30 + random.random() * 70
  62. wh, hh = int(w * 0.8), int(x=h * 0.8)
  63. rx = (random.randint(0, wh - 1) +
  64. random.randint(0, wh - 1) +
  65. random.randint(0, wh - 1)) / 3
  66. ry = (random.randint(0, hh - 1) +
  67. random.randint(0, hh - 1) +
  68. random.randint(0, hh - 1)) / 3
  69. if random.random() < 0.8:
  70. # draw rectangle
  71. rw = int(random.random() * ((w - rx) / 2) + 1)
  72. rh = int(random.random() * ((h - ry) / 2) + 1)
  73. self.draw_rect(ctx, rx, ry, rw, rh, hue, sat, lum)
  74. else:
  75. # draw circle
  76. mm = min((rx, ry, (w - rx), (h - ry)))
  77. rr = int(random.random() * (mm * 0.4) + 2)
  78. self.draw_circle(ctx, rx, ry, rr, hue, sat, lum)
  79. if self.x_mirror:
  80. surface = self.mirror_x(surface)
  81. if self.y_mirror:
  82. surface = self.mirror_y(surface)
  83. self.surface = surface
  84.  
  85. def get_linear_pattern(self, x, y, w, h, hue, sat, lum, hor, rpt):
  86. """Get gradation pattern."""
  87. hue = hue / 360.0
  88. sat = sat / 100.0
  89. l1 = lum
  90. l0 = max(((l1 - random.randint(20, 49)), 0)) / 100.0
  91. l2 = min(((l1 - random.randint(20, 49)), 100.0)) / 100.0
  92. l1 = l1 / 100.0
  93. rgb0 = colorsys.hls_to_rgb(hue, l0, sat)
  94. rgb1 = colorsys.hls_to_rgb(hue, l1, sat)
  95. rgb2 = colorsys.hls_to_rgb(hue, l2, sat)
  96. if hor:
  97. # horizontal gradation
  98. lg = cairo.LinearGradient(x, y, x + w, y)
  99. else:
  100. # vertical gradation
  101. lg = cairo.LinearGradient(x, y, x, y + h)
  102.  
  103. if rpt:
  104. # repeat gradation
  105. lg.add_color_stop_rgb(0.0, rgb0[0], rgb0[1], rgb0[2])
  106. lg.add_color_stop_rgb(0.2, rgb1[0], rgb1[1], rgb1[2])
  107. lg.add_color_stop_rgb(0.5, rgb2[0], rgb2[1], rgb2[2])
  108. lg.add_color_stop_rgb(0.8, rgb1[0], rgb1[1], rgb1[2])
  109. lg.add_color_stop_rgb(1.0, rgb0[0], rgb0[1], rgb0[2])
  110. else:
  111. lg.add_color_stop_rgb(0.0, rgb0[0], rgb0[1], rgb0[2])
  112. lg.add_color_stop_rgb(0.5, rgb1[0], rgb1[1], rgb1[2])
  113. lg.add_color_stop_rgb(1.0, rgb2[0], rgb2[1], rgb2[2])
  114. return lg
  115.  
  116. def draw_rect(self, ctx, x, y, w, h, hue, sat, lum):
  117. """Draw rectangle."""
  118. hor = True if random.random() < 0.5 else False
  119. rpt = True if random.random() < 0.3 else False
  120. if w <= 2 or h <= 2:
  121. # no border
  122. lg = self.get_linear_pattern(x, y, w, h, hue, sat, lum, hor, rpt)
  123. ctx.set_source(lg)
  124. ctx.rectangle(x, y, w, h)
  125. ctx.fill()
  126. else:
  127. # with border
  128. lg = self.get_linear_pattern(x, y, w, h, hue, sat, lum, hor, rpt)
  129. ctx.set_source(lg)
  130. ra = min((w, h)) / 3
  131. if ra <= 1 or random.random() < 0.5:
  132. # rectangle
  133. ctx.rectangle(x, y, w, h)
  134. else:
  135. # round rectangle
  136. self.draw_rounder_rectangle(ctx, x, y, w, h, ra)
  137. ctx.fill_preserve()
  138. ctx.set_source_rgba(0, 0, 0, self.border_alpha)
  139. ctx.stroke()
  140.  
  141. def draw_rounder_rectangle(self, ctx, x, y, w, h, ra):
  142. """Set sub path rounded rectangle."""
  143. deg = math.pi / 180.0
  144. ctx.new_sub_path()
  145. ctx.arc(x + w - ra, y + ra, ra, -90 * deg, 0 * deg)
  146. ctx.arc(x + w - ra, y + h - ra, ra, 0 * deg, 90 * deg)
  147. ctx.arc(x + ra, y + h - ra, ra, 90 * deg, 180 * deg)
  148. ctx.arc(x + ra, y + ra, ra, 180 * deg, 270 * deg)
  149. ctx.close_path()
  150.  
  151. def draw_circle(self, ctx, x, y, r, hue, sat, lum):
  152. """Draw cirlce."""
  153. l1 = lum
  154. la = random.randint(20, 49)
  155. l0 = max([(l1 - la), 0]) / 100.0
  156. l2 = max([(l1 + la), 100]) / 100.0
  157. l1 = l1 / 100.0
  158. hue = hue / 360.0
  159. sat = sat / 100.0
  160. rgb0 = colorsys.hls_to_rgb(hue, l0, sat)
  161. rgb1 = colorsys.hls_to_rgb(hue, l1, sat)
  162. rgb2 = colorsys.hls_to_rgb(hue, l2, sat)
  163. rg = cairo.RadialGradient(x, y, 0, x, y, r)
  164. rg.add_color_stop_rgb(1.0, rgb0[0], rgb0[1], rgb0[2])
  165. rg.add_color_stop_rgb(0.7, rgb1[0], rgb1[1], rgb1[2])
  166. rg.add_color_stop_rgb(0.0, rgb2[0], rgb2[1], rgb2[2])
  167. ctx.set_source(rg)
  168. ctx.arc(x, y, r, 0, 2 * math.pi)
  169. ctx.fill_preserve()
  170. ctx.set_source_rgba(0, 0, 0, self.border_alpha)
  171. ctx.stroke()
  172.  
  173. def mirror_x(self, surface):
  174. """Surface X mirror."""
  175. w = surface.get_width()
  176. h = surface.get_height()
  177. src = surface.get_data()
  178. xx = int((w / 2.0) + 0.5)
  179. x = 0
  180. x1 = w - 1
  181. while x < xx:
  182. for y in range(h):
  183. for i in range(4):
  184. src[(y * w + x1) * 4 + i] = src[(y * w + x) * 4 + i]
  185. x += 1
  186. x1 -= 1
  187. fmt = cairo.FORMAT_ARGB32
  188. return cairo.ImageSurface.create_for_data(src, fmt, w, h, w * 4)
  189.  
  190. def mirror_y(self, surface):
  191. """Surface Y mirror."""
  192. w = surface.get_width()
  193. h = surface.get_height()
  194. src = surface.get_data()
  195. yy = int((h / 2.0) + 0.5)
  196. y = 0
  197. y1 = h - 1
  198. while y < yy:
  199. for x in range(w):
  200. for i in range(4):
  201. src[(y1 * w + x) * 4 + i] = src[(y * w + x) * 4 + i]
  202. y += 1
  203. y1 -= 1
  204. fmt = cairo.FORMAT_ARGB32
  205. return cairo.ImageSurface.create_for_data(src, fmt, w, h, w * 4)
  206.  
  207. if __name__ == '__main__':
  208. # testing
  209. art = TinyPixelartGrad(256, 256)
  210. surface = art.surface
  211. surface.write_to_png("result.png")
  212. print("Done.")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement