textereo.awk (3193B)
1 # Textereo: ASCII stereogram generator in AWK 2 # Usage: [busybox] awk -f textereo.awk map.txt 3 # Map format: 4 # First line: [desired width] [maxpattern length] 5 # Second line: alphabet (allowed characters to generate patterns from) 6 # Next H lines: depth map, W digits from 0 to 7 without spaces 7 # You can insert single zeros or empty lines into the map to adjust height 8 # 9 # Created by Luxferre in 2023, released into public domain 10 11 function dchar(str, pos) { # delete a character from str at position pos 12 if(!pos) return str 13 else return substr(str, 1, pos - 1) substr(str, pos + 1) 14 } 15 16 function ichar(str, pos, c) { # insert a character c into str at position pos 17 return substr(str, 1, pos - 1) c substr(str, pos) 18 } 19 20 BEGIN { # we use 95-character subset from ASCII by default 21 srand() # init the PRNG 22 getline # read the first line from the file to parse parameters 23 WIDTH = int($1) # desired width of the image to generate 24 PATLEN = int($2) # generated pattern length (must be between 8 and W/2) 25 getline # read the full character set 26 CHARSET = $0 27 CHRANGE = length(CHARSET) 28 if(WIDTH == 0) WIDTH = 78 29 if(PATLEN < 8 || PATLEN > (WIDTH/2)) PATLEN = 10 # 10 to 15 is optimal 30 } 31 32 { # process the map itself 33 j = 0 # set the secondary counter to store previous value 34 FREEBUF = CHARSET # start with the full charset 35 PATBUF = "" # start with empty pattern buffer 36 mapline = $0 # cache the map line 37 RWIDTH = length(mapline); # real pattern width 38 tlen = (WIDTH - RWIDTH) / 2 # trailer AND header length 39 for(i=0;i<tlen;i++) mapline = "0" mapline "0" # grow the line to the width 40 if(length(mapline) > WIDTH) mapline = substr(mapline, 1, WIDTH) 41 for(i=0;i<PATLEN;i++) { # fill in the pattern buffer 42 do # we can repeat the characters in the pattern but not immediately 43 pbc = substr(CHARSET, 1+int(rand()*CHRANGE), 1) 44 while(pbc == j || !length(pbc)) # don't allow empty or repeating chars 45 PATBUF = PATBUF pbc # concatenate the character to the pattern 46 j = pbc # save as the previous value to j 47 # delete this character from the unused buffer 48 FREEBUF = dchar(FREEBUF, index(FREEBUF, pbc)) 49 } 50 j = 0 # reset the secondary counter 51 prevlen = PATLEN # cache the previous pattern length 52 maplen = length(mapline) 53 patpos = 0 # track pattern position 54 for(i=0;++i<=maplen;) { # iterate over every character 55 curlen = PATLEN - int(substr(mapline, i, 1)) # extract depth value and length 56 delta = curlen - prevlen 57 if(delta > 0) # add unused characters if decreasing depth value 58 for(j=0;j<delta;j++) { 59 ri = 1+int(rand()*length(FREEBUF)) # get random index 60 rc = substr(FREEBUF, ri, 1) # retrieve the character 61 FREEBUF = dchar(FREEBUF, ri) # delete it from the buffer 62 PATBUF = ichar(PATBUF, 1+patpos, rc) # insert it here 63 } 64 else if(delta < 0) # remove characters if increasing depth value 65 for(j=0;j<-delta;j++) 66 PATBUF = dchar(PATBUF, 1+patpos) 67 prevlen = curlen # update the previous length 68 # now, output the current pattern character 69 printf("%c", substr(PATBUF, 1 + (patpos % curlen), 1)) 70 patpos = (patpos + 1) % curlen # update pattern position 71 } 72 printf("\n") 73 }