/* * pnmtartan - synthesize tartan images * * pnmtartan [options] threading... * * The threading is given as multiple args, each one specifying a * number and a colour, number first. The number is the thread count; * the colour is the colour of the threads. The colour can be a * single letter, R G B C M Y W K, indicating, respectively, red, * green, blue, cyan, magenta, yellow, white, and black; it can also * be an RGB triple given as /red/green/blue, or RGBA as * /red/green/blue/alpha. Either of these can have a letter (not * restricted to the aforementioned eight) and an equal sign prefixed * to it; this makes that letter equivalent to that colour for future * use. The letter-and-equal-sign syntax can also be given without a * number, or with the number 0, in which case it just defines the * letter without adding any threads. * * By default, a symmetric tartan is produced; in this case, the first * and last items in the thread list are the pivot rows of the sett. * The pivots should be their full width, not half that. For example, * specifying 3R 6G 2W results in a tartan threaded 3R 6G 2W 6G 3R 6G * 2W 6G 3R etc, not the 3R 6G 4W 6G 6R 6G 4W 6G etc that would result * from duplicating the first and last entries. If -asymm is given, * the threading list is used directly, making it possible to produce * asymmetric tartans. By default, the same threading pattern is used * for both dimensions. If a / appears in the threading, the pattern * before it is for the X dimension; after, Y. * * Different weave patterns are available. The examples below use the * simplest weave, obtainable with "-weave 1", for compactness; this * is a simple over/under checkerboard. The default weave pattern is * "-weave 2", producing iamges much more like real tartans. * * By default, the output contains one full tile of the tartan in each * dimension, the smallest that can be produced such that tiling it * yields the correct results. Depending on the weave and the * threading, this can be as little as one sett, or it may be more. * The aforementioned 3R 6G 2W tartan with -weave 1, for example, * would produce a 34x34 image; it would be 17x17, except that the * checkerboard of the weave would not match up correctly in that * case. Consider a smaller example, 1R 1G 2W with -weave 1. The * basic repeating colour sequence is R G W W G, but a 5x5 picture * based on that * * R G W W G * ’—’’’—’– •’—’’’—’– •’—’’’—’ * R R ™ G ™ R ™ W ™ R * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’– •’—’’’—’– •’—’’’—’– •’ * G ™ R ™ G ™ W ™ G ™ G ™ * ’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’—’’’—’– •’—’’’—’– •’—’’’—’ * W W ™ G ™ W ™ W ™ W * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’– •’—’’’—’– •’—’’’—’– •’ * W ™ R ™ W ™ W ™ W ™ G ™ * ’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’—’’’—’– •’—’’’—’– •’—’’’—’ * G G ™ G ™ G ™ W ™ R * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * * would tile as * * ’—’’’—’– •’—’’’—’– •’—’’’—’—’’’—’– •’—’’’—’– •’—’’’—’ * R ™ G ™ R ™ W ™ R R ™ G ™ R ™ W ™ R * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’– •’—’’’—’– •’—’’’—’– •’– •’—’’’—’– •’—’’’—’– •’ * ™ R ™ G ™ W ™ G ™ G ™ ™ R ™ G ™ W ™ G ™ G ™ * ’– •’˜’’’˜’– •’˜’’’˜’– •’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’—’’’—’– •’—’’’—’– •’—’’’—’—’’’—’– •’—’’’—’– •’—’’’—’ * W ™ G ™ W ™ W ™ W W ™ G ™ W ™ W ™ W * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’– •’—’’’—’– •’—’’’—’– •’– •’—’’’—’– •’—’’’—’– •’ * ™ R ™ W ™ W ™ W ™ G ™ ™ R ™ W ™ W ™ W ™ G ™ * ’– •’˜’’’˜’– •’˜’’’˜’– •’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’—’’’—’– •’—’’’—’– •’—’’’—’—’’’—’– •’—’’’—’– •’—’’’—’ * G ™ G ™ G ™ W ™ R G ™ G ™ G ™ W ™ R * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’—’’’—’– •’—’’’—’– •’—’’’—’—’’’—’– •’—’’’—’– •’—’’’—’ * R ™ G ™ R ™ W ™ R R ™ G ™ R ™ W ™ R * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’– •’—’’’—’– •’—’’’—’– •’– •’—’’’—’– •’—’’’—’– •’ * ™ R ™ G ™ W ™ G ™ G ™ ™ R ™ G ™ W ™ G ™ G ™ * ’– •’˜’’’˜’– •’˜’’’˜’– •’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’—’’’—’– •’—’’’—’– •’—’’’—’—’’’—’– •’—’’’—’– •’—’’’—’ * W ™ G ™ W ™ W ™ W W ™ G ™ W ™ W ™ W * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’– •’—’’’—’– •’—’’’—’– •’– •’—’’’—’– •’—’’’—’– •’ * ™ R ™ W ™ W ™ W ™ G ™ ™ R ™ W ™ W ™ W ™ G ™ * ’– •’˜’’’˜’– •’˜’’’˜’– •’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’—’’’—’– •’—’’’—’– •’—’’’—’—’’’—’– •’—’’’—’– •’—’’’—’ * G ™ G ™ G ™ W ™ R G ™ G ™ G ™ W ™ R * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * * instead of the correct * * ’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’ * R ™ G ™ R ™ W ™ R ™ R ™ R ™ W ™ R ™ G ™ * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’ * ™ R ™ G ™ W ™ G ™ G ™ G ™ G ™ G ™ W ™ G * ’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’ * W ™ G ™ W ™ W ™ W ™ R ™ W ™ W ™ W ™ G ™ * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’ * ™ R ™ W ™ W ™ W ™ G ™ W ™ G ™ W ™ W ™ W * ’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’ * G ™ G ™ G ™ W ™ G ™ R ™ G ™ W ™ G ™ G ™ * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’ * ™ R ™ R ™ W ™ R ™ G ™ R ™ G ™ R ™ W ™ R * ’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’ * G ™ G ™ G ™ W ™ G ™ R ™ G ™ W ™ G ™ G ™ * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’ * ™ R ™ W ™ W ™ W ™ G ™ W ™ G ™ W ™ W ™ W * ’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * ’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’ * W ™ G ™ W ™ W ™ W ™ R ™ W ™ W ™ W ™ G ™ * ’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’ * ’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’– •’—’’’—’ * ™ R ™ G ™ W ™ G ™ G ™ G ™ G ™ G ™ W ™ G * ’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’– •’˜’’’˜’ * * But 2W 4G 2R with that same weave would produce a 12x12 image, * because W W G G G G R R G G G G tiles correctly. * * -weave 1 is the one depicted above, with a unit cell that looks like * * ’– •’—’’’—’ * ™ ™ * ’– •’˜’’’˜’ * ’—’’’—’– •’ * ™ ™ * ’˜’’’˜’– •’ * * but other weaves are available. At present, the only alternatives * are diagonal weaves like * * ’– •’˜’’’˜’˜’’’˜’– •’– •’˜’’’˜’˜’’’˜’– •’– * ’—’’’—’—’’’—’– •’– •’—’’’—’—’’’—’– •’– •’—’ * ™ ™ ™ ™ ™ ™ ™ ™ * ’˜’’’˜’˜’’’˜’– •’– •’˜’’’˜’˜’’’˜’– •’– •’˜’ * ’—’’’—’– •’– •’—’’’—’—’’’—’– •’– •’—’’’—’—’ * ™ ™ ™ ™ ™ ™ ™ ™ * ’˜’’’˜’– •’– •’˜’’’˜’˜’’’˜’– •’– •’˜’’’˜’˜’ * ’– •’– •’—’’’—’—’’’—’– •’– •’—’’’—’—’’’—’– * ™ ™ ™ ™ ™ ™ ™ ™ ™ * ’– •’– •’˜’’’˜’˜’’’˜’– •’– •’˜’’’˜’˜’’’˜’– * ’– •’—’’’—’—’’’—’– •’– •’—’’’—’—’’’—’– •’– * ™ ™ ™ ™ ™ ™ ™ ™ ™ * ’– •’˜’’’˜’˜’’’˜’– •’– •’˜’’’˜’˜’’’˜’– •’– * ’—’’’—’—’’’—’– •’– •’—’’’—’—’’’—’– •’– •’—’ * ™ ™ ™ ™ ™ ™ ™ ™ * ’˜’’’˜’˜’’’˜’– •’– •’˜’’’˜’˜’’’˜’– •’– •’˜’ * ’—’’’—’– •’– •’—’’’—’—’’’—’– •’– •’—’’’—’—’ * ™ ™ ™ ™ ™ ™ ™ ™ * ’˜’’’˜’– •’– •’˜’’’˜’˜’’’˜’– •’– •’˜’’’˜’˜’ * ’– •’– •’—’’’—’—’’’—’– •’– •’—’’’—’—’’’—’– * ™ ™ ™ ™ ™ ™ ™ ™ ™ * ’– •’– •’˜’’’˜’˜’’’˜’– •’– •’˜’’’˜’˜’’’˜’– * ’– •’—’’’—’—’’’—’– •’– •’—’’’—’—’’’—’– •’– * * (and its converse, slanted the other way), for different over/under * patterns. The above example is obtainable with "-weave 2", with * "-weave -2" slanted the other way; larger versions can be requested * with larger numbers, such as "-weave 3". The default is equivalent * to "-weave 2", which may be specified explicitly. * * The default output size may be overridden with the -size flag. This * effectively tiles an infinite area with the default and then cuts * out the requested size. By default, the output has the beginning * of the specified pattern in its upper-left corner; this may be * changed with -offset, which shifts the extracted rectangle right or * down (for positive arguments) or up or left (for negative * arguments) by the specified number of pixels. For example, * specifying "-offset 2 1" produces output just like what would be * produced without -offset, except that its (0,0) is at what would be * (2,1) in the image without -offset. Thus, the -offset arguments * are, effectively, reduced modulo the default output size. * * A negative argument to -size requests the default output size in * that dimension; thus, the default is equivalent to "-size -1 -1". * * The output file's maxval is, by default, 255. This may be changed * with the -maxval flag. (For PAM files, maxval2 defaults to 255 and * may be changed with -maxval2. If all the colours have zero alpha, * a PPM file is written and -maxval2 is irrelevant.) * * The predefined colours are equivalent to (where M is the maxval) * * K /0/0/0/0 * B /0/0/M/0 * G /0/M/0/0 * C /0/M/M/0 * R /M/0/0/0 * M /M/M/M/0 * Y /M/M/0/0 * W /M/M/M/0 */ #include #include #include extern const char *__progname; typedef struct thread THREAD; typedef struct cletter CLETTER; typedef struct colour COLOUR; struct colour { int r; int g; int b; int a; } ; struct cletter { CLETTER *link; char l; COLOUR c; } ; struct thread { int n; COLOUR c; } ; static int weave = 2; static int size_x = -1; static int size_y = -1; static int offset_x = 0; static int offset_y = 0; static int thread_n = 0; static int thread_a = 0; static THREAD *threads = 0; static THREAD *threadsx; static THREAD *threadsy; static int thread_nx = -1; static int thread_ny = -1; static int maxval = 255; static int maxval2 = 255; static CLETTER *cletters = 0; static int asymmetric = 0; static int def_size_x; static int def_size_y; static int oclass; static int threadcountx; static int threadcounty; static char **wpat; static THREAD **tpatx; static THREAD **tpaty; #define T_PPM 3 #define T_RPPM 6 #define T_PAM 7 #define T_RPAM 8 static CLETTER *lookup_cletter(char c, int create) { CLETTER *cl; for (cl=cletters;cl;cl=cl->link) if (cl->l == c) return(cl); if (create) { cl = malloc(sizeof(CLETTER)); cl->l = c; cl->link = cletters; cletters = cl; } return(cl); } static void define_predefined_colours(void) { CLETTER *cl; const char *s; s = "K000R100G010Y110B001M101C011W111"; while (*s) { cl = lookup_cletter(*s++,1); cl->c.r = (*s++ == '1') ? -1 : 0; cl->c.g = (*s++ == '1') ? -1 : 0; cl->c.b = (*s++ == '1') ? -1 : 0; cl->c.a = 0; } } static int parse_colour(const char *s0, const char *s, COLOUR *c) { __label__ fail; int r; int g; int b; int a; int component(const char *name, int missingok) { unsigned long int uli; int i; char *ep; if (!*s && missingok) return(0); if (*s == '/') s ++; uli = strtoul(s,&ep,0); if (ep == s) { fprintf(stderr,"%s: thread arg `%s': missing %s component\n",__progname,s0,name); goto fail; } i = uli; if (i != uli) { fprintf(stderr,"%s: thread arg `%s': %s component out of range\n",__progname,s0,name); goto fail; } s = ep; return(i); } r = component("red",0); g = component("green",0); b = component("blue",0); a = component("alpha",1); if (*s) { fprintf(stderr,"%s: thread arg `%s': junk after colour\n",__progname,s0); return(1); } c->r = r; c->g = g; c->b = b; c->a = a; return(0); fail: return(1); } static void add_threading(int n, COLOUR c) { if (thread_n >= thread_a) threads = realloc(threads,(thread_a=thread_n+8)*sizeof(*threads)); threads[thread_n++] = (THREAD){.n=n,.c=c}; } static int thread_arg(const char *s0) { const char *s; unsigned long int uli; int i; char *ep; char defc; CLETTER *cl; COLOUR c; if (!strcmp(s0,"/")) { if (thread_nx >= 0) { fprintf(stderr,"%s: extra / in threading list\n",__progname); return(1); } thread_nx = thread_n; return(0); } s = s0; uli = strtoul(s,&ep,0); if (ep == s) uli = 0; i = uli; if ((i < 0) || (i != uli)) { fprintf(stderr,"%s: thread arg `%s' number out of range\n",__progname,s0); return(1); } s = ep; if (! s[0]) { fprintf(stderr,"%s: thread arg `%s' includes no colour\n",__progname,s0); return(1); } if (! s[1]) { cl = lookup_cletter(s[0],0); if (! cl) { fprintf(stderr,"%s: undefined colour `%s'\n",__progname,s0); return(1); } c = cl->c; } else { if (s[0] && (s[1] == '=')) { defc = s[0]; s += 2; } else { defc = '\0'; } if (parse_colour(s0,s,&c)) return(1); if (defc) { cl = lookup_cletter(defc,1); cl->c = c; } } if (i > 0) add_threading(i,c); return(0); } static void handleargs(int ac, char **av) { int skip; int errs; skip = 0; errs = 0; for (ac--,av++;ac;ac--,av++) { if (skip > 0) { skip --; continue; } if (**av != '-') { if (thread_arg(*av)) errs = 1; continue; } if (0) { needarg:; fprintf(stderr,"%s: %s needs a following argument\n",__progname,*av); errs = 1; continue; } #define WANTARG() do { if (++skip >= ac) goto needarg; } while (0) if (!strcmp(*av,"-asymm")) { asymmetric = 1; continue; } if (!strcmp(*av,"-weave")) { WANTARG(); weave = atoi(av[skip]); continue; } if (!strcmp(*av,"-size")) { WANTARG(); size_x = atoi(av[skip]); WANTARG(); size_y = atoi(av[skip]); continue; } if (!strcmp(*av,"-offset")) { WANTARG(); offset_x = atoi(av[skip]); WANTARG(); offset_y = atoi(av[skip]); continue; } if (!strcmp(*av,"-maxval")) { WANTARG(); maxval = atoi(av[skip]); continue; } if (!strcmp(*av,"-maxval2")) { WANTARG(); maxval2 = atoi(av[skip]); continue; } #undef WANTARG fprintf(stderr,"%s: unrecognized option `%s'\n",__progname,*av); errs = 1; } if ((size_x == 0) || (size_y == 0)) { fprintf(stderr,"%s: output dimensions must not be zero\n",__progname); errs = 1; } if (maxval < 1) { fprintf(stderr,"%s: output maxval must be at least 1\n",__progname); errs = 1; } if (maxval2 < 1) { fprintf(stderr,"%s: output maxval2 must be at least 1\n",__progname); errs = 1; } if (errs) exit(1); } static void threading_postarg(void) { int i; if (thread_n < 1) { fprintf(stderr,"%s: no threading given\n",__progname); exit(1); } if (thread_nx < 0) { if (! asymmetric) for (i=thread_n-2;i>=1;i--) add_threading(threads[i].n,threads[i].c); threadsx = threads; threadsy = threads; thread_nx = thread_n; thread_ny = thread_n; threadcountx = 0; for (i=thread_n-1;i>=0;i--) threadcountx += threads[i].n; threadcounty = threadcountx; } else { thread_ny = thread_n - thread_nx; if (thread_nx < 1) { fprintf(stderr,"%s: no X threading given\n",__progname); exit(1); } if (thread_ny < 1) { fprintf(stderr,"%s: no Y threading given\n",__progname); exit(1); } if ((thread_nx > 2) && !asymmetric) { for (i=thread_nx-2;i>0;i--) add_threading(0,(COLOUR){.r=0,.g=0,.b=0,.a=0}); bcopy(&threads[thread_nx],&threads[(thread_nx-1)*2],thread_ny*sizeof(THREAD)); for (i=thread_nx-2;i>0;i--) threads[((thread_nx-1)*2)-i] = threads[i]; thread_nx = (thread_nx - 1) * 2; } if ((thread_ny > 2) && !asymmetric) { for (i=thread_ny-2;i>0;i--) add_threading(threads[thread_nx+i].n,threads[thread_nx+i].c); thread_ny = (thread_ny - 1) * 2; } threadsx = threads; threadsy = threads + thread_nx; threadcountx = 0; for (i=thread_nx-1;i>=0;i--) threadcountx += threadsx[i].n; threadcounty = 0; for (i=thread_ny-1;i>=0;i--) threadcounty += threadsy[i].n; } } static void set_maxvals(void) { int i; THREAD *t; for (i=thread_n-1;i>=0;i--) { t = &threads[i]; if ((t->c.r == -1) || (t->c.r > maxval)) t->c.r = maxval; if ((t->c.g == -1) || (t->c.g > maxval)) t->c.g = maxval; if ((t->c.b == -1) || (t->c.b > maxval)) t->c.b = maxval; if (t->c.a > maxval2) t->c.a = maxval2; } } static unsigned int lcm(unsigned int a, unsigned int b) { unsigned int i; unsigned int j; unsigned int r; i = a; j = b; while (j != 0) { r = i % j; i = j; j = r; } return(a*(b/i)); } static void set_default_size(void) { if (thread_nx < 2) { def_size_x = 1; } else { def_size_x = lcm(threadcountx,abs(weave)*2); } if (size_x < 0) size_x = def_size_x; if (offset_x > 0) offset_x %= def_size_x; if (offset_x < 0) offset_x = (def_size_x - ((-offset_x) % def_size_x)) % def_size_x; if (thread_ny < 2) { def_size_y = 1; } else { def_size_y = lcm(threadcounty,abs(weave)*2); } if (size_y < 0) size_y = def_size_y; if (offset_y > 0) offset_y %= def_size_y; if (offset_y < 0) offset_y = (def_size_y - ((-offset_y) % def_size_y)) % def_size_y; } static void init_output(void) { int i; oclass = (maxval > 255) ? T_PPM : T_RPPM; for (i=thread_n-1;i>=0;i--) { if (threads[i].c.a != 0) { oclass = ((maxval > 255) || (maxval2 > 255)) ? T_PAM : T_RPAM; break; } } switch (oclass) { case T_PPM: printf("P3\n%u %u\n%u\n",size_x,size_y,maxval); break; case T_RPPM: printf("P6\n%u %u\n%u\n",size_x,size_y,maxval); break; case T_PAM: printf("P7\n%u %u\n%u %u\n",size_x,size_y,maxval,maxval2); break; case T_RPAM: printf("P8\n%u %u\n%u %u\n",size_x,size_y,maxval,maxval2); break; default: abort(); break; } } static void gen_weave(void) { int sz; int w; int x; int y; char *vec; int n; w = abs(weave); sz = w * 2; wpat = malloc(sz*sizeof(*wpat)); vec = malloc(sz*sz); for (y=sz-1;y>=0;y--) { wpat[y] = vec; vec += sz; } for (y=sz-1;y>=0;y--) { for (x=sz-1;x>=0;x--) { if (weave < 0) { n = x + sz - y; } else { n = x + y; } wpat[x][y] = ((n % sz) < w); } } } static void gen_thread(void) { int ti; int i; THREAD *t; int j; tpatx = malloc(threadcountx*sizeof(*tpatx)); ti = 0; for (i=0;in;j>0;j--) { if (ti >= threadcountx) abort(); tpatx[ti++] = t; } } if (ti != threadcountx) abort(); tpaty = malloc(threadcounty*sizeof(*tpaty)); ti = 0; for (i=0;in;j>0;j--) { if (ti >= threadcounty) abort(); tpaty[ti++] = t; } } if (ti != threadcounty) abort(); } static void pnmputpixel(COLOUR c) { switch (oclass) { default: abort(); break; case T_PPM: printf("%u %u %u\n",c.r,c.g,c.b); break; case T_RPPM: putchar(c.r); putchar(c.g); putchar(c.b); break; case T_PAM: printf("%u %u %u %u\n",c.r,c.g,c.b,c.a); break; case T_RPAM: putchar(c.r); putchar(c.g); putchar(c.b); putchar(c.a); break; } } static void gen_image(void) { int ix; int iy; int wx; int wy; int tx; int ty; int wn; wn = abs(weave) * 2; wy = offset_y % wn; ty = offset_y % threadcounty; for (iy=0;iyc:tpatx[tx]->c); wx = (wx + 1) % wn; tx = (tx + 1) % threadcountx; } wy = (wy + 1) % wn; ty = (ty + 1) % threadcounty; } } int main(int, char **); int main(int ac, char **av) { define_predefined_colours(); handleargs(ac,av); threading_postarg(); set_maxvals(); set_default_size(); init_output(); gen_weave(); gen_thread(); gen_image(); exit(0); }