#!/usr/bin/env lua require "gd" require "lfs" -- Initial implementation of spiral fractal through basic cyclical geometric functions (cos,sin & etc.). -- Was originally written by me, Alexey Galiulin, in Pascal in 1994. Transfered into standard C in 1996. -- Rewritten in C++ in 1999. Current Lua version was created in 2010. m = 0; x = 0; y = 0; r = 0; s = 0; k = 0; l = 0; r1 = 0; i = 0; j = 0; pi = 3.14159265359; a = 0; b = 0; c = 0; d = 0; t = 1; printf = function(s,...) return io.write(s:format(...)) end function scanf(s, n) local n = io.stdin:read(); if s == '%i' or s == '%f' or s == '%d' or s == '%l' then return tonumber(n); else return n; end end function abssis() local abssis_result = j; if t == 1 or t == 30 or t >= 121 and t <= 123 or t == 125 or t == 126 or t >= 128 and t <= 133 or t == 135 then return math.floor(x+math.cos(i)*k+math.cos(j)*l+0.5); end if t == 6 or t == 127 or t == 134 or t == 136 or t == 138 or t >= 140 and t <= 143 or t == 145 or t == 146 or t == 148 or t == 150 then return math.floor(x+math.cos(i+math.cos(i))*k+math.cos(j-math.sin(j))*l+0.5); end if t == 7 or t == 124 or t == 137 or t == 144 or t == 147 or t == 149 then return math.floor(x+math.cos(i+math.cos(i))*k+math.cos(j-math.sin(j)*math.sin(j))*l+0.5); end if t == 9 then return math.floor(x+(math.cos(i)+math.sin(i))*k+math.cos(j)*l+0.5); end if t == 11 or t == 170 then return math.floor(x+(math.cos(i)+math.sin(i)*math.sin(i))*k+math.cos(j)*l+0.5); end if t == 12 or t == 171 then return math.floor(x+(math.cos(i)*math.sin(i)+math.sin(i)*math.sin(i))*k+math.cos(j)*l+0.5); end if t == 13 or t == 24 or t == 26 or t == 27 or t >= 37 and t <= 42 or t == 44 or t == 47 then return math.floor(x+(math.cos(i)+math.sin(i))*k+(math.cos(j)+math.sin(i))*l+0.5); end if t == 14 then return math.floor(x+(math.cos(i)+math.sin(j))*k+(math.cos(j)+math.sin(i))*l+0.5); end if t == 15 or t >= 18 and t <= 23 or t == 25 or t == 28 or t == 29 or t >= 31 and t <= 36 then return math.floor(x+(math.cos(j)+math.sin(i))*k+(math.cos(j)+math.sin(i))*l+0.5); end if t == 16 or t == 17 then return math.floor(x+(math.cos(j)+math.sin(j))*k+(math.cos(j)+math.sin(i))*l+0.5); end if t == 49 or t == 50 then return math.floor(x+math.cos(i)*2*k+math.cos(j)*l+0.5); end if t == 43 or t == 46 then return math.floor(x+math.cos(i+math.sin(i))*k+math.cos(j)*l+0.5); end if t == 45 then return math.floor(x+math.cos(i+math.cos(i))*k+math.cos(j)*l+0.5); end if t == 48 or t == 51 then return math.floor(x+math.cos(i+1/math.cos(i))*k+math.cos(j)*l+0.5); end if t == 2 or t > 104 and t < 121 or t == 139 then return math.floor(x+math.sin(i+math.sin(i))*k+math.sin(j)*l+0.5); end if t == 3 or t > 83 and t < 105 then return math.floor(x+math.sin(i+math.sin(i)/math.cos(i))*k+math.sin(j)*l+0.5); end if t > 186 then return math.floor(x+math.cos(j+math.atan(j)*math.cos(j)*math.sin(i))*k+math.cos(i)*l+0.5); end if t == 4 or t > 66 and t < 84 then return math.floor(x+math.sin(i+math.sin(i))*k+math.sin(j)*l+0.5); end if t == 5 or t > 51 and t < 67 then return math.floor(x+math.cos(i+math.cos(i))*k+math.cos(j)*l+0.5); end if t == 8 or t > 150 and t < 168 then return math.floor(x+math.cos(i+math.cos(i)*math.sin(j))*k+math.cos(j-math.sin(j)*math.sin(j))*l+0.5); end if t == 10 or t > 167 and t < 176 then return math.floor(x+(math.cos(i)+math.sin(i)*math.cos(i))*k+math.cos(j)*l+0.5); end if t > 175 and t < 183 then return math.floor(x+math.cos(math.log10(i))*k+math.cos(j)*l+0.5); end if t > 182 and t < 189 then return math.floor(x+math.cos(i+pi/math.log10(i))*k+math.cos(j)*l+0.5); end if t == 189 then return math.floor(x+math.cos(i)*k+math.cos(j+math.sin(i))*l+0.5); end if t == 190 then return math.floor(x+math.cos(i+math.cos(j))*k+math.sin(j+math.sin(i))*l+0.5); end return abssis_result; end function ordinat() local ordinat_result=i; if t == 1 or t == 19 or t == 26 or t == 52 or t == 67 or t == 84 or t == 105 or t == 151 or t == 176 or t == 183 or t == 187 then return math.floor(y-math.sin(i)*k-math.sin(j)*l+0.5); end if t == 2 or t == 25 or t == 53 or t == 85 or t == 121 or t == 127 or t == 137 or t == 152 or t == 177 or t == 184 then return math.floor(y-math.sin(i+math.sin(i))*math.cos(i)*k-math.sin(j)*math.cos(i)*l+0.5); end if t == 3 or t == 20 or t == 24 or t == 54 or t == 69 or t == 106 or t == 122 or t == 134 or t == 153 or t == 178 or t == 185 then return math.floor(y-math.sin(i+math.sin(i)/math.cos(i))*math.cos(i)*k-math.sin(j)*math.cos(i)*l+0.5); end if t == 188 then return math.floor(y-math.sin(i+math.atan(i)*math.sin(i))*k-math.sin(j)*l+0.5); end if t == 4 or t == 27 or t == 55 or t == 86 or t == 107 or t == 123 or t == 136 or t == 154 then return math.floor(y-math.sin(i+math.sin(i))*math.cos(i)*k-math.sin(j)*l+0.5); end if t == 5 or t == 6 or t == 21 or t == 37 or t == 87 or t == 108 or t == 155 then return math.floor(y-math.sin(i+math.sin(i))*k-math.sin(j)*l+0.5); end if t == 7 or t == 28 or t == 38 or t == 72 or t == 88 or t == 109 or t == 125 or t == 156 then return math.floor(y-math.sin(i+math.sin(i))*k-math.sin(j+math.cos(j))*l+0.5); end if t == 8 or t == 29 or t == 39 or t == 57 or t == 70 or t == 89 or t == 110 or t == 126 or t == 138 or t == 174 or t == 179 then return math.floor(y-math.sin(i+math.sin(i)*math.cos(j))*k-math.sin(j+math.cos(j))*l+0.5); end if t == 9 or t == 58 or t == 73 or t == 90 or t == 111 or t == 140 or t == 157 then return math.floor(y-(math.sin(i)+math.cos(i))*k-math.sin(j)*l+0.5); end if t == 10 or t == 22 or t == 40 or t == 74 or t == 91 or t == 112 or t == 128 or t == 141 or t == 158 or t == 171 then return math.floor(y-(math.sin(i)*math.sin(i)+math.cos(i))*k-math.sin(j)*l+0.5); end if t == 11 or t == 31 or t == 41 or t == 60 or t == 75 or t == 92 or t == 113 or t == 129 or t == 142 or t == 159 or t == 170 then return math.floor(y-(math.sin(i)*math.cos(i)+math.cos(i))*k-math.sin(j)*l+0.5); end if t == 12 or t == 32 or t == 42 or t == 61 or t == 76 or t == 93 or t == 114 or t == 130 or t == 143 or t == 147 or t == 160 or t == 169 then return math.floor(y-(math.sin(i)*math.cos(i)+math.cos(i)*math.cos(i))*k-math.sin(j)*l+0.5); end if t == 13 or t == 16 or t == 94 or t == 115 or t == 131 then return math.floor(y-(math.sin(i)+math.cos(i))*k-(math.sin(j)+math.cos(i))*l+0.5); end if t == 14 or t == 33 or t == 44 or t == 63 or t == 78 or t == 95 or t == 116 or t == 132 or t == 145 or t == 162 or t == 180 then return math.floor(y-(math.sin(i)+math.cos(j))*k-(math.sin(j)+math.cos(i))*l+0.5); end if t == 15 or t == 64 or t == 79 or t == 96 or t == 117 or t == 133 or t == 146 or t == 163 then return math.floor(y-(math.sin(j)+math.cos(i))*k-(math.sin(j)+math.cos(i))*l+0.5); end if t == 17 or t == 34 or t == 65 or t == 80 or t == 97 or t == 118 or t == 173 then return math.floor(y-(math.sin(i)*math.cos(i))*k-(math.sin(j)+math.cos(i))*l+0.5); end if t == 18 or t == 35 or t == 47 or t == 56 or t == 68 or t == 98 or t == 119 or t == 135 or t == 148 or t == 124 or t == 165 or t == 168 or t == 181 or t == 186 then return math.floor(y-(math.sin(i)*math.cos(j))*k-(math.sin(j)+math.cos(i))*l+0.5); end if t == 23 or t == 36 then return math.floor(y-(math.sin(i)+math.cos(i))*k-(math.sin(j)+math.cos(i))*l+0.5); end -- or t == 104 if t == 49 or t == 62 or t == 77 or t == 99 or t == 120 or t == 150 or t == 182 then return math.floor(y-math.sin(pi*0.5/math.cos(i))*k-math.sin(j)*l+0.5); end -- ended ininity if t == 50 or t == 59 or t == 100 or t == 149 or t == 161 then return math.floor(y-math.sin(math.cos(i))*k-math.sin(math.cos(j))*l+0.5); end if t == 30 or t == 71 or t == 101 or t == 164 then return math.floor(y-math.sin(i)*k+math.sin(j)*l+0.5); end if t == 43 or t == 81 or t == 102 or t == 166 or t == 172 or t == 48 then return math.floor(y-math.sin(i+math.cos(i))*k+math.sin(j)*l+0.5); end if t == 45 or t == 82 or t == 167 or t == 46 then return math.floor(y-math.sin(i+math.sin(i))*k+math.sin(j)*l+0.5); end if t == 51 or t == 66 or t == 83 or t == 103 or t == 139 or t == 144 or t == 175 or t == 104 then return math.floor(y-math.sin(i+1/math.cos(i))*k+math.sin(j)*l+0.5); end if t == 189 then return math.floor(y-math.sin(i)*k-math.sin(j)*l+0.5); end if t == 190 then return math.floor(y-math.sin(i+math.cos(j))*k-math.sin(j)*l+0.5); end return ordinat_result; end s=20; t1 = 0; par1 = ""; loop = false; screensaver = false; imagepath = "spir.jpg" methodmax = 190; if arg[1] then par1 = string.upper(arg[1]); if string.find(par1, "/H") or string.find(par1, "-H") then assert(nil, "spir(.lua) [method_number|loop circle_radius ball_radius [step [random]]]"); elseif string.find(par1, "SCREEN") then loop = true; t1 = 0; screensaver = true; if string.find(arg[0], ".exe") then imagepath = string.gsub(arg[0], ".exe", ".jpg"); elseif string.find(arg[0], ".lua") then imagepath = string.gsub(arg[0], ".lua", ".jpg"); else imagepath = string.format("%s.jpg", arg[0]); end if not string.find(imagepath, "\\") then imagepath = string.format("%s\\%s", lfs.currentdir(), imagepath); end imagename = string.gsub(imagepath, ".jpg", "s1.jpg"); batchpath = string.gsub(imagepath, ".jpg", ".bat"); ImageView=string.format("\"%s\\Windows Photo Viewer\\PhotoViewer.dll\"", os.getenv("ProgramFiles")); -- lfs.attributes(ImageView) file = io.open(ImageView,"r"); if file then file:close(file); else ImageView=string.format("%%SystemRoot%%\\system32\\shimgvw.dll"); end file = io.open(batchpath, "w"); par1=string.format("start %%SystemRoot%%\\system32\\rundll32.exe %s, ImageView_Fullscreen %%1", ImageView); file:write(par1); file:close(file); par1 = "LOOP"; elseif string.find(par1, "LOOP") then loop = true; par1 = string.gsub(par1, "LOOP", ""); t1 = tonumber(par1); if not t1 then t1 = 0; else t1 = t1 - 1; end par1 = "LOOP"; else end end x1 = 45; y1 = 5; timeMs = os.time(); randomMod = math.abs(math.sin(os.time()/1000)); print( imagepath .. " " .. timeMs .. " " .. randomMod .. " " .. math.abs(math.cos(os.time()/10000))/100 ); t = 0; color = 0; pixcol = 0; repeat -- /* clrscr(); */ -- printf("default step - %i \n", s); math.randomseed( timeMs*math.abs(math.cos(os.time()/10000))/79 ); if screensaver then for i=1,math.random(3),1 do math.random(250); end redm = math.floor(math.random(230))+20; greenm = math.floor(math.random(210)); bluem = math.floor(math.random(220))+10; else redm = 125; greenm = 177; bluem = 190; end t1 = t1 + 1; t0 = t; t = 0; if arg[1] then if par1 == "LOOP" then t = t1; if screensaver then repeat t = math.floor(math.random(methodmax-1))+1; until t ~= t0 printf( "%i (%i, %i, %i): %i, ", t1, redm, greenm, bluem, t ); else printf( "%i, ", t1 ); end else t = tonumber(arg[1]); end if not t then t = 0; end else print("interactive mode."); end while t<=0 or t>methodmax do printf("enter method from 1 to 189 - "); t = scanf("%i", t); end if arg[2] then if arg[2] == "loop" then if screensaver then x1 = math.floor(math.random(204))+45; end if x1 == 250 then return 1; end loop = true; x = x1; x1 = x1 + 1; printf( "%i, ", x ); else x = tonumber(arg[2]); end if not x then x = 0; end end while x<=25 or x>250 do printf("enter diameter from 25 to 250 - "); x = scanf("%i", x); end r1=x*2; if arg[3] then if arg[3] == "loop" then if screensaver then repeat y1 = math.floor(math.random(x-4))+1; until y1 < x-3 end if y1 == x-3 then return 1; end loop = true; y = y1; y1 = y1 + 1; printf( "%i, ", y ); else y = tonumber(arg[3]); end if not y then y = 0; end end while y<2 or y>=x-3 do printf("enter radius from 1 to %i - ", x-3); -- /* gotoxy(28+math.floor(math.log10(r1)/2.2),4); */ y = scanf("%i", y); end l = y*2; if arg[4] then s = tonumber(arg[4]); if not s then s = 4; end else if arg[1] then s = 5; end end while s<2 or s>20 do printf("enter step from 2 to 20 - "); s = scanf("%i", s); end f = 0; step=s/200; z = 0; -- initgraph(&x,&y,"."); -- setviewport(0,0,612+x*3,345+7*x,true); -- im = gd.create(x, y); -- pim = gd.createFromJpeg("./bugs.jpg") -- assert(pim) -- sx, sy = pim:sizeXY() x = 0; -- setbkcolor(1); -- setcolor(2); -- /* clrscr(); */ -- clearviewport(); if screensaver then im = gd.createTrueColor(1024, 780); y=420+3*x; x=470+x; else im = gd.createTrueColor(890, 550); y=320+3*x; x=420+x; end r=y; m=15; pixcol=2; k=r-r1; j=0; i=0; c=abssis(); d=ordinat(); i=i+step; j=j-step*r/r1+step; a=abssis(); b=ordinat(); white = im:colorAllocate(255, 255, 255); black = im:colorAllocate(0, 0, 0); -- gd.copy(im, pim, 0, 0, 0, 0, sx, sy, sx, sy); -- im:filledRectangle(0, 0, sx, sy, black); if arg[5] then im:alphaBlending(true); color1 = color; repeat color = im:colorAllocate(math.random(80), math.random(90), math.random(100)); until color ~= color1 im:colorTransparent(color); im:fill( x, y, color ); im:alphaBlending(false); -- else -- color = im:colorAllocate(0, 1, 1); end -- pim = gd.createPalette(300, 2) -- for c1 = 1, 255, 1 do -- color1 = pim:colorAllocate(255-c1, c1, c1) -- pim:setPixel(c1, 1, color1); -- end -- im:paletteCopy(pim) -- im:setPixel(c, math.floor(d/1.2), white); im:setThickness(1); z = 0; pixcol1 = pixcol; repeat pixcol=math.floor(math.random(250))+2; pixcolg=math.floor(math.random(250))+2; pixcolb=math.floor(math.random(250))+2; until pixcol1 ~= pixcol and pixcol ~= pixcolg and pixcolg ~= pixcolb repeat i=0; z = z+1; pixcol=pixcol+1; if pixcol == 255 then pixcol=2; end if screensaver then pixcolg=pixcolg+1; if pixcolg == 255 then pixcolg=2; end pixcolb=pixcolb+1; if pixcolb == 255 then pixcolb=2; end else pixcolg=pixcol+1; pixcolb=pixcol+2; end -- setcolor(pixcol); if pixcol < redm then red = pixcol; else red = pixcol-redm; end if pixcolg < greenm then green = greenm - pixcolg; else green = pixcolg-greenm; end if pixcolb < bluem then blue = bluem - pixcolb; else blue = pixcolb; end color = im:colorAllocate(red, green, blue); if not color or arg[5] and arg[5] == "random" then color = im:colorAllocate(math.floor(math.random(255)), math.floor(math.random(255)), math.floor(math.random(255))); -- color = im:colorAllocate(pixcol, pixcol, pixcol); assert(color, "can't get collor"); end im:colorTransparent(color); repeat i=i+step; j=j-step*r/r1+step; a1 = a; b1 = b; a=abssis(); b=ordinat(); im:line(a1, math.floor(b1/1.2), a, math.floor(b/1.2), color); -- im:filledRectangle(a1, math.floor(b1/1.2), a, math.floor(b/1.2), color); im:setPixel(a, math.floor(b/1.2), black) until i>=2*pi if arg[5] and arg[5] == "debug" then print(z .. " " .. a .. " " .. b); end until (c==a and d==b) or (z == 1000 and (loop or arg[6] or scanf("%c", f)=='q')) if arg[5] then im:alphaBlending(true); color = im:colorAllocate(math.random(155), math.random(155), math.random(155)) im:colorTransparent(color); im:fill( x, 5, color ); im:alphaBlending(false); end im:png("spir.png"); if arg[5] and arg[5] == "theme" then im:alphaBlending(true); for i = 0, 14 do for j = 0, 21 do if (j < 4 or j > 17) and (i < 4 or i > 10) then color = im:colorAllocate(math.random(255), math.random(255), math.random(255)) im:colorTransparent(color); im:filledArc(math.random(20)+j*40, i*40+math.random(20), math.random(40)+math.random(j+1), math.random(40)+math.random(i+1), math.random(60), 60+math.random(300), color, gd.ARC); end -- im:filledRectangle(sx+20+j*10, i*20+40, sx+30+j*10, i*20+50, rcl) -- rcl = im:colorAllocate(math.random(255), math.random(255), math.random(255)) -- im:line(sx+20+j*10, i*20+40, sx+30+j*10, i*20+50, rcl) end end im:alphaBlending(false); end if arg[5] and arg[5] == "file" and arg[6] then im:jpeg(arg[6], 100); elseif screensaver then imagename = string.gsub(imagepath, ".jpg", "s" .. t1 .. ".jpg"); im:jpeg(imagename, 100); else im:jpeg("spir" .. t1 .. ".jpg", 100); end if not loop and not arg[6] then os.execute("spir" .. t1 .. ".jpg"); elseif screensaver then print(" "); if t1 - math.floor(t1/50)*50 == 9 then imagename = string.gsub(imagepath, ".jpg", "s" .. t1-8 .. ".jpg"); os.execute(batchpath .. " " .. imagename); end end -- setcolor(2); color = im:colorAllocate(1, 1, 1); if arg[1] and par1 == "LOOP" then f = 'y'; if t1 == methodmax then f = 'n'; end elseif arg[2] and arg[2] == "loop" then f = 'y'; elseif arg[3] and arg[3] == "loop" then f = 'y'; elseif arg[1] then f = 'n'; else print("again?"); f=scanf("%c", f); end until f=='n'