#! /usr/bin/gawk -f # Last edited on 2009-02-11 23:07:58 by stolfi BEGIN { usage = ( \ ARGV[0] " \\\n" \ " -v size={NH}x{NV} \\\n" \ " -v cell={CH}x{CV} \\\n" \ " -v spot={SH}x{SV} \\\n" \ " [ -v dark={BOOL} ]" \ ); # Writes a PBM image with approximately {NH} colunms and {NV} rows # of pixels, containing an array of cells, each with {CH} by {CV} pixels. # Each cell has a square spot with {SH} by {SV] pixels. # If {dark} is 0 (the default) the background is white and the # foreground is black. If [dark} is 1 the colors are reversed. max_dim = 4*1024; # Max width or height in pixels. max_thickness = 48; # Max black/white line thickness in pixels. printf "size = %s\n", size > "/dev/stderr"; printf "cell = %s\n", cell > "/dev/stderr"; printf "spot = %s\n", spot > "/dev/stderr"; printf "dark = %s\n", dark > "/dev/stderr"; # Light or dark background? if (dark == "") { dark = 0; } if ((dark != 0) && (dark != 1)) { arg_error(("bad {dark} = \"" dark "\"")); } # Chip dimensions (pixels): nf = split(size, f, "x"); check_size("size", f, nf); nh = f[1] + 0; nv = f[2] + 0; if ((nh < 1) || (nh > max_dim)) { arg_error(("invalid {nh}")); } if ((nv < 1) || (nv > max_dim)) { arg_error(("invalid {nv}")); } nf = split(cell, f, "x"); check_size("cell", f, nf); ch = f[1] + 0; cv = f[2] + 0; nf = split(spot, f, "x"); check_size("spot", f, nf); sh = f[1] + 0; sv = f[2] + 0; split("", pix); # {pix[h,v]} is 0 (white) or 1 (dark). fill_cell(pix,ch,cv,sh,sv,dark); write_image(nh,nv,ch,cv,pix); } function check_size(name,f,nf, i,fi) { # Checks whether {nf} is 2 and {f[1],f[2]} are numbers. if (nf != 2) { arg_error(("invalid {" name "}")); } for (i = 1; i <= 2; i++) { fi = f[i]; if (fi !~ /^[0-9]+$/) { arg_error(("invalid {" name "} coord \"" fi "\"")); } } } function write_image(nh,nv,ch,cv,pix, h,v,dh,dv) { # Write the (plain) PBM image header: printf "P1\n"; printf "%d %d\n", nh, nv; # Write the pixels: for (v = 0; v < nv; v += cv) { # Write another row of cells for (dv = 0; dv < cv; dv++) { # Write another pixel row of the image: for (h = 0; h < nh; h += ch) { # Write another pixel row from the cell: * for (dh = 0; dh < ch; dh++) { printf "%d", pix[dh,dv]; } printf "\n"; } } } fflush(); } function fill_cell(pix,ch,cv,sh,sv,dark, h,v,kh,kv,bh,bv,p) { # Compute the spot offset from the upper right corner: kh = int((ch-sh)/2); kv = int((cv-sv)/2); # Fill the pixels as requested: for (dv = 0; dv < cv; dv++) { for (dh = 0; dh < ch; dh++) { bh = ((dh >= kh) && (dh < (kh + sh))); bv = ((dv >= kv) && (dv < (kv + sv))); p = (bh && bv); pix[dh,dv] = (dark ? 1-p : p); } } } function arg_error(msg) { printf "** %s\n", msg > "/dev/stderr"; printf "usage: %s\n", usage > "/dev/stderr"; exit 1; }