# 2D.py

a guest
Mar 3rd, 2014
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1.
2. import random
3. import numpy as np
4. import math
5. try:
6.     from PIL import Image      # necessary for manipulation with images
7.     from PIL import ImageFilter
8.     from PIL import ImageDraw,ImageFont
9. except:
10.     print (" Warning: Failed to load Pillow (Imaging) modules!")
11.     print (" Pillow (fork of PIL) should be available in repositories")
13.     exit()
14.
15.
16. length=2**10  #working size
17. rough_intensity=1.5  #1.5 good
18. rough_gamma=1.3      #0.85good
19. highcropprc=2
20. lowcropprc=5 #% water surface effectively
21. map_size=384  # final size in widelands
22. minavg=0.2
23. maxavg=0.45
24. seed_intensity=0.15 # 0.66 good, inserting additional randomnes before running diamond square algorithm
25.
26.
27.
28. px_array=np.zeros(shape=(length,length),dtype=float)
29. blur_array=np.zeros(shape=(length,length),dtype=float)
30.
31. def new_RGB(bp1,bp2,value,R1,G1,B1,R2,G2,B2):
32.     ratio=(float(value)-bp1)/(bp2-bp1)
33.     Rnew=R1*(1-ratio)+ R2*ratio
34.     Gnew=G1*(1-ratio)+ G2*ratio
35.     Bnew=B1*(1-ratio)+ B2*ratio
36.     return Rnew,Gnew,Bnew
37.
38. def wrap(value):
39.     if value>=length:
40.         return value-length
41.     if value<0:
42.         return value+length
43.     return value
44.
45.
46.
47. k=0
48. listofdef=[0,0.1,0.2,0.8,0.9,1]
49. while k<10:  #generates 10 fractals (=10 jpg images and txt files with heights)
50.     print ("Fractal: "+str(k+1))
51.
52.     lowcount=0
53.     highcount=1
54.     px_array.fill(-100)    #defaults
55.     px_array[0 , 0]=random.uniform(0,1)   #at least one value must be given to start fractal generation
56.
57.     #this is an exemption to fractal algorithm but we need to add more randomness/irregularity
58.     for i in range(8):
59.         for j in range(8):
60.             if random.uniform(0,1) > (1- seed_intensity):
61.                 i_l=int(i/8.0*length)
62.                 j_l=int(j/8.0*length)
63.                 px_array[i_l, j_l]=random.choice(listofdef)
64.
65.     sqsize=length
66.
67.     while sqsize >1:
68.         roughness=math.pow(rough_intensity*float(sqsize)/length,rough_gamma)
69.         print ("  sqsize: "+str(sqsize)+", roughness: " +str(round(roughness,3)))
70.         #iterating over line, starting on 0+sqsize/2
71.
72.         pixel_x_pos=0+sqsize/2
73.
74.         while pixel_x_pos<length:
75.             pixel_y_pos=0+sqsize/2
76.             while pixel_y_pos<length:
77.                 px1=    px_array[wrap(pixel_x_pos-sqsize/2) , wrap(pixel_y_pos-sqsize/2)]
78.                 px2=    px_array[wrap(pixel_x_pos-sqsize/2) , wrap(pixel_y_pos+sqsize/2)]
79.                 px3=    px_array[wrap(pixel_x_pos+sqsize/2) , wrap(pixel_y_pos-sqsize/2)]
80.                 px4=    px_array[wrap(pixel_x_pos+sqsize/2) , wrap(pixel_y_pos+sqsize/2)]
81.
82.                 new_value=(px1+px2+px3+px4)/4.0 + random.uniform(-1,1)*roughness
83.                 if new_value>1:
84.                     highcount+=1
85.                 if new_value<0:
86.                     lowcount+=1
87.                 if px1==-100 or px2==-100 or px3==-100 or px4==-100:
88.                     print ("   touched wrong pixel: "+str(pixel_x_pos)+" x "+str(pixel_y_pos))
89.                     #exit()
90.
91.                 px_array[pixel_x_pos , pixel_y_pos]=new_value
92.                 pixel_y_pos=pixel_y_pos+sqsize
93.             pixel_x_pos=pixel_x_pos+sqsize
94.
95.
96.         #iterating once more and populating not calculated pixels
97.         pixel_x_pos=0
98.
99.         while pixel_x_pos<length:
100.             pixel_y_pos=0
101.             while pixel_y_pos<length:
102.                 #print (pixel_x_pos,pixel_y_pos)
103.                 if px_array[pixel_x_pos,pixel_y_pos]>-100:   #never change yet calculated pixel
104.                     pixel_y_pos=pixel_y_pos+sqsize/2
105.                     continue
106.
107.                 px1=    px_array[wrap(pixel_x_pos-sqsize/2) , pixel_y_pos]
108.                 px2=    px_array[wrap(pixel_x_pos+sqsize/2) , pixel_y_pos]
109.                 px3=    px_array[pixel_x_pos , wrap(pixel_y_pos-sqsize/2)]
110.                 px4=    px_array[pixel_x_pos , wrap(pixel_y_pos+sqsize/2)]
111.                 if px1==-100 or px2==-100 or px3==-100 or px4==-100:
112.                     print ("   touched wrong pixel: "+str(pixel_x_pos)+" x "+str(pixel_y_pos))
113.                     #exit()
114.
115.                 new_value=(px1+px2+px3+px4)/4.0 + random.uniform(-1,1)*roughness
116.                 if new_value>1:
117.                     highcount+=1
118.                 if new_value<0:
119.                     lowcount+=1
120.                 #print (str(new_value)+" ( pure avg="+str((px1+px2+px3+px4)/4.0)+")    on pos :"+str(pixel_x_pos)+"  x  "+str(pixel_y_pos))
121.
122.                 px_array[pixel_x_pos , pixel_y_pos]=new_value
123.
124.                 pixel_y_pos=pixel_y_pos+sqsize/2
125.             pixel_x_pos=pixel_x_pos+sqsize/2
126.
127.         sqsize=sqsize/2
128.
129.
130.     newImage = Image.new( 'RGB', (length,length), "black")
131.
132.     #blurring the image
133.     for i in range(length):
134.         for j in range(length):
135.             if px_array[i][j]==-100:
136.                 print ("unpopulated pixel")
137.                 exit()
138.             blur_array[i,j]=(px_array[i,j] + px_array[i,j] + px_array[wrap(i+1),wrap(j)] +
139.             px_array[wrap(i-1),wrap(j)] + px_array[wrap(i),wrap(j+1)] + px_array[wrap(i),wrap(j-1)])/ 6.0
140.     #iteration 2
141.     for i in range(length):
142.         for j in range(length):
143.             px_array[i,j]=(blur_array[i,j]  + px_array[i,j] + blur_array[wrap(i+1),wrap(j)] +
144.             blur_array[wrap(i-1),wrap(j)] +  blur_array[wrap(i),wrap(j+1)] + blur_array[wrap(i),wrap(j-1)])/ 6.0
145.     #iteration 3
146.     for i in range(length):
147.         for j in range(length):
148.             blur_array[i,j]=(px_array[i,j] + px_array[i,j] + px_array[wrap(i+1),wrap(j)] +
149.             px_array[wrap(i-1),wrap(j)] + px_array[wrap(i),wrap(j+1)] + px_array[wrap(i),wrap(j-1)])/ 6.0
150.     #iteration 4
151.     for i in range(length):
152.         for j in range(length):
153.             px_array[i,j]=(blur_array[i,j]  + px_array[i,j] + blur_array[wrap(i+1),wrap(j)] +
154.             blur_array[wrap(i-1),wrap(j)] +  blur_array[wrap(i),wrap(j+1)] + blur_array[wrap(i),wrap(j-1)])/ 6.0
155.
156.     #normalizing the image, calculating minvalue and maxvalue
157.     minvalue=10
158.     maxvalue=-10
159.
160.     for i in range(length):
161.         #print(str(i)+" : "+str(px_array[i]))
162.         for j in range(length):
163.
164.             if  px_array[i][j]<minvalue:
165.                     minvalue=px_array[i][j]
166.             elif  px_array[i][j]>maxvalue:
167.                     maxvalue=px_array[i][j]
168.
169.
170.     print ("  Raw fractal values range: "+str(round(minvalue,2)) + " - "+ str(round(maxvalue,2)))  #+", avg: "+str(avgvaluesum/count))
171.
172.     #ordering all pixel values
173.     allpx=[]
174.     for i in range(0,length,2):
175.         for j in range(0,length,2):
176.             allpx.append(px_array[i][j])
177.     allpx=sorted(allpx)
178.
179.     lowvalue =allpx[int((lowcropprc/100.0)*len(allpx))]   #this and everything below will be water at level 0
180.     highvalue=allpx[int(((100-highcropprc)/100.0)*len(allpx))]   #this and all above will be top on level 60
181.     print ("  Cropping top and bottoms at: "+str(round(lowvalue,2))+ " / "+str(round(highvalue,2)))
182.
183.
184.     lowcount=0
185.     hightcount=0
186.     avgvaluesum=0
187.     count=0.0
188.     #recalculating image
189.     for i in range(length):
190.         for j in range(length):
191.
192.             if px_array[i][j]>highvalue:
193.                 highcount+=1
194.                 px_array[i][j]=1
195.             elif px_array[i][j]<lowvalue:
196.                 lowcount+=1
197.                 px_array[i][j]=0
198.             else:
199.                 #print (str(px_array[i][j])+ " to")
200.                 px_array[i][j]=(px_array[i][j]-lowvalue)/(highvalue-lowvalue)
201.                 #print (str(px_array[i][j]))
202.                 avgvaluesum+=px_array[i,j]  #=math.pow(px_array[i,j],1.3)   #gamma
203.                 count+=1
204.
205.     avg=float(avgvaluesum)/count
206.
207.     print ("  Average of non-limit pixels: "+str(round(avg,3))+", image split: "+str(lowcount) +" / "+str(count)+" / "+str(highcount))
208.
209.
210.     gamma=1
211.     avgvaluesum=0
212.     count=0.0
213.     if avg<minavg:
214.         gamma=(avg/minavg)**2
215.         #applying gamma
216.         for i in range(length):
217.             for j in range(length):
218.                 if  px_array[i][j]<1 and  px_array[i][j]>0:
219.                     px_array[i][j]=pow(px_array[i][j],gamma)
220.                     avgvaluesum=avgvaluesum+px_array[i][j]
221.                     count+=1
222.     elif avg>maxavg:
223.         gamma=(avg/maxavg)
224.         #applying gamma
225.         for i in range(length):
226.             for j in range(length):
227.                 if  px_array[i][j]<1 and  px_array[i][j]>0:
228.                     px_array[i][j]=pow(px_array[i][j],gamma)
229.                     avgvaluesum=avgvaluesum+px_array[i][j]
230.                     count+=1
231.     if count>0:
232.         print ("  applying gamma: "+ str(round(gamma,2))+"(if needed), new average:"+str(round(float(avgvaluesum)/count,2)))
233.
234.
235.
236.     #verifying the results the image, calculating minvalue and maxvalue
237.     minvalue=10
238.     maxvalue=-10
239.     for i in range(length):
240.         #print(str(i)+" : "+str(px_array[i]))
241.         for j in range(length):
242.             if  px_array[i][j]<minvalue:
243.                     minvalue=px_array[i][j]
244.             if  px_array[i][j]>maxvalue:
245.                     maxvalue=px_array[i][j]
246.
247.     print ("  Modified image value range: "+str(minvalue) + " - "+ str(maxvalue))
248.
249.
250.
251.
252.     #output as jpg image
253.     P1R=0   #grass
254.     P1G=70
255.     P1B=0
256.     P2R=61  #light green
257.     P2G=114
258.     P2B=61
259.     P3R=112   #light brown
260.     P3G=112
261.     P3B=76
262.     P4R=56 #dark brown
263.     P4G=55
264.     P4B=5
265.     P5R=210
266.     P5G=209
267.     P5B=203
268.
269.     for i in range(length):
270.         #print(str(i)+" : "+str(px_array[i]))
271.         for j in range(length):
272.             if px_array[i][j]==-100:
273.                 print ("unpopulated pixel")
274.                 exit()
275.             value=px_array[i][j]*255
276.             if value<=0:
277.                 finalR=0
278.                 finalG=115
279.                 finalB=232
280.             elif value<60:
281.                 finalR,finalG,finalB = new_RGB(0,60,value,P1R,P1G,P1B,P2R,P2G,P2B)
282.             elif value<130:
283.                 finalR,finalG,finalB = new_RGB(60,130,value,P2R,P2G,P2B,P3R,P3G,P3B)
284.             elif value<215:
285.                 finalR,finalG,finalB = new_RGB(130,215,value,P3R,P3G,P3B,P4R,P4G,P4B)
286.             else:
287.                 finalR,finalG,finalB = new_RGB(215,255,value,P5R,P5G,P5B,255,255,255)
288.
289.             newImage.putpixel((i,j),(int(finalR),int(finalG),int(finalB)))
290.
291.     newname="Terrain_"+str(k+1)+".jpg"
292.     newImage.save(newname,quality=98)
293.
294.
295.     #output to file
296.     filename="import_coordinates_"+str(k+1)+".txt"
297.     f = open(filename, 'w')
298.     for i in range(map_size):
299.         x=round(float(i)/map_size*length)
300.         #print (" calculating : " +str(i) + "->"+str(x))
301.         for j in range(map_size):
302.             offset=0
303.             if j%2==1:
304.                 offset=0.5
305.             y=round(float(j+offset)/map_size*length)
306.             if px_array[x][y]==0:
307.                 value=0
308.             else:
309.                 value=min ((px_array[x][y]*60.0)+1 , 60)
310.                 value=max(value,0)
311.                 value=int(value)
312.             f.write(str(i)+" "+str(j)+" "+str(value)+'\n')
313.         f.write (' \n')
314.     f.close
315.
316.     k=k+1