Automatic Mondrian

J'ai toujours pensé que Piet Mondrian (1872-1944) utilisait un ordinateur. La preuve en 175 lignes...

I guess Mondrian (1872-1944) used a computer: as a 175-lined clue...

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
 #! /usr/bin/python -Qnew
# -*- coding: utf-8 -*-
import random, time, os
 
# Automatic Mondrian (Pieter Cornelis "Piet" Mondriaan, 1872-1944)
# v 1.1- 2014, 30 september - GPL 2 by Jean-Christophe BEUMIER
 
# How does it work?
# 1. Creating an image with a light gray background and drawing a frame
# 2. (several times) if (random) x,y is gray and not too close to a line:
#       dividing field (random) by horizontal or vertical line
# 3. if (random) x,y is gray: colouring the field
 
# Rough & dirty written! Known bugs and weaknesses:
# 1. a colour (light gray, red, yellow or blue) can be missing
#    -> if you cannot stand it, delete the file and try another picture
# 2. if your system doesn't have imagemagick, PNM format is heavy; for this
#    kind of picture: 720Ko PNM = about 5Ko GIF = about 1Ko PNG '5' 
#    -> convert it through a picture processor application 
 
# ver 1.1 improvement: lines couldn't cross: processing by dividing fields
#    -> I add an exception, completing the line, by default three times
 
 
# picture dimensions (px) - any size you like, not too little:
width=600
height=400
thick=8 # line width
gray=chr(216) # default colour: very light gray
dark=chr(32) # line: very dark gray
cross=3 # possibility of crossing lines
 
tab=[gray]*width*height*3 # nbr of pixel (RVB: 3 bytes per colour)
nbr=20 # max number of division
clr=[[chr(255),chr(30),chr(30)],[chr(255),chr(255),chr(64)],[chr(0),chr(100),chr(255)]] # red RVB / yellow RVB / blue RVB : Mondrian colours
 
header="P6 %s %s 255\n" %(width, height) # PNM file colour/raw data
 
# framing
for j in range(0,width):
  for i in range(0,thick):
    point=width*3*i+j*3
    tab[(point)]=dark
    tab[point+1]=dark
    tab[point+2]=dark
  for i in range(height-thick,height):
    point=width*3*i+j*3
    tab[point]=dark
    tab[point+1]=dark
    tab[point+2]=dark
for j in range(0,height):
  for i in range(0,thick):
    point=width*3*j+i*3
    tab[(point)]=dark
    tab[point+1]=dark
    tab[point+2]=dark
  for i in range(width-thick,width):
    point=width*3*j+i*3
    tab[point]=dark
    tab[point+1]=dark
    tab[point+2]=dark
 
# drawing
for r in range(nbr): # attempts 'r' times
  # random inner point
  x=thick+random.randrange(width-thick*3)
  y=thick+random.randrange(height-thick*3)
 
  flag1=1
  for i in range(-thick,thick*2):
    if tab[(width*y+x+i)*3]!=gray:
      flag1=0 # vertically too close
  flag0=1
  for j in range(-thick,thick*2):
    if tab[(width*(y+j)+x)*3]!=gray:
      flag0=0 # horizontally too close
 
  thru=False # ver 1.1 improving
  if r<cross: thru=True # possibility of lines through others
 
  hasard=random.randrange(2) # vertical (1) or horizontal (0) line
  if hasard==1 and flag1: # vertical ligne, not too close
    prog=0
    if thru: # ver 1.1 improving
      for k in range(0+thick,height-thick):
        for i in range(thick):
          tab[(k*width+x+i)*3]=dark
          tab[(k*width+x+i)*3+1]=dark
          tab[(k*width+x+i)*3+2]=dark
    else:
      while tab[((y-prog-1)*width+x)*3]==gray:
        for i in range(thick):
          tab[((y-prog-1)*width+x+i)*3]=dark
          tab[((y-prog-1)*width+x+i)*3+1]=dark
          tab[((y-prog-1)*width+x+i)*3+2]=dark
        prog+=1
      prog=0
      while tab[((y+prog)*width+x)*3]==gray:
        for i in range(thick):
          tab[((y+prog)*width+x+i)*3]=dark
          tab[((y+prog)*width+x+i)*3+1]=dark
          tab[((y+prog)*width+x+i)*3+2]=dark
        prog+=1
 
  if hasard==0 and flag0: # horizontal ligne, not too close
    if thru: # ver 1.1 improving
      for k in range(0+thick,width-thick):
        for i in range(thick):
          tab[((y+i)*width+k)*3]=dark
          tab[((y+i)*width+k)*3+1]=dark
          tab[((y+i)*width+k)*3+2]=dark
    else:
      prog=0
      while tab[(width*y+x-prog-1)*3]==gray:
        for i in range(thick):
          tab[(width*(y+i)+x-prog-1)*3]=dark
          tab[(width*(y+i)+x-prog-1)*3+1]=dark
          tab[(width*(y+i)+x-prog-1)*3+2]=dark
        prog+=1
      prog=0
      while tab[(width*y+x+prog)*3]==gray:
        for i in range(thick):
          tab[(width*(y+i)+x+prog)*3]=dark
          tab[(width*(y+i)+x+prog)*3+1]=dark
          tab[(width*(y+i)+x+prog)*3+2]=dark
        prog+=1
 
# colouring
for r in range(nbr): # attempts 'r' times
  x=random.randrange(width)
  y=random.randrange(height)
  if tab[(width*y+x)*3]==gray: # but works only on gray parts of picture
    prog=0
    while tab[(width*y+x+prog-1)*3]==gray:
      prog-=1
    left=x+prog # determining left abscissa of rectangle
    prog=0
    while tab[(width*y+x+prog+1)*3]==gray:
      prog+=1
    right=x+prog # determining right abscissa of rectangle
    prog=0
    while tab[(width*(y+prog-1)+x)*3]==gray:
      prog-=1
    up=y+prog # determining top ordinate of rectangle
    prog=0
    while tab[(width*(y+prog+1)+x)*3]==gray:
      prog+=1 # determining bottom ordinate of rectangle
    down=y+prog
 
    teinte=clr[random.randrange(3)] # random colour of rectangle
    for i in range(left,right+1): # filling rectangle
      for j in range(up,down+1):
       tab[(i+width*j)*3]=teinte[0]
       tab[(i+width*j)*3+1]=teinte[1]
       tab[(i+width*j)*3+2]=teinte[2]
 
image=header+"".join(tab) # header + joining data from list
temps=time.time() # number of second since 1970.01.01 0h00:00
name="mondrian"+str(temps)
 
han=open(name+".pnm","w") # saving picture
han.write(image)
han.close()
 
try:
  # only with imagemagick on your system:
  os.system("convert "+name+".pnm "+name+".png")
  os.remove(name+".pnm") 
except: # I didn't check: imagemagick is on my system
  print """
imagemagick is not on your system
PNM file P6 colour & raw data: rather heavy file
"""

Je ne sais pas ce que vous en pensez... Do you know what?...

 

Mais je trouve que celles-ci sont bien mieux... I find these are much better...

 

...que celles de Mondrian!  ...than Mondrian's one!

 

Cette dernière avec la version 1.1: deux ou trois lignes peuvent se croiser!

This one with ver1.1 improvement:some crossing lines are permitted!